【自然语言处理(NLP)】基于SQuAD的机器阅读理解

news2025/1/2 2:53:17

【自然语言处理(NLP)】基于SQuAD的机器阅读理解


在这里插入图片描述


作者简介:在校大学生一枚,华为云享专家,阿里云专家博主,腾云先锋(TDP)成员,云曦智划项目总负责人,全国高等学校计算机教学与产业实践资源建设专家委员会(TIPCC)志愿者,以及编程爱好者,期待和大家一起学习,一起进步~
.
博客主页ぃ灵彧が的学习日志
.
本文专栏人工智能
.
专栏寄语:若你决定灿烂,山无遮,海无拦
.
在这里插入图片描述

文章目录

  • 【自然语言处理(NLP)】基于SQuAD的机器阅读理解
  • 前言
    • (一)、任务描述
    • (二)、环境配置
  • 一、数据准备
    • (一)、数据集简介
    • (二)、数据处理
    • (三)、处理测试数据的特征
    • (四)、生成训练数据加载器
  • 二、BERT模型配置
  • 三、模型训练
  • 四、模型预测与评估
  • 总结


前言

(一)、任务描述

机器阅读理解(Maching Reading Comprehension,MRC)是一项基于文本的问答任务(Text-QA),也是非常重要和经典的自然语言处理任务之一。机器阅读理解旨在对自然语言文本进行语义理解和推理,并以此完成一些下游的任务。


(二)、环境配置

本示例基于飞桨开源框架2.0版本。

import paddle
import paddle.nn.functional as F
import re
import numpy as np

print(paddle.__version__)

# cpu/gpu环境选择,在 paddle.set_device() 输入对应运行设备。
# device = paddle.set_device('gpu')

输出结果如下图1所示:
在这里插入图片描述


一、数据准备


(一)、数据集简介

斯坦福问答数据集(SQuAD)是一个阅读理解数据集,由维基百科的一系列文章中提出的问题及答案组成,其中每个问题的答案要么对应阅读段落中的一段文本或片段,要么没有答案。


(二)、数据处理

机器阅读理解中的长度限制问题:由于机器阅读理解任务很多篇章都会超过预训练模型的最大长度限制,如BERT模型单条最大处理文本长度为512个字符,因此绝大多数情况下需要做截断或者更换模型结构等操作,本实践使用滑动窗口方式来解决长度问题。


 def prepare_train_features(examples):
        contexts = [examples[i]['context'] for i in range(len(examples))]
        questions = [examples[i]['question'] for i in range(len(examples))]

        tokenized_examples = tokenizer(
            questions,
            contexts,
            stride=doc_stride,
            max_seq_len=max_seq_length)

        # Let's label those examples!
        for i, tokenized_example in enumerate(tokenized_examples):
            # We will label impossible answers with the index of the CLS token.
            input_ids = tokenized_example["input_ids"]
            cls_index = input_ids.index(tokenizer.cls_token_id)

            # The offset mappings will give us a map from token to character position in the original context. This will
            # help us compute the start_positions and end_positions.
            offsets = tokenized_example['offset_mapping']

            # Grab the sequence corresponding to that example (to know what is the context and what is the question).
            sequence_ids = tokenized_example['token_type_ids']

            # One example can give several spans, this is the index of the example containing this span of text.
            sample_index = tokenized_example['overflow_to_sample']
            answers = examples[sample_index]['answers']
            answer_starts = examples[sample_index]['answer_starts']

            # Start/end character index of the answer in the text.
            start_char = answer_starts[0]
            end_char = start_char + len(answers[0])

            # Start token index of the current span in the text.
            token_start_index = 0
            while sequence_ids[token_start_index] != 1:
                token_start_index += 1

            # End token index of the current span in the text.
            token_end_index = len(input_ids) - 1
            while sequence_ids[token_end_index] != 1:
                token_end_index -= 1
            # Minus one more to reach actual text
            token_end_index -= 1

            # Detect if the answer is out of the span (in which case this feature is labeled with the CLS index).
            if not (offsets[token_start_index][0] <= start_char and
                    offsets[token_end_index][1] >= end_char):
                tokenized_examples[i]["start_positions"] = cls_index
                tokenized_examples[i]["end_positions"] = cls_index
            else:
                # Otherwise move the token_start_index and token_end_index to the two ends of the answer.
                # Note: we could go after the last offset if the answer is the last word (edge case).
                while token_start_index < len(offsets) and offsets[
                        token_start_index][0] <= start_char:
                    token_start_index += 1
                tokenized_examples[i]["start_positions"] = token_start_index - 1
                while offsets[token_end_index][1] >= end_char:
                    token_end_index -= 1
                tokenized_examples[i]["end_positions"] = token_end_index + 1

        return tokenized_examples

