LLM - DataCollatorForLanguageModeling 样本生成 by transformers

目录

一.引言

二.生成样本 By API

1.样本处理样式

2.DataCollatorForLanguageModeling

2.1 样本准备

2.2 API 生成

三.生成样本 By DIY

1.样本准备

2.data_colloator 实现

3.使用自定义 data_colloator

四.总结


一.引言

前面我们讲了 Baichuan7B 的 lora 微调步骤,我们在 QA 基础上构建了样本集并训练,但是细心的同学肯定发现我们原始样本中只给出了 input_ids 但是没有给出 labels,本文我们简单看下 data_collator 如何生成样本 label 并自定义实现一个简单的 data_collator。

二.生成样本 By API

1.样本处理样式

def preprocess(tokenizer, config, example, max_seq_length, prompt_key, target_key):
    prompt = example[prompt_key]
    target = example[target_key]
    prompt_ids = tokenizer.encode(prompt, max_length=max_seq_length, truncation=True)
    target_ids = tokenizer.encode(target, max_length=max_seq_length, truncation=True, add_special_tokens=False)
    # 最终还是将 instruction 的输入输出都拼在一起,使用经典的 causal-LM 的 next word prediction 方式来训练
    input_ids = prompt_ids + target_ids + [config.eos_token_id] # EOS 用于标识句子结束
    return {"input_ids": input_ids, "seq_len": len(prompt_ids)}

首先加载 tokenizer 对 Q 和 A 分别 token 获取对应 Q_ids 和 A_ids:

Q: 请计算:39 * 0 = 什么?
A: 这是简单的乘法运算,39乘以0得到的是0
TokenQ: [31106, 15875, 77, 57, 53, 31159, 53, 60, 58, 31135, 6787, 6775, 81]
TokenA: [31106, 3908, 14313, 31640, 31257, 31481, 31742, 72, 57, 53, 31640, 31187, 53, 60, 58, 9323, 31178, 52, 79, 54, 59, 56]

获取 ids 后,会直接将 Q_ids A_ids 连接并在尾部增加 eos_token_id 标识当前句子结束,这里 eos_token_id = 2,合并后的 input_ids 如下:

input_ids = [31106, 15875, 77, 57, 53, 31159, 53, 60, 58, 31135, 6787, 6775, 81, 31106, 3908, 14313, 31640, 31257, 31481,
           31742, 72, 57, 53, 31640, 31187, 53, 60, 58, 9323, 31178, 52, 79, 54, 59, 56, 2]

除此之外,json 里还用 seq_len 记录了 prompt_ids 即 Q_ids 的长度:

json = {"input_ids": input_ids, "seq_len": 13}

2.DataCollatorForLanguageModeling

data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer,mlm=False)
    # 初始化 trainer, 此处报错: NotImplementedError: Cannot copy out of meta tensor; no data!
    trainer = ModifiedTrainer(
        model=model,
        train_dataset=dataset,
        args=training_args,
        callbacks=[TensorBoardCallback(writer)], # 回调将训练情况写入 tensorboard
        data_collator=data_collator,
    )
    trainer.train()

上文中我们把 json 样本生成的 Dataset 和 DataCollatorForLanguageModeling 直接传给了 Trainer 训练,但是样本中并没有 labels,于是就在想没有 labels 怎么梯度回传,下面用 DataCollatorForLanguageModeling API 看下 data_collator 使用后生成的数据样式。

2.1 样本准备

这里我直接将第一步 tokenizer 后的样本手动生成两个 json 测试后续流程:

# p: [31106, 15875, 77, 57, 53, 31159, 53, 60, 58, 31135, 6787, 6775, 81]
# t: [31106, 3908, 14313, 31640, 31257, 31481, 31742, 72, 57, 53, 31640, 31187, 53, 60, 58, 9323, 31178, 52, 79, 54, 59, 56]
sample1 = [31106, 15875, 77, 57, 53, 31159, 53, 60, 58, 31135, 6787, 6775, 81, 31106, 3908, 14313, 31640, 31257, 31481,
           31742, 72, 57, 53, 31640, 31187, 53, 60, 58, 9323, 31178, 52, 79, 54, 59, 56, 2]