(三)、处理测试数据的特征


def prepare_validation_features(examples):
        # Tokenize our examples with truncation and maybe padding, but keep the overflows using a stride. This results
        # in one example possible giving several features when a context is long, each of those features having a
        # context that overlaps a bit the context of the previous feature.
        # NOTE: Almost the same functionality as HuggingFace's prepare_train_features function. The main difference is
        # that HugggingFace uses ArrowTable as basic data structure, while we use list of dictionary instead.
        contexts = [examples[i]['context'] for i in range(len(examples))]
        questions = [examples[i]['question'] for i in range(len(examples))]

        tokenized_examples = tokenizer(
            questions,
            contexts,
            stride=doc_stride,
            max_seq_len=max_seq_length)

        # For validation, there is no need to compute start and end positions
        for i, tokenized_example in enumerate(tokenized_examples):
            # Grab the sequence corresponding to that example (to know what is the context and what is the question).
            sequence_ids = tokenized_example['token_type_ids']

            # One example can give several spans, this is the index of the example containing this span of text.
            sample_index = tokenized_example['overflow_to_sample']
            tokenized_examples[i]["example_id"] = examples[sample_index]['id']

            # Set to None the offset_mapping that are not part of the context so it's easy to determine if a token
            # position is part of the context or not.
            tokenized_examples[i]["offset_mapping"] = [
                (o if sequence_ids[k] == 1 else None)
                for k, o in enumerate(tokenized_example["offset_mapping"])
            ]

        return tokenized_examples

(四)、生成训练数据加载器


 if train_file:
            train_ds = load_dataset(task_name, data_files=train_file)
        else:
            train_ds = load_dataset(task_name, splits='train')
        train_ds.map(prepare_train_features, batched=True)
        train_batch_sampler = paddle.io.DistributedBatchSampler(
            train_ds, batch_size=batch_size, shuffle=True)
        train_batchify_fn = lambda samples, fn=Dict({
            "input_ids": Pad(axis=0, pad_val=tokenizer.pad_token_id),
            "token_type_ids": Pad(axis=0, pad_val=tokenizer.pad_token_type_id),
            "start_positions": Stack(dtype="int64"),
            "end_positions": Stack(dtype="int64")
        }): fn(samples)

        train_data_loader = DataLoader(
            dataset=train_ds,
            batch_sampler=train_batch_sampler,
            collate_fn=train_batchify_fn,
            return_list=True)

        num_training_steps = max_steps if max_steps > 0 else len(
            train_data_loader) * num_train_epochs
        num_train_epochs = math.ceil(num_training_steps /
                                     len(train_data_loader))

        lr_scheduler = LinearDecayWithWarmup(
            learning_rate, num_training_steps, warmup_proportion)

        # Generate parameter names needed to perform weight decay.
        # All bias and LayerNorm parameters are excluded.
        decay_params = [
            p.name for n, p in model.named_parameters()
            if not any(nd in n for nd in ["bias", "norm"])
        ]
        optimizer = paddle.optimizer.AdamW(
            learning_rate=lr_scheduler,
            epsilon=adam_epsilon,
            parameters=model.parameters(),
            weight_decay=weight_decay,
            apply_decay_param_fun=lambda x: x in decay_params)
        criterion = CrossEntropyLossForSQuAD()

        global_step = 0
        tic_train = time.time()
        for epoch in range(num_train_epochs):
            for step, batch in enumerate(train_data_loader):
                global_step += 1
                input_ids, token_type_ids, start_positions, end_positions = batch
                logits = model(
                    input_ids=input_ids, token_type_ids=token_type_ids)
                loss = criterion(logits, (start_positions, end_positions))

                if global_step % logging_steps == 0:
                    print(
                        "global step %d, epoch: %d, batch: %d, loss: %f, speed: %.2f step/s"
                        % (global_step, epoch + 1, step + 1, loss,
                           logging_steps / (time.time() - tic_train)))
                    tic_train = time.time()
                loss.backward()
                optimizer.step()
                lr_scheduler.step()
                optimizer.clear_grad()

                if global_step % save_steps == 0 or global_step == num_training_steps:
                    if rank == 0:
                        output_dir_ = os.path.join(output_dir,
                                                  "model_%d" % global_step)
                        if not os.path.exists(output_dir_):
                            os.makedirs(output_dir_)
                        # need better way to get inner model of DataParallel
                        model_to_save = model._layers if isinstance(
                            model, paddle.DataParallel) else model
                        model_to_save.save_pretrained(output_dir_)
                        tokenizer.save_pretrained(output_dir_)
                        print('Saving checkpoint to:', output_dir_)
                    if global_step == num_training_steps:
                        break

二、BERT模型配置

本实践使用BERT预训练模型进行微调,该模型对应PaddleNLP中的BertForQuestionAnswering模型,与BERT关联的Tokenizer为BertTokenizer,此处我们使用BERT模型进行微调,并且对所有英文字母都进行小写处理,调用model_class.from_pretrained(model_name_or_path)时,若本地没有下载预训练的参数,会首先下载参数:


 model_type='bert'
    model_name_or_path='bert-base-chinese'
    task_name = task_name.lower()
    model_type = model_type.lower()
    model_class, tokenizer_class = MODEL_CLASSES[model_type]
    tokenizer = tokenizer_class.from_pretrained(model_name_or_path)

三、模型训练


@paddle.no_grad()
def evaluate(model, data_loader):
    model.eval()

    all_start_logits = []
    all_end_logits = []
    tic_eval = time.time()

    for batch in data_loader:
        input_ids, token_type_ids = batch
        start_logits_tensor, end_logits_tensor = model(input_ids,
                                                       token_type_ids)

        for idx in range(start_logits_tensor.shape[0]):
            if len(all_start_logits) % 1000 == 0 and len(all_start_logits):
                print("Processing example: %d" % len(all_start_logits))
                print('time per 1000:', time.time() - tic_eval)
                tic_eval = time.time()

            all_start_logits.append(start_logits_tensor.numpy()[idx])
            all_end_logits.append(end_logits_tensor.numpy()[idx])

    all_predictions, _, _ = compute_prediction(
        data_loader.dataset.data, data_loader.dataset.new_data,
        (all_start_logits, all_end_logits), False, n_best_size,
        max_answer_length)

    # Can also write all_nbest_json and scores_diff_json files if needed
    with open('prediction.json', "w", encoding='utf-8') as writer:
        writer.write(
            json.dumps(
                all_predictions, ensure_ascii=False, indent=4) + "\n")

    squad_evaluate(
        examples=data_loader.dataset.data,
        preds=all_predictions,
        is_whitespace_splited=False)

    model.train()

四、模型预测与评估



class CrossEntropyLossForSQuAD(paddle.nn.Layer):
    def __init__(self):
        super(CrossEntropyLossForSQuAD, self).__init__()

    def forward(self, y, label):
        start_logits, end_logits = y
        start_position, end_position = label
        start_position = paddle.unsqueeze(start_position, axis=-1)
        end_position = paddle.unsqueeze(end_position, axis=-1)
        start_loss = paddle.nn.functional.cross_entropy(
            input=start_logits, label=start_position)
        end_loss = paddle.nn.functional.cross_entropy(
            input=end_logits, label=end_position)
        loss = (start_loss + end_loss) / 2
        return loss