# p: [31106, 33370, 5629, 16927, 54, 56, 31179, 11002, 72, 31526, 31342, 8835, 31221, 31423, 7156, 55, 31396, 31222, 33370, 31604, 72, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 6851, 11002, 75]
# t: [31106, 33370, 5629, 16927, 54, 56, 31179, 11002, 72, 8835, 31221, 31423, 55, 31396, 31222, 33370, 31604, 72, 2926, 31415, 31396, 31222, 33370, 1231, 31221, 11254, 11002, 31380, 1522, 31482, 11002, 31380, 31640, 31187, 31222, 33370, 31135, 31396, 31380, 73, 5, 54, 56, 34399, 55, 31191, 60, 5, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 60, 31179, 11002, 73, 2122, 72, 6787, 31161, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 60, 31179, 11002, 73]
sample2 = [31106, 33370, 5629, 16927, 54, 56, 31179, 11002, 72, 31526, 31342, 8835, 31221, 31423, 7156, 55, 31396,
           31222, 33370, 31604, 72, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 6851, 11002, 75, 31106, 33370, 5629,
           16927, 54, 56, 31179, 11002, 72, 8835, 31221, 31423, 55, 31396, 31222, 33370, 31604, 72, 2926, 31415, 31396,
           31222, 33370, 1231, 31221, 11254, 11002, 31380, 1522, 31482, 11002, 31380, 31640, 31187, 31222, 33370, 31135,
           31396, 31380, 73, 5, 54, 56, 34399, 55, 31191, 60, 5, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 60,
           31179, 11002, 73, 2122, 72, 6787, 31161, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 60, 31179, 11002,
           73, 2]

json1 = {"input_ids": sample1, "seq_len": 13}
json2 = {"input_ids": sample2, "seq_len": 31}

features = [json1, json2]

每个 json 的 input_ids 都遵循 Q_ids + A_ids + [SEP] 即 Prompt_ids + Target_ids + [SEP] 的规则生成。

2.2 API 生成

from transformers import AutoTokenizer
from transformers import DataCollatorForLanguageModeling

model_checkpoint = "/model/baichuan-7B"
tokenizer = AutoTokenizer.from_pretrained(model_checkpoint, trust_remote_code=True)
tokenizer.pad_token = tokenizer.unk_token
data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer,mlm=False)

features = [json1, json2]
batch = data_collator(features)

print(batch)

调用 API 生成一个 Batch 对应的大 json 共包含 4 个 key:

• attention_mask

对于基于 mask 的语言任务例如 Bert,data_collator 可以帮助生成掩码标签。对于 sample1 其长度较短,所以后面的 PAD_TOKEN 部分的 mask 均为 0,而 sample2 的长度为所有样本中最长的且小于 max_length,所以其 mask 均为 1。

'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
		 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 
		 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
		 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])

• input_ids

与上面同理,data_collator 会就算当前 batch 样本中的 max_length,对于不足 max_length 的样本进行补齐的 padding 操作,所以 sample1 的样本补了很多 padding,sample2 正常。

'input_ids': tensor([[31106, 15875,    77,    57,    53, 31159,    53,    60,    58, 31135,
          6787,  6775,    81, 31106,  3908, 14313, 31640, 31257, 31481, 31742,
            72,    57,    53, 31640, 31187,    53,    60,    58,  9323, 31178,
            52,    79,    54,    59,    56,     2,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
             0,     0,     0,     0,     0,     0],
        [31106, 33370,  5629, 16927,    54,    56, 31179, 11002,    72, 31526,
         31342,  8835, 31221, 31423,  7156,    55, 31396, 31222, 33370, 31604,
            72, 31415, 31396, 31222, 33370,  1231, 31221, 31195,  6851, 11002,
            75, 31106, 33370,  5629, 16927,    54,    56, 31179, 11002,    72,
          8835, 31221, 31423,    55, 31396, 31222, 33370, 31604,    72,  2926,
         31415, 31396, 31222, 33370,  1231, 31221, 11254, 11002, 31380,  1522,
         31482, 11002, 31380, 31640, 31187, 31222, 33370, 31135, 31396, 31380,
            73,     5,    54,    56, 34399,    55, 31191,    60,     5, 31415,
         31396, 31222, 33370,  1231, 31221, 31195,    60, 31179, 11002,    73,
          2122,    72,  6787, 31161, 31415, 31396, 31222, 33370,  1231, 31221,
         31195,    60, 31179, 11002,    73,     2]])

Tips:

这里 pad 的 0 和 mask 的 0 需要区分,这里 padding 为 0 是因为我们定义了 pad_token = unk_token,而 unk_token = <unk> 经过 tokenizer encode 后得到的是 [0]。