def run():
    task_name='dureader_robust'
    train_file=None
    predict_file=None
    model_type='bert'
    model_name_or_path='bert-base-chinese'
    output_dir='models'
    max_seq_length=128
    batch_size=8
    learning_rate=5e-5
    weight_decay=0.0
    adam_epsilon=1e-8
    ax_grad_norm=1.0
    num_train_epochs=3
    max_steps=-1
    warmup_proportion=0.0
    logging_steps=200
    save_steps=200
    seed=42
    device='gpu'
    doc_stride =128
    n_best_size =20
    max_query_length=64
    max_answer_length=30
    do_lower_case=True
    verbose=True
    do_train=True
    do_predict=True
    paddle.set_device(device)
    if paddle.distributed.get_world_size() > 1:
        paddle.distributed.init_parallel_env()
    rank = paddle.distributed.get_rank()
    task_name='dureader_robust'
    model_type='bert'
    model_name_or_path='bert-base-chinese'
    task_name = task_name.lower()
    model_type = model_type.lower()
    model_class, tokenizer_class = MODEL_CLASSES[model_type]
    tokenizer = tokenizer_class.from_pretrained(model_name_or_path)
    set_seed(1024)
    if rank == 0:
        if os.path.exists(model_name_or_path):
            print("init checkpoint from %s" % model_name_or_path)

    model = model_class.from_pretrained(model_name_or_path)

    if paddle.distributed.get_world_size() > 1:
        model = paddle.DataParallel(model)

    def prepare_train_features(examples):
        contexts = [examples[i]['context'] for i in range(len(examples))]
        questions = [examples[i]['question'] for i in range(len(examples))]

        tokenized_examples = tokenizer(
            questions,
            contexts,
            stride=doc_stride,
            max_seq_len=max_seq_length)

        # Let's label those examples!
        for i, tokenized_example in enumerate(tokenized_examples):
            # We will label impossible answers with the index of the CLS token.
            input_ids = tokenized_example["input_ids"]
            cls_index = input_ids.index(tokenizer.cls_token_id)

            # The offset mappings will give us a map from token to character position in the original context. This will
            # help us compute the start_positions and end_positions.
            offsets = tokenized_example['offset_mapping']

            # Grab the sequence corresponding to that example (to know what is the context and what is the question).
            sequence_ids = tokenized_example['token_type_ids']

            # One example can give several spans, this is the index of the example containing this span of text.
            sample_index = tokenized_example['overflow_to_sample']
            answers = examples[sample_index]['answers']
            answer_starts = examples[sample_index]['answer_starts']

            # Start/end character index of the answer in the text.
            start_char = answer_starts[0]
            end_char = start_char + len(answers[0])

            # Start token index of the current span in the text.
            token_start_index = 0
            while sequence_ids[token_start_index] != 1:
                token_start_index += 1

            # End token index of the current span in the text.
            token_end_index = len(input_ids) - 1
            while sequence_ids[token_end_index] != 1:
                token_end_index -= 1
            # Minus one more to reach actual text
            token_end_index -= 1

            # Detect if the answer is out of the span (in which case this feature is labeled with the CLS index).
            if not (offsets[token_start_index][0] <= start_char and
                    offsets[token_end_index][1] >= end_char):
                tokenized_examples[i]["start_positions"] = cls_index
                tokenized_examples[i]["end_positions"] = cls_index
            else:
                # Otherwise move the token_start_index and token_end_index to the two ends of the answer.
                # Note: we could go after the last offset if the answer is the last word (edge case).
                while token_start_index < len(offsets) and offsets[
                        token_start_index][0] <= start_char:
                    token_start_index += 1
                tokenized_examples[i]["start_positions"] = token_start_index - 1
                while offsets[token_end_index][1] >= end_char:
                    token_end_index -= 1
                tokenized_examples[i]["end_positions"] = token_end_index + 1

        return tokenized_examples

    if do_train:
        
        if train_file:
            train_ds = load_dataset(task_name, data_files=train_file)
        else:
            train_ds = load_dataset(task_name, splits='train')
        train_ds.map(prepare_train_features, batched=True)
        train_batch_sampler = paddle.io.DistributedBatchSampler(
            train_ds, batch_size=batch_size, shuffle=True)
        train_batchify_fn = lambda samples, fn=Dict({
            "input_ids": Pad(axis=0, pad_val=tokenizer.pad_token_id),
            "token_type_ids": Pad(axis=0, pad_val=tokenizer.pad_token_type_id),
            "start_positions": Stack(dtype="int64"),
            "end_positions": Stack(dtype="int64")
        }): fn(samples)

        train_data_loader = DataLoader(
            dataset=train_ds,
            batch_sampler=train_batch_sampler,
            collate_fn=train_batchify_fn,
            return_list=True)

        num_training_steps = max_steps if max_steps > 0 else len(
            train_data_loader) * num_train_epochs
        num_train_epochs = math.ceil(num_training_steps /
                                     len(train_data_loader))

        lr_scheduler = LinearDecayWithWarmup(
            learning_rate, num_training_steps, warmup_proportion)

        # Generate parameter names needed to perform weight decay.
        # All bias and LayerNorm parameters are excluded.
        decay_params = [
            p.name for n, p in model.named_parameters()
            if not any(nd in n for nd in ["bias", "norm"])
        ]
        optimizer = paddle.optimizer.AdamW(
            learning_rate=lr_scheduler,
            epsilon=adam_epsilon,
            parameters=model.parameters(),
            weight_decay=weight_decay,
            apply_decay_param_fun=lambda x: x in decay_params)
        criterion = CrossEntropyLossForSQuAD()

        global_step = 0
        tic_train = time.time()
        for epoch in range(num_train_epochs):
            for step, batch in enumerate(train_data_loader):
                global_step += 1
                input_ids, token_type_ids, start_positions, end_positions = batch
                logits = model(
                    input_ids=input_ids, token_type_ids=token_type_ids)
                loss = criterion(logits, (start_positions, end_positions))

                if global_step % logging_steps == 0:
                    print(
                        "global step %d, epoch: %d, batch: %d, loss: %f, speed: %.2f step/s"
                        % (global_step, epoch + 1, step + 1, loss,
                           logging_steps / (time.time() - tic_train)))
                    tic_train = time.time()
                loss.backward()
                optimizer.step()
                lr_scheduler.step()
                optimizer.clear_grad()

                if global_step % save_steps == 0 or global_step == num_training_steps:
                    if rank == 0:
                        output_dir_ = os.path.join(output_dir,
                                                  "model_%d" % global_step)
                        if not os.path.exists(output_dir_):
                            os.makedirs(output_dir_)
                        # need better way to get inner model of DataParallel
                        model_to_save = model._layers if isinstance(
                            model, paddle.DataParallel) else model
                        model_to_save.save_pretrained(output_dir_)
                        tokenizer.save_pretrained(output_dir_)
                        print('Saving checkpoint to:', output_dir_)
                    if global_step == num_training_steps:
                        break

    def prepare_validation_features(examples):
        # Tokenize our examples with truncation and maybe padding, but keep the overflows using a stride. This results
        # in one example possible giving several features when a context is long, each of those features having a
        # context that overlaps a bit the context of the previous feature.
        # NOTE: Almost the same functionality as HuggingFace's prepare_train_features function. The main difference is
        # that HugggingFace uses ArrowTable as basic data structure, while we use list of dictionary instead.
        contexts = [examples[i]['context'] for i in range(len(examples))]
        questions = [examples[i]['question'] for i in range(len(examples))]

        tokenized_examples = tokenizer(
            questions,
            contexts,
            stride=doc_stride,
            max_seq_len=max_seq_length)

        # For validation, there is no need to compute start and end positions
        for i, tokenized_example in enumerate(tokenized_examples):
            # Grab the sequence corresponding to that example (to know what is the context and what is the question).
            sequence_ids = tokenized_example['token_type_ids']

            # One example can give several spans, this is the index of the example containing this span of text.
            sample_index = tokenized_example['overflow_to_sample']
            tokenized_examples[i]["example_id"] = examples[sample_index]['id']

            # Set to None the offset_mapping that are not part of the context so it's easy to determine if a token
            # position is part of the context or not.
            tokenized_examples[i]["offset_mapping"] = [
                (o if sequence_ids[k] == 1 else None)
                for k, o in enumerate(tokenized_example["offset_mapping"])
            ]

        return tokenized_examples

    if do_predict and rank == 0:

        if predict_file:
            dev_ds = load_dataset(task_name, data_files=predict_file)
        else:
            dev_ds = load_dataset(task_name, splits='dev')

        dev_ds.map(prepare_validation_features, batched=True)
        dev_batch_sampler = paddle.io.BatchSampler(
            dev_ds, batch_size=batch_size, shuffle=False)

        dev_batchify_fn = lambda samples, fn=Dict({
            "input_ids": Pad(axis=0, pad_val=tokenizer.pad_token_id),
            "token_type_ids": Pad(axis=0, pad_val=tokenizer.pad_token_type_id)
        }): fn(samples)

        dev_data_loader = DataLoader(
            dataset=dev_ds,
            batch_sampler=dev_batch_sampler,
            collate_fn=dev_batchify_fn,
            return_list=True)

        evaluate(model, dev_data_loader)

部分输出结果如下图2所示:

在这里插入图片描述


总结

本系列文章内容为根据清华社出版的《自然语言处理实践》所作的相关笔记和感悟,其中代码均为基于百度飞桨开发,若有任何侵权和不妥之处,请私信于我,定积极配合处理,看到必回!!!

最后,引用本次活动的一句话,来作为文章的结语~( ̄▽ ̄~)~:

学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。

ps:更多精彩内容还请进入本文专栏人工智能,进行查看,欢迎大家支持与指教啊~( ̄▽ ̄~)~

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/50877.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue3和vue2组件风格对比

Vue3 组合式 API&#xff08;Composition API&#xff09; 主要用于在大型组件中提高代码逻辑的可复用性。 传统的组件随着业务复杂度越来越高&#xff0c;代码量会不断的加大&#xff0c;整个代码逻辑都不易阅读和理解。 Vue3 使用组合式 API 的地方为 setup。 在 setup 中…

无代码资讯|SAP发布低代码平台;钉钉低代码应用数破500万;轻流举办无代码城市论坛......

栏目导读&#xff1a;无代码资讯栏目从全球视角出发&#xff0c;带您了解无代码相关最新资讯。 TOP3 大事件 1、SAP 召开“SAP TechEd ”大会&#xff0c;发布低代码平台 SAP Build 11 月 15 日-16 日&#xff0c;全球企服巨头 SAP 在美国拉斯维加斯召开“2022 SAP TechEd”产…