code=tokenizer.encode(tokenizer.pad_token, max_length=10000, truncation=True)
print('pad', tokenizer.unk_token, 'token', code)
=> pad <unk> token [0]

• seq_len

这个很好理解,一个 batch 内的多个样本,每个样本的 prompt_id 的长度即 Q_id 的长度。这个长度主要用于 batch 内判断 longest 最长的序列是多长,从而对短的样本进行 padding,保证进入深度模型网络的样本维度一致。

'seq_len': tensor([13, 31])

• labels

'labels': tensor([[31106, 15875,  77,  57,  53, 31159,  53,  60,    58, 31135,
          6787,  6775,    81, 31106,  3908, 14313, 31640, 31257, 31481, 31742,
            72,    57,    53, 31640, 31187,    53,    60,    58,  9323, 31178,
            52,    79,    54,    59,    56,     2,  -100,  -100,  -100,  -100,
          -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,
          -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,
          -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,
          -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,
          -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,
          -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,
          -100,  -100,  -100,  -100,  -100,  -100],
        [31106, 33370,  5629, 16927,    54,    56, 31179, 11002,    72, 31526,
         31342,  8835, 31221, 31423,  7156,    55, 31396, 31222, 33370, 31604,
            72, 31415, 31396, 31222, 33370,  1231, 31221, 31195,  6851, 11002,
            75, 31106, 33370,  5629, 16927,    54,    56, 31179, 11002,    72,
          8835, 31221, 31423,    55, 31396, 31222, 33370, 31604,    72,  2926,
         31415, 31396, 31222, 33370,  1231, 31221, 11254, 11002, 31380,  1522,
         31482, 11002, 31380, 31640, 31187, 31222, 33370, 31135, 31396, 31380,
            73,     5,    54,    56, 34399,    55, 31191,    60,     5, 31415,
         31396, 31222, 33370,  1231, 31221, 31195,    60, 31179, 11002,    73,
          2122,    72,  6787, 31161, 31415, 31396, 31222, 33370,  1231, 31221,
         31195,    60, 31179, 11002,    73,     2]])}

最后一个 key 是 labels,这里也可以解决我们前面的疑惑了,为什么样本里只有 input_ids 和 seq_len,但是经过 data_collator 处理送到 trainer 可以正常训练,这里的 label 对应的是 QA 里 A 的 token ids 即 target ids,以第一个 sample 为例,第一个 sample 的 A ids 为:

[31106, 3908, 14313, 31640, 31257, 31481, 31742, 72, 57, 53, 31640, 31187, 53, 60, 58, 9323, 31178, 52, 79, 54, 59, 56] + [2]

最后的 [2] 与前面 <unk> 类似,eos_token 后编码为 [2]:

code=tokenizer.encode(tokenizer.eos_token, max_length=10000, truncation=True)
print('eos', tokenizer.eos_token, 'token', code)
=> eos </s> token [2]

三.生成样本 By DIY

上面使用 Transformer API 实现了 {"input_ids":  xxx, "seq_len": xxx} 形式的数据解析与样本生成,下面我们参考上面逻辑自定义一版 data_collator。首先整理一下思路:

input_ids = Q_ids + A_ids + [SEP]_ids

seq_len = Q_ids.length

labels =  if (max_length) A_ids else A_ids + padding * n

根据 A_ids 的长度判断是否是 longest,然后决定是否补齐 padding 从而生成对应 Label。

1.样本准备

# p: [31106, 15875, 77, 57, 53, 31159, 53, 60, 58, 31135, 6787, 6775, 81]
# t: [31106, 3908, 14313, 31640, 31257, 31481, 31742, 72, 57, 53, 31640, 31187, 53, 60, 58, 9323, 31178, 52, 79, 54, 59, 56]
sample1 = [31106, 15875, 77, 57, 53, 31159, 53, 60, 58, 31135, 6787, 6775, 81, 31106, 3908, 14313, 31640, 31257, 31481,
           31742, 72, 57, 53, 31640, 31187, 53, 60, 58, 9323, 31178, 52, 79, 54, 59, 56, 2]

# p: [31106, 33370, 5629, 16927, 54, 56, 31179, 11002, 72, 31526, 31342, 8835, 31221, 31423, 7156, 55, 31396, 31222, 33370, 31604, 72, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 6851, 11002, 75]
# t: [31106, 33370, 5629, 16927, 54, 56, 31179, 11002, 72, 8835, 31221, 31423, 55, 31396, 31222, 33370, 31604, 72, 2926, 31415, 31396, 31222, 33370, 1231, 31221, 11254, 11002, 31380, 1522, 31482, 11002, 31380, 31640, 31187, 31222, 33370, 31135, 31396, 31380, 73, 5, 54, 56, 34399, 55, 31191, 60, 5, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 60, 31179, 11002, 73, 2122, 72, 6787, 31161, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 60, 31179, 11002, 73]
sample2 = [31106, 33370, 5629, 16927, 54, 56, 31179, 11002, 72, 31526, 31342, 8835, 31221, 31423, 7156, 55, 31396,
           31222, 33370, 31604, 72, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 6851, 11002, 75, 31106, 33370, 5629,
           16927, 54, 56, 31179, 11002, 72, 8835, 31221, 31423, 55, 31396, 31222, 33370, 31604, 72, 2926, 31415, 31396,
           31222, 33370, 1231, 31221, 11254, 11002, 31380, 1522, 31482, 11002, 31380, 31640, 31187, 31222, 33370, 31135,
           31396, 31380, 73, 5, 54, 56, 34399, 55, 31191, 60, 5, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 60,
           31179, 11002, 73, 2122, 72, 6787, 31161, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 60, 31179, 11002,
           73, 2]

json1 = {"input_ids": sample1, "seq_len": 13}
json2 = {"input_ids": sample2, "seq_len": 31}

features = [json1, json2]

样本继续使用上面构造的 json1 和 json2 并统一放到 features 的 list 中。

2.data_colloator 实现

def data_collator(features: list) -> dict:
    # 序列长度: [36, 106]
    len_ids = [len(feature["input_ids"]) for feature in features]
    # 取最长的序列长度: 106
    longest = max(len_ids)
    input_ids = []
    labels_list = []
    # 降序排列
    for ids_l, feature in sorted(zip(len_ids, features), key=lambda x: -x[0]):
        ids = feature["input_ids"]  # tokenIds
        seq_len = feature["seq_len"]  # seqLen
        # len(prompt) x [-100] + Target + [longest - len(prompt)] * [-100]
        labels = ([-100] * seq_len + ids[seq_len:] + [-100] * (longest - ids_l))
        ids = ids + [pad_token_id] * (longest - ids_l)

        _ids = torch.LongTensor(ids)
        labels_list.append(torch.LongTensor(labels))
        input_ids.append(_ids)
    # tensor([[], []])
    input_ids = torch.stack(input_ids)
    labels = torch.stack(labels_list)
    return {
        "input_ids": input_ids,
        "labels": labels,
    }

data_collator 的逻辑主要是这一句:

# len(prompt) x [-100] + Target + [longest - len(prompt)] * [-100]
labels = ([-100] * seq_len + ids[seq_len:] + [-100] * (longest - ids_l))

即将 Q mask 进行掩码,A 即 Target 保持不变,最后根据 longest 的长度决定是否 padding,这里手动指定了 pad_token_id = 0,实际代码中可以使用 tokenizer 自动指定:

tokenizer.pad_token_id

除此之外,这里和上面 API 生成还有一个区别是是否 mask Q_ids,API 把 Q_ids 全部去掉,上面方法保留了 Q_ids 的位置,但是使用 -100 进行了 mask,实际场景下二者没有区别,只不过 DIY 的 labels 如果 Q_ids 很长则会占用很多无关空间。

3.使用自定义 data_colloator

    trainer = ModifiedTrainer(
        model=model,
        train_dataset=dataset,
        args=training_args,
        callbacks=[TensorBoardCallback(writer)], # 回调将训练情况写入 tensorboard
        data_collator=data_collator,
    )

定义好 Trainer 后,将上面定一个 data_collator 传给 data_collator 参数即可,不过常规情况下我们使用 API 即可,如果自己对样本和 label 的构建有自定义需求,则可以采用后者 DIY 的形式。

四.总结

经过上面的分析,对于样本的处理和 label 的生成流程我们大致清晰了,下面解释下上面的样本如何应用在 LM 大语言模型中以及自己理解的这样构造的含义。