MySQL是如何实现事务的隔离级别

MySQL是如何实现事务的隔离级别 - 游生 - 博客园 摘要 本文旨在了解MySQL InnoDB引擎如何支持事务的隔离级别。 文章主要内容分两个部分。 第一部分阐述数据库的并发问题以及为之产生的ANSI SQL 标准隔离级别。 第二部分根据 MySQL 官方文档解释 InnoDB 是如何支持这些隔离…

关于python中自带的类似postman的工具

关于python中自带的类似postman的工具 1.新建一个http 请求&#xff1a; 2.添加请求方式 2.1程序运行 验证数据的运行&#xff1a; 1.post数据添加验证

打造无证服务化:这个政务服务平台有点不一样

摘要&#xff1a;华为云携手深圳市华傲数据技术有限公司针对“数字政府建设”与“数字经济发展”两大场景&#xff0c;打造华傲可信政务区块链解决方案。本文分享自华为云社区《华为云携手华傲数据打造“无证服务”政务服务平台》&#xff0c;作者&#xff1a;灰灰哒 。 当前&…

xray扫描器的使用长亭xray被动扫描

长亭xray被动扫描为了实现点到哪里扫到哪里&#xff0c;用长亭xray配合burp suite插件 插件名为Passive Scan Client GitHub - lilifengcode/Burpsuite-Plugins-Usage: Burpsuite-Plugins-Usage 就用默认端口1664就行&#xff0c;把浏览器代理设成127.0.01 &#xff1a; 1664…

【Pandas数据处理100例】(八十七):Pandas使用get_dummies构建哑变量

前言 大家好,我是阿光。 本专栏整理了《Pandas数据分析处理》,内包含了各种常见的数据处理,以及Pandas内置函数的使用方法,帮助我们快速便捷的处理表格数据。 正在更新中~ ✨ 🚨 我的项目环境: 平台:Windows10语言环境:python3.7编译器:PyCharmPandas版本:1.3.5N…

<学习笔记>从零开始自学Python-之-web应用框架Django( 十一)用户系统和身份验证

用户系统是现代网站的重要组成部分&#xff0c;对用户进行分组权限管理是非常必要的。 Django内置了一套用户和身份验证系统&#xff0c;不用太多代码开发就可以使用这个系统。 Django 的身份验证系统包括&#xff1a; • 用户 • 权限&#xff1a;二元&#xff08;是或否&…

Unity游戏Mod/插件制作教程05 - 插件实例2: 简单功能实现

这一次的教程进行一个小小的功能实现&#xff0c;完整的制作一个插件。以Mirror这个游戏为例&#xff0c;插件的目标是当玩家按下空格时&#xff0c;有一定概率为玩家增加金钱&#xff0c;或者扣除玩家金钱。概率、增加的金钱、扣除的金钱都由配置文件决定。 使用dnSpy查找金钱…

【SQL】数据库事务

【SQL】数据库事务事物的ACID特性事务的状态显式事务隐式事务事务的使用举例SQL中的四种隔离级别MySQL中的隔离级别如何设置事务的隔离级别innodb默认支持事务事务是一组逻辑操作单元&#xff0c;使数据从一种状态转变到另一种状态事物的ACID特性 原子性&#xff08;atomicity…

Java搭建宝塔部署实战毕设项目springboot车险理赔管理系统源码

大家好啊&#xff0c;我是测评君&#xff0c;欢迎来到web测评。 本期给大家带来一套Java开发的毕业设计项目springboot车险理赔管理系统源码。 技术架构 技术框架&#xff1a;SpringBoot mybatis bootstrap jquery mysql5.7运行环境&#xff1a;jdk8 nginx1.20 tomcat9 …

QT学习笔记(六)——QT弹出对话框并在主窗口调用对话框的信息

QT弹出对话框并在主窗口调用对话框的信息&#xff0c;显示影像 最近封控&#xff0c;大部分时间都在自己学习写代码&#xff0c;有点feel 了哈&#xff0c;自己摸出来一个简单的qt 界面&#xff0c;也实现了自己想要的功能。本篇博客主要记录一下&#xff0c;如何弹出对话框&a…

[附源码]SSM计算机毕业设计疫情期间物资分派管理系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

@Accessors 注解作用

文章目录前言一、Accessors 源码二、Accessors 属性说明1、fluent 属性2、chain 属性3、prefix 属性前言 在最近的工作中&#xff0c;看到 Accessors(chain true) 这样的注解&#xff0c;上网查询了下&#xff0c;他是 lombok 插件包中的一个注解&#xff0c;那么它是什么意思…

如何快速实现一个颜色选择器

在做前端界面开发的时候&#xff0c;遇到需要改变颜色的需求&#xff0c;就需要使用颜色选择器。 针对这个问题&#xff0c;第一想法&#xff0c;自然是H5提供了input color&#xff0c;可以实现。但不出意外的&#xff0c;IE并不支持。而且&#xff0c;chrome的实现方式和fire…

[附源码]Python计算机毕业设计Django个人博客系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

【java】输入输出流

文章目录标准输入流标准输出流字节打印流字符打印流案例--复制java文件&#xff08;文件打印流版本&#xff09;对象序列化流序列化流反序列化流serialVersionID&transientProperties作为Map集合的使用Properties作为集合的特有方法Properties与IO流相结合的方法案例--游戏…

必备模块知识——超声波传感器

一、超声波传感器 1、什么是超声波 人们能听到声音是由于物体振动产生的&#xff0c;它的频率在20HZ-20KHZ范围内&#xff0c;超过20KHZ称为超声波&#xff0c;低于20HZ的称为次声波。常用的超声波频率为几十KHZ-几十MHZ。 2、什么是超声波传感器&#xff08;常用的HC-SR04超…

基于PHP+MySQL教室预约管理系统的设计与实现

随着我国国民教育的提高,大学生的数量一直在不断的增加,根据网络资料的查询,发现2012年的大学生人数为600万,这是一个不小的数量,说明了我国教育的进步是巨大的。但是问题也随之产生,每年如此多的大学生就需要大学不断的扩建,可是还是不能满足如此多的学生对教室的使用,所以如何…

【学习笔记】深度学习入门:基于Python的理论与实现-与学习相关的技巧

CONTENTS六、与学习相关的技巧6.1 参数的更新6.2 权重的初始值6.3 Batch Normalization6.4 正则化6.5 超参数的验证六、与学习相关的技巧 6.1 参数的更新 神经网络的学习的目的是找到使损失函数的值尽可能小的参数。这是寻找最优参数的问题&#xff0c;解决这个问题的过程称为…