input 为 QA,output 为 A。Input 和 Output 分别在 Embedding lookup 获取输入向量,添加 position 向量后进入 Multi-Head Attention,首先经过 Q、K、V 的 Linear 映射转换,随后经过 Encoder 和 Decoder 的 Transformer 结构,最终通过一个 Linear + Softmax 输出预测概率 logits,输出概率 logits 与 A_ids 对应的 multi_hot 向量计算 batch loss 并回传,这里会忽略 [-100] 的掩码,更完整的 loss 计算逻辑大家可以参考 model.loss 的实现。

    # 根据输入计算 Loss
    def compute_loss(self, model, inputs, return_outputs=False):
        return model(
            input_ids=inputs["input_ids"],
            labels=inputs["labels"],
        ).loss

一般情况下,这里 QA 也分别代表 Prompt 和 Target,上面这种样本和 label 的构造方式意在学习当给定 Prompt 的前提提示下,模型能够预测得到 Target,即语言生成。如果想要学习其他不同的模式,大家也可以根据需求自定义修改上面的 data_collator。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Qt添加第三方字体

最近开发项目时&#xff0c;据说不能用系统自带的微软雅黑字体&#xff0c;于是找一个开源的字体&#xff0c;思源黑体&#xff0c;这个是google和Adobe公司合力开发的可以免费使用。本篇记录一下Qt使用第三方字体的方式。字体从下载之家下载http://www.downza.cn/soft/266042.…

uniapp实现路由跳转拦截

场景&#xff1a;系统可以不登录就可以访问浏览商城&#xff0c;一些菜单&#xff08;购买、添加修改用户信息、添加地址、修改密码等&#xff09;需要进行登录才能操作。 思路&#xff1a; 1.新建公共js文件进行路由拦截&#xff0c;添加白名单。&#xff08;白名单菜单不需…

【压力传感器】LPS22DFTR、LPS33KTR 绝对 压力,ADP5131 排气式压力计 50kPa 6-DIP

LPS22DFTR MEMS纳米压力传感器是一款超紧凑型压阻式绝对压力传感器&#xff0c;可用作数字输出气压计。LPS22DF的功耗更低&#xff0c;与上一代产品相比压力噪声更低。该器件包括一个传感元件和一个IC接口&#xff0c;通过I2C、MIPI I3CSM或SPI接口从传感元件向应用程序进行通信…

【操作系统】几种基本页面置换算法的基本思想和流程图

目录 一、概述二、最佳置换算法&#xff08;OPT&#xff09;三、先进先出置换算法&#xff08;FIFO&#xff09;四、最近最久未使用置换算法&#xff08;LRU&#xff09;五、三种页面置换算法优缺点对比六、运行结果七、总结 一、概述 在地址映射过程中&#xff0c;若在页面中发…

在After Effects 加速渲染的 21个技巧,记得收藏!

如何减少After Effects 渲染时间&#xff1f; 1.升级内存 减少渲染时间的一种有效方法是升级 RAM&#xff08;随机存取存储器&#xff09;。RAM 在渲染过程中起着至关重要的作用&#xff0c;因为它存储并快速访问渲染任务所需的数据。增加系统中的 RAM 量可提供更多的数据存储…

Activity引擎(初次学习与总结梳理全记录,包括易混淆知识点分析,常用报错解决方案等)

最近工作需要使用Acticity框架处理审批业务&#xff0c;简单了解后能虽能很快的上手&#xff0c;但是对于Activity的整体认识并不够&#xff0c;特此花费很多精力全面的学习并记录。包含对很多的概念的第一次理解过程&#xff1b;对知识点的混淆地方的梳理&#xff1b;对实践过…

深度学习 / 数据处理:如何处理偏态数据

1 前言 当我们使用一个线性回归模型时&#xff0c;通常这个模型是在很大假设的前提下才有一个很好的结果&#xff1a; 1、假设预测因子和预测目标之间的关系是线性的2、数据不存在外在噪声&#xff1a;不存在一些极端的数据3、非共线性&#xff08; collinearity&#xff09;…

区块链生态发展

文章目录 前言以太坊的到来什么是图灵完备&#xff1f;什么是智能合约&#xff1f; 以太坊的应用去中心化应用 DApp代币发行 公有链&联盟链区块链应用总结 前言 前面的区块链文章有介绍区块链的诞生以及底层运行原理&#xff0c; 本文主要介绍一下区块链应用的发展&#x…

Windows Bat实现延时功能的几种常见方式

文章目录 1. 使用ping命令实现延时2. 使用timeout命令实现延时3. 使用choice命令实现延时4. 使用for循环实现延时5. 使用sleep命令实现延时6. 使用VBScript.sleep实现延时总结 在 bat批处理中实现延时功能的几种常用方式 1. 使用ping命令实现延时 使用ping命令可以实现延时的…

最小二乘拟合平面——拉格朗日乘子法

目录 一、算法原理二、代码实现1、python2、matlab 三、算法效果 一、算法原理 设拟合出的平面方程为&#xff1a; a x b y c z d 0 (1) axbyczd0\tag{1} axbyczd0(1) 约束条件为&#xff1a; a 2 b 2 c 2 1 (2) a^2b^2c^21\tag{2} a2b2c21(2)   可以得到平面参数 a…

ahk1.1获取输入光标当前位置坐标(不是鼠标的位置)

F1 Up::Caret:GetCaretPos(1), hasCaretPos:1x坐标 : Caret.xy坐标 : Caret.yToolTip, %x坐标% %y坐标%Return; 获取光标坐标GetCaretPos(Byacc:1){Static initIf (A_CaretX""){Caretx:Carety:CaretH:CaretW:0If (Byacc){If (!init)init:DllCall("LoadLibrary&q…

Access violation at address 00000000. Read of address 00000000.的解决办法

Access violation at address 00000000. Read of address 00000000. 原理解决办法 在使用spacesniffer查看C盘空间的时候报错 原理 这个问题是关于Access Violation&#xff08;非法访问&#xff09;&#xff0c;General Protection Fault&#xff08;一般保护性错误&#x…

pytorch构建深度网络的基本概念——随机梯度下降

文章目录 随机梯度下降定义一个简单的模型定义Loss什么是梯度随机梯度下降 随机梯度下降 现在说说深度学习中的权重更新算法&#xff1a;经典算法SGD&#xff1a;stochastic gradient descent&#xff0c;随机梯度下降。 定义一个简单的模型 假设我们的模型就是要拟合一根直…

IDEA+springboot + ssm +shiro+ easyui +mysql实现的进销存系统

IDEAspringboot ssm shiro easyui mysql实现的进销存系统 一、系统介绍1.环境配置 二、系统展示1. 管理员登录2.首页3.修改密码4.系统日志5. 用户管理6. 角色管理7. 进货入库8.退货出库9.进货单据查询10.退货单据查询11.当前库存查询12.销售出库13.客户退货14. 销售单据查询15…

HTML和CSS配合制作一个简单的登录界面

HTML和CSS配合制作一个简单的登录界面 界面HTMLCSS解释语法 界面 HTML <!DOCTYPE html> <html lang"en"> <head><title>篮球世界</title><meta charset"UTF-8"><link type"text/css" rel"styleshe…

从Web2到Web3:区块链技术的未来前景

随着互联网的发展&#xff0c;Web1.0、Web2.0 和 Web3.0 成为了人们口中津津乐道的话题。那么&#xff0c;这三种网络时代究竟有什么区别呢&#xff1f; Web1.0 是一个只读的时代&#xff0c;那个时候&#xff0c;用户只能浏览网页&#xff0c;无法进行互动和创作。Web2.0 则是…

github搜索案例

目录结构 public/index.html <!DOCTYPE html> <html lang""><head><meta charset"utf-8"><!-- 针对IE浏览器的一个特殊配置&#xff0c;含义是让IE浏览器以最高的渲染级别渲染页面 --><meta http-equiv"X-UA-Comp…

AI绘画Stable Diffusion实战操作: 62个咒语调教-时尚杂志封面

今天来给大家分享&#xff0c;如何用sd简单的咒语输出好看的图片的教程&#xff0c;今天做的是时尚杂志专题&#xff0c;话不多说直入主题。 还不会StableDiffusion的基本操作&#xff0c;推荐看看这篇保姆级教程&#xff1a; AI绘画&#xff1a;Stable Diffusion 终极炼丹宝…

Win32 汇编在对话框上画线

参阅前文&#xff0c;首先要有一个基本的对话框&#xff1b; 把对话框资源文件里的控件定义都删除&#xff0c;得到的一个rc文件&#xff0c;test.rc&#xff1b; #include <resource.h>#define DLG_MAIN 1DLG_MAIN DIALOG 193, 180, 130, 150 STYLE DS_MODALFRAME | …

用主流编程语言解小学题

最近在网上刷到一个视频&#xff0c;内容是奶奶有60 元钱&#xff0c;去超市买了10元水果&#xff0c;收营员应该找奶奶多少钱?我一开始反应就是50元&#xff0c;后来想了想题干里没有说明这60元是怎么构成的&#xff0c;有可能是一张50元和一张10元&#xff0c;或者是3张20元…