当前位置: 首页 > news >正文

从零开始实现大语言模型(十三):预训练大语言模型GPTModel

1. 前言

使用梯度下降算法通过下一个token预测任务预训练大语言模型GPTModel,前向传播流程每次会输入一个batch的长度均为context_len的训练样本,执行 batch_size × context_len \text{batch\_size}\times\text{context\_len} batch_size×context_len次下一个token预测任务,共预测输出 batch_size × context_len \text{batch\_size}\times\text{context\_len} batch_size×context_len个tokens。后向传播流程首先会使用交叉熵(Cross Entropy)损失函数计算大语言模型GPTModel的预测输出与训练样本标签之间的损失(loss),再通过后向传播算法计算大语言模型参数梯度,最后使用梯度下降算法更新大语言模型的参数。

本文使用交叉熵损失函数计算生成大语言模型GPTModel的预测输出与训练样本标签之间的loss,介绍大语言模型的预训练流程,并实现预训练大语言模型的函数pretrain_model

2. 损失函数Cross Entropy

交叉熵损失函数可以度量大语言模型的预测输出与训练样本标签之间的差异。损失函数计算生成的loss值越大,表明大语言模型的预测输出与训练样本标签之间的差异越大,loss值越小,表明大语言模型的预测输出与训练样本标签之间的差异越小。

对输入文本做tokenization,将输入文本转换成包含context_len个token ID的列表,并输入大语言模型GPTModel,可以得到context_len个维度为vocabulary_size的logits向量,第 i i i个logits向量是大语言模型根据前 i i i个token预测生成的下一个token的概率分数向量,logits向量中的第 k k k个概率分数值越大,表明大语言模型预测生成的下一个token的ID为 k k k的概率越高。

使用softmax函数将大语言模型预测生成的logits向量归一化,得到大语言模型预测生成的下一个token的概率分布,概率分布中对应样本标签位置的概率值表示大语言模型预测输出的token为相应训练样本标签的概率。对应样本标签位置的概率值越接近1,表明大语言模型预测输出的token为相应训练样本标签的概率越高,大语言模型的预测输出与训练样本标签之间的差异越小。

图一

使用梯度下降算法预训练大语言模型GPTModel的前向传播流程中,大语言模型每次会预测生成 batch_size × context_len \text{batch\_size}\times\text{context\_len} batch_size×context_len个下一个token的概率分布。如下图所示,交叉熵损失函数会分别获取 batch_size × context_len \text{batch\_size}\times\text{context\_len} batch_size×context_len个概率分布中对应样本标签位置的概率值,使用对数函数计算这些概率值的对数,并计算所有对数值的均值,最后将对数均值的相反数作为大语言模型GPTModel的预测输出与训练样本标签之间的损失loss。

图二

如下面的代码所示,使用torch.tensor函数创建训练样本inputs及训练样本标签targets,将训练样本inputs输入大语言模型gpt2_small,并使用softmax函数将大语言模型的输出张量logits归一化,得到 2 × 3 2\times3 2×3个下一个token的概率分布,其中每个概率分布的维度均等于词汇表的大小50257。分别获取 2 × 3 2\times3 2×3个下一个token的概率分布中对应样本标签位置的概率值,使用torch.log函数计算这些概率值的对数,并计算所有对数值均值的相反数,可以得到大语言模型gpt2_small的预测输出与样本标签targets之间的交叉熵损失:

import torch
# from [从零开始实现大语言模型(七):多头注意力机制] import MultiHeadAttention
# from [从零开始实现大语言模型(八):Layer Normalization] import LayerNorm
# from [从零开始实现大语言模型(九):前馈神经网络与GELU激活函数] import GELU, FeedForward
# from [从零开始实现大语言模型(十一):构建大语言模型GPTModel] import TransformerBlock, GPTModeltorch.manual_seed(123)embedding_dim = 768
num_layers = 12
num_heads = 12
context_len = 1024
vocabulary_size = 50257
dropout = 0.1
qkv_bias = Falsegpt2_small = GPTModel(embedding_dim=embedding_dim,num_layers=num_layers,num_heads=num_heads,context_len=context_len,vocabulary_size=vocabulary_size,dropout=dropout,qkv_bias=qkv_bias
)inputs = torch.tensor([[16833, 3626, 6100],  # [["every effort moves"],[40, 1107, 588]]      # ["I really like"]]
)targets = torch.tensor([[3626, 6100, 345],  # [[" effort moves you"],[588, 428, 11311]]  # [" really like chocolate"]]
)with torch.no_grad():logits = gpt2_small(inputs)
probas = torch.softmax(logits, dim=-1)target_probas_1 = probas[0, [0, 1, 2], targets[0]]
target_probas_2 = probas[1, [0, 1, 2], targets[1]]log_probas = torch.log(torch.cat((target_probas_1, target_probas_2)))
avg_log_probas = torch.mean(log_probas)
neg_avg_log_probas = avg_log_probas * -1print("probas shape:", probas.shape)
print("target_probas_1:", target_probas_1)
print("target_probas_2:", target_probas_2)
print("log_probas:", log_probas)
print("avg_log_probas:", avg_log_probas)
print("cross entropy loss:", neg_avg_log_probas)

执行上面代码,打印结果如下:

probas shape: torch.Size([2, 3, 50257])
target_probas_1: tensor([2.6369e-05, 1.5997e-05, 1.6926e-05])
target_probas_2: tensor([1.5638e-05, 8.9422e-06, 1.7967e-05])
log_probas: tensor([-10.5433, -11.0431, -10.9867, -11.0658, -11.6247, -10.9270])
avg_log_probas: tensor(-11.0318)
cross entropy loss: tensor(11.0318)

可以直接使用PyTorch内置的cross_entropy函数执行上述计算流程,得到大语言模型gpt2_small的预测输出logits与样本标签targets之间的交叉熵损失:

loss = torch.nn.functional.cross_entropy(logits.flatten(0, 1), targets.flatten())
print(loss)

执行上面代码,打印结果如下:

tensor(11.0318)

根据打印结果可知,上述6个步骤计算得到的损失值与PyTorch内置的cross_entropy函数计算得到的交叉熵损失完全相同。交叉熵损失本质上就是大语言模型预测生成的 batch_size × context_len \text{batch\_size}\times\text{context\_len} batch_size×context_len个下一个token的概率分布中对应样本标签位置概率值的对数均值的相反数。

3. 大语言模型预训练流程

预训练大语言模型的流程与训练普通神经网络模型本质上并没有任何不同。如下图所示,预训练大语言模型可以把整个训练数据集扫几个epoch,每个epoch会把整个训练数据集扫一遍,每次会使用训练数据集中一个batch的训练样本训练一次大语言模型。前向传播流程会将一个batch的训练样本输入大语言模型,得到大语言模型的预测输出logits。后向传播流程首先会使用交叉熵损失函数计算大语言模型的预测输出logits与训练样本标签targets之间的损失loss,再通过后向传播算法计算大语言模型参数梯度,最后使用梯度下降算法更新大语言模型的参数。

图三

可以使用如下代码定义计算一个batch样本数据交叉熵损失的函数calc_loss_batch,以及计算整个数据集上所有样本数据交叉熵损失的函数calc_loss_loader。函数calc_loss_batch将一个batch的样本数据输入大语言模型,得到大语言模型的预测输出logits,并使用torch.nn.functional.cross_entropy函数计算大语言模型的预测输出logits与样本标签targets之间的损失loss。函数calc_loss_loader每次取数据集中一个batch的样本数据,使用calc_loss_batch函数计算该batch样本数据的交叉熵损失,并返回数据集上所有样本数据损失loss的均值:

def calc_loss_batch(input_batch, target_batch, model, device):input_batch = input_batch.to(device)target_batch = target_batch.to(device)logits = model(input_batch)loss = torch.nn.functional.cross_entropy(logits.flatten(0, 1), target_batch.flatten())return lossdef calc_loss_loader(data_loader, model, device, num_batches=None):model.eval()total_loss = 0.0if num_batches is None:num_batches = len(data_loader)else:num_batches = min(num_batches, len(data_loader))with torch.no_grad():for i, (input_batch, target_batch) in enumerate(data_loader):if i < num_batches:loss = calc_loss_batch(input_batch, target_batch, model, device)total_loss += loss.item()else:breakreturn total_loss / num_batches

实现预训练大语言模型的函数pretrain_model,可以使用for循环将整个训练数据集扫num_epochs遍,并在每次训练大语言模型的循环中,首先使用optimizer.zero_grad函数将大语言模型所有参数的梯度置为0,然后使用函数calc_loss_batch计算一个batch训练样本的交叉熵损失loss。使用loss.backward函数可以执行后向传播流程,计算大语言模型所有参数的梯度,并通过optimizer.step函数使用梯度下降算法更新大语言模型参数。具体代码如下所示:

# from [从零开始实现大语言模型(十二):文本生成策略] import generate_textdef pretrain_model(model, optimizer, train_loader, num_epochs, device,eval_freq, eval_iter, tokenizer, start_context,save_freq, checkpoint_dir, checkpoint=None, val_loader=None
):if not os.path.exists(checkpoint_dir):os.makedirs(checkpoint_dir, exist_ok=True)if checkpoint is not None:model_checkpoint_path = os.path.join(checkpoint_dir, f"model_{checkpoint:06d}.pth")optimizer_checkpoint_path = os.path.join(checkpoint_dir, f"optimizer_{checkpoint:06d}.pth")model.load_state_dict(torch.load(model_checkpoint_path))optimizer.load_state_dict(torch.load(optimizer_checkpoint_path))else:checkpoint = -1train_losses, val_losses, track_tokens_seen = [], [], []tokens_seen, global_step = 0, -1for epoch in range(num_epochs):model.train()for i, (input_batch, target_batch) in enumerate(train_loader):if global_step % eval_freq == 0:model.train()optimizer.zero_grad()loss = calc_loss_batch(input_batch, target_batch, model, device)loss.backward()optimizer.step()tokens_seen += input_batch.numel()global_step += 1print(f"Epoch {epoch + 1} (Batch {i:06d}): Train loss {loss.item():.3f}")checkpoint, train_loss, val_loss = val_and_save(model, optimizer, train_loader, val_loader, epoch, global_step, eval_freq,eval_iter, start_context, tokenizer, save_freq, checkpoint_dir, checkpoint, device)if train_loss is not None:train_losses.append(train_loss)val_losses.append(val_loss)track_tokens_seen.append(tokens_seen)checkpoint, _, _ = val_and_save(model, optimizer, train_loader, val_loader, epoch, global_step, 1,eval_iter, start_context, tokenizer, 1, checkpoint_dir, checkpoint, device)print(f"Epoch {epoch + 1} finished, checkpoint: {checkpoint:06d}")return train_losses, val_losses, track_tokens_seendef val_and_save(model, optimizer, train_loader, val_loader, epoch, global_step, eval_freq,eval_iter, start_context, tokenizer, save_freq, checkpoint_dir, checkpoint, device
):train_loss, val_loss = None, Noneif global_step % eval_freq == 0:if val_loader is not None:train_loss = calc_loss_loader(train_loader, model, device, eval_iter)val_loss = calc_loss_loader(val_loader, model, device, eval_iter)print(f"Epoch {epoch + 1} (Step {global_step:06d}): Train loss {train_loss:.3f}, Val loss {val_loss:.3f}")generated_sample_text = generate_text(model, start_context, max_new_tokens=50, tokenizer=tokenizer,context_size=model.pos_emb.weight.shape[0], top_k=1, compact_format=True)print(f"Generated Sample Text: {generated_sample_text}")print("=====================================================================")if global_step % save_freq == 0:checkpoint += 1model_checkpoint_path = os.path.join(checkpoint_dir, f"model_{checkpoint:06d}.pth")optimizer_checkpoint_path = os.path.join(checkpoint_dir, f"optimizer_{checkpoint:06d}.pth")torch.save(model.state_dict(), model_checkpoint_path)torch.save(optimizer.state_dict(), optimizer_checkpoint_path)return checkpoint, train_loss, val_loss

PyTorch中神经网络模型的state_dict是一个字典对象,字典中的key为神经网络模型中参数的名称,value为相应的参数。使用.state_dict函数可以一次性获取神经网络模型中的所有参数,并通过torch.save函数将所有参数保存为一个checkpoint。torch.load函数可以读取指定checkpoint,通过.load_state_dict函数可以将神经网络模型中的参数修改为checkpoint中的记录值。

所有具有自适应能力的优化器(如AdamW可以根据历史梯度信息动态调整学习率)都需要记录每个神经网络参数的历史梯度等信息,同样可以使用.state_dict一次性获取优化器中的所有数据记录,以及通过.load_state_dict函数从指定checkpoint中还原这些记录数据。

如下面的代码所示,使用从零开始实现大语言模型(二):文本数据处理中构建的Dataset创建训练集train_dataset及验证集val_dataset,并通过PyTorch内置的torch.utils.data.DataLoader类创建训练集及验证集对应的DataLoader。使用torch.optim.AdamW实例化训练大语言模型的优化器optimizer,最后使用函数pretrain_model预训练大语言模型gpt2_small

import os
import random
import tiktoken
from torch.utils.data import Dataset, DataLoader# from [从零开始实现大语言模型(二):文本数据处理] import LLMDatasettrain_data_path = "train_data"
val_data_path = "val_data"
vocabulary = "gpt2"
special_token_id = 50256
context_len = 1024
stride = 1024
batch_size = 2num_epochs = 10
eval_freq = 5
eval_iter = 1
save_freq = 5
checkpoint_dir = "checkpoint"
start_context = "萧炎,斗之力,三段"
tokenizer = tiktoken.encoding_for_model(vocabulary)
device = torch.device("cpu")
gpt2_small.to(device)
optimizer = torch.optim.AdamW(gpt2_small.parameters(), lr=0.0006, weight_decay=0.1)train_dataset = LLMDataset(train_data_path, vocabulary, special_token_id, context_len, stride)
val_dataset = LLMDataset(val_data_path, vocabulary, special_token_id, context_len, stride)
train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True, drop_last=True)
val_loader = DataLoader(dataset=val_dataset, batch_size=batch_size, shuffle=False, drop_last=False)
print(f"train_loader len: {len(train_loader)}")train_losses, val_losses, tokens_seen = pretrain_model(gpt2_small, optimizer, train_loader, num_epochs, device,eval_freq, eval_iter, tokenizer, start_context,save_freq, checkpoint_dir, val_loader=val_loader
)

执行上面代码,打印结果如下:

train_loader len: 7
Epoch 1 (Batch 000000): Train loss 11.034
Epoch 1 (Step 000000): Train loss 9.827, Val loss 9.784
Generated Sample Text: 萧炎,斗之力,三段 Knowledge�缌�缌缌�703 clashes�缌 longest,,缌,���,缌缌�
=====================================================================
Epoch 1 (Batch 000001): Train loss 9.940
Epoch 1 (Batch 000002): Train loss 8.811
Epoch 1 (Batch 000003): Train loss 7.954
Epoch 1 (Batch 000004): Train loss 7.286
Epoch 1 (Batch 000005): Train loss 6.629
Epoch 1 (Step 000005): Train loss 5.980, Val loss 6.003
Generated Sample Text: 萧炎,斗之力,三段,,,,,,,,,,,,,,,,�
=====================================================================
Epoch 1 (Batch 000006): Train loss 6.027
Epoch 1 (Step 000006): Train loss 5.390, Val loss 5.479
Generated Sample Text: 萧炎,斗之力,三段,,,�,,,��,,,,,�,�,,,
=====================================================================
Epoch 1 finished, checkpoint: 000002
Epoch 2 (Batch 000000): Train loss 5.401
Epoch 2 (Batch 000001): Train loss 5.028
Epoch 2 (Batch 000002): Train loss 4.788
Epoch 2 (Batch 000003): Train loss 4.616
Epoch 2 (Step 000010): Train loss 4.511, Val loss 4.526
Generated Sample Text: 萧炎,斗之力,三段,�,�,�,�,�,�,�,�,�,��,�,
=====================================================================[...]Epoch 9 (Step 000060): Train loss 2.561, Val loss 3.470
Generated Sample Text: 萧炎,斗之力,三段���是在脸�的�,�炣�殸废是萧炣也是曰�,萧�
=====================================================================
Epoch 9 (Batch 000005): Train loss 2.560
Epoch 9 (Batch 000006): Train loss 2.558
Epoch 9 (Step 000062): Train loss 2.456, Val loss 3.455
Generated Sample Text: 萧炎,斗之力,三段���,脸庿,炎�,萧炎萧�炎�萧�,萧�的�
=====================================================================
Epoch 9 finished, checkpoint: 000021
Epoch 10 (Batch 000000): Train loss 2.525
Epoch 10 (Batch 000001): Train loss 2.388
Epoch 10 (Batch 000002): Train loss 2.663
Epoch 10 (Step 000065): Train loss 2.270, Val loss 3.468
Generated Sample Text: 萧炎,斗之力,三段��技萧�的萧炣也�,萧�讵��更中着曰萧�着�
=====================================================================
Epoch 10 (Batch 000003): Train loss 2.464
Epoch 10 (Batch 000004): Train loss 2.602
Epoch 10 (Batch 000005): Train loss 2.511
Epoch 10 (Batch 000006): Train loss 2.557
Epoch 10 (Step 000069): Train loss 2.117, Val loss 3.474
Generated Sample Text: 萧炎,斗之力,三段��,这的�法的萧�炼�萧�法,萧�级级父了�
=====================================================================
Epoch 10 finished, checkpoint: 000023

从上面的打印结果可知,使用梯度下降算法训练大语言模型gpt2_small,可以减小大语言模型的预测输出与样本标签之间的交叉熵损失,并显著提升大语言模型的文本生成能力。在训练刚开始时,将萧炎,斗之力,三段输入大语言模型gpt2_small,生成的是Knowledge�缌�缌缌�703 clashes�缌 longest,,缌,���,缌缌�或者,,,,,,,,,,,,,,,,�这样不包含任何有效信息的自然语言文本序列。在仅包含7个batch训练样本的数据集上训练10个epoch,大语言模型gpt2_small已经可以生成���,脸庿,炎�,萧炎萧�炎�萧�,萧�的�以及��,这的�法的萧�炼�萧�法,萧�级级父了�这样与训练数据集存在一定关联的自然语言文本了。

可以使用如下代码,分别绘制大语言模型gpt2_small在训练集及验证集上交叉熵损失的变化情况图像:

import matplotlib.pyplot as pltdef plot_losses(epochs_seen, tokens_seen, train_losses, val_losses):fig, ax1 = plt.subplots(figsize=(5, 3))ax1.plot(epochs_seen, train_losses, label="Training loss")ax1.plot(epochs_seen, val_losses, linestyle="-.", label="Validation loss")ax1.set_xlabel("Epochs")ax1.set_ylabel("Loss")ax1.legend(loc="upper right")ax2 = ax1.twiny()ax2.plot(tokens_seen, train_losses, alpha=0)ax2.set_xlabel("Tokens seen")fig.tight_layout()plt.show()epochs_tensor = torch.linspace(0, num_epochs, len(train_losses))
plot_losses(epochs_tensor, tokens_seen, train_losses, val_losses)

执行上面代码,生成交叉熵损失的变化情况图像如下:

图四

从上面的交叉熵损失变化情况图像可知,在训练刚开始时,训练集及验证集上的交叉熵损失都非常大。使用梯度下降算法训练大语言模型gpt2_small,可以减小大语言模型的预测输出与样本标签之间的交叉熵损失,使大语言模型的预测输出与样本标签之间的差异性更小。

随着训练的进行,训练集和验证集上交叉熵损失的差异会越来越大,训练集上的交叉熵损失值会比验证集小的越来越明显,表明大语言模型在训练数据集上的过拟合情况越来越严重。在工业界的预训练大语言模型实践中,并不会在一个很小的训练数据集上训练多个epoch,而是会在一个非常大的训练数据集上训练少数几个甚至只训练一个epoch,这种训练策略可以很大程度上解决预训练大语言模型时的过拟合问题。

4. 结束语

前向传播流程将一个batch的训练样本输入大语言模型,共预测输出 batch_size × context_len \text{batch\_size}\times\text{context\_len} batch_size×context_len个维度为vocabulary_size的logits向量。后向传播流程首先使用交叉熵损失函数计算大语言模型的预测输出与训练样本标签之间的损失loss,并通过后向传播算法计算大语言模型参数梯度,最后使用梯度下降算法更新大语言模型的参数。

预训练大语言模型就是不断从训练数据集中获取一个batch的训练样本,然后执行这个操作直至收敛的过程。

相关文章:

从零开始实现大语言模型(十三):预训练大语言模型GPTModel

1. 前言 使用梯度下降算法通过下一个token预测任务预训练大语言模型GPTModel&#xff0c;前向传播流程每次会输入一个batch的长度均为context_len的训练样本&#xff0c;执行 batch_size context_len \text{batch\_size}\times\text{context\_len} batch_sizecontext_len次下…...

[C++面试] 对通透比较器了解多少?(较少涉及,可跳过)

一、入门 1、什么是比较器 在 C 中&#xff0c;比较器是一个可调用对象&#xff08;函数、函数对象或 Lambda 表达式&#xff09;&#xff0c;用于定义元素之间的比较规则。 用途&#xff1a;通常作为参数传递给标准库中的排序函数或关联容器&#xff0c;以指定元素的顺序。…...

【高分论文密码】AI大模型和R语言的全类型科研图形绘制,从画图、标注、改图、美化、组合、排序分解科研绘图每个步骤

在科研成果竞争日益激烈的当下&#xff0c;「一图胜千言」已成为高水平SCI期刊的硬性门槛——数据显示很多情况的拒稿与图表质量直接相关。科研人员普遍面临的工具效率低、设计规范缺失、多维数据呈现难等痛点&#xff0c;因此科研绘图已成为成果撰写中的至关重要的一个环节&am…...

el-input-number添加自定义内容class-unit

在el-input,el-input-number中有需要在输入框后面添加单位的需求&#xff0c;这时候就需要用到class-unit <el-input-number size"small" class-unit"%" class"inputNumberClass"></el-input-number>// css .inputNumberClass[clas…...

MYSQL学习笔记(十一):MYSQL数据类型讲解

前言&#xff1a; 学习和使用数据库可以说是程序员必须具备能力&#xff0c;这里将更新关于MYSQL的使用讲解&#xff0c;大概应该会更新30篇&#xff0c;涵盖入门、进阶、高级(一些原理分析);这一篇数据类型&#xff0c;比较多&#xff0c;但是我感觉了解即可&#xff0c;ai时…...

【数据分享】1999—2023年我国地级市社会消费品零售总额和年末金融机构存贷款余额(Shp/Excel格式)

在之前的文章中&#xff0c;我们分享过基于2000-2024年《中国城市统计年鉴》整理的1999-2023年地级市的人口相关数据、染物排放和环境治理相关数据和房地产投资情况和商品房销售面积相关指标数据&#xff08;均可查看之前的文章获悉详情&#xff09;&#xff01; 本次我们分享…...

使用 MyBatis-Plus 实现数据库的多租户管理

在现代 SaaS&#xff08;软件即服务&#xff09;应用中&#xff0c;多租户架构是一种常见的设计模式。它允许多个租户共享同一个应用实例&#xff0c;同时确保每个租户的数据相互隔离。MyBatis-Plus 提供了强大的多租户支持&#xff0c;能够帮助开发者轻松实现多租户管理。本文…...

大语言模型学习--向量数据库基础知识

1.向量 向量是多维数据空间中的一个坐标点。 向量类型 图像向量 文本向量 语音向量 Embedding 非结构化数据转换为向量过程 通过深度学习训练&#xff0c;将真实世界离散数据&#xff0c;投影到高维数据空间上&#xff0c;通过数据在空间中间的距离体现真实世界的相似度 V…...

计算机三级网络技术备考(5)

第七章&#xff1a;路由器及其配置 考点1&#xff1a;路由器概述及其工作原理 考点2&#xff1a;路由器工作模式及基础配置 考点3&#xff1a;路由器的接口配置 【sdh 0 2 sonet 0】 考点4&#xff1a;路由器的路由配置 考点5&#xff1a;路由器DHCP配置 考点6&#xff1a…...

Java关键字与标识符

Java关键字是预定义的保留字&#xff0c;用于定义程序结构和语义&#xff0c;如if、for、class等&#xff0c;不能用作标识符。JDK 8有50个关键字&#xff0c;JDK 11引入var用于局部变量类型推断。标识符用于命名变量、类等&#xff0c;由字母、数字、_、$组成&#xff0c;不能…...

生活小妙招之UE ViewPortUV-SceneTextureUV

后处理材质customNode中写SceneTextureLookup遇到了一些问题&#xff0c;做做记录 比如要在custom中写一个普通的镜像模糊&#xff0c;脑子都不带转的上来就直接这么写了&#xff0c;像是顺理成章的就应该这么写&#xff0c;并且网上随便搜UE咋写镜像模糊估计都是这样式的。 但…...

FB投广探秘:为何Facebook广告账户不消耗

在Facebook上投放广告时&#xff0c;您是否遇到过这种情况:广告创建完成后却发现账户没消耗&#xff0c;广告没跑出去?为什么会遇到这种情况?小编将结合最新行业动态&#xff0c;为你解析广告为何无消耗。 一、原因解析 1、账户余额不足 最直接的原因往往最容易被忽视。若…...

亚信安全发布第七期《勒索家族和勒索事件监控报告》

本周态势快速感知 本周全球共监测到勒索事件121起&#xff0c;与上周相比&#xff0c;勒索事件数量大幅下降&#xff0c;仍需注意防范。从整体上看Clop是影响最严重的勒索家族&#xff1b;本周Ransomhub和Akira也是活动频繁的两个恶意家族&#xff0c;需要注意防范。本周&…...

flask实现mvc模式

Flask 默认是一个轻量级框架&#xff0c;并不强制使用 MVC 模式&#xff0c;但我们可以按照 MVC 结构来组织代码&#xff0c;使项目更加清晰和可维护。 Flask 实现 MVC 模式 Flask 本身并没有严格的 Controller 层&#xff0c;但我们可以通过 视图函数&#xff08;View Functi…...

基于LabVIEW的脚本化子VI动态生成

该示例展示了一种利用LabVIEW VI脚本&#xff08;VI Scripting&#xff09;技术&#xff0c;通过程序化方式动态生成并替换子VI的解决方案。核心逻辑为&#xff1a;基于预定义的模板VI&#xff0c;根据用户选择的数学操作&#xff08;加法或乘法&#xff09;&#xff0c;自动生…...

Linux 网络:skb 数据管理

文章目录 1. 前言2. skb 数据管理2.1 初始化2.2 数据的插入2.2.1 在头部插入数据2.2.2 在尾部插入数据 2.2 数据的移除 3. 小结 1. 前言 限于作者能力水平&#xff0c;本文可能存在谬误&#xff0c;因此而给读者带来的损失&#xff0c;作者不做任何承诺。 2. skb 数据管理 数…...

golang坐标转换 gomap3d库

gomap3d Go语言实现的多坐标系转换库&#xff0c;支持天文学/航天领域常用坐标系转换 基础算子支持c gomap3d 特性 支持5种坐标系互转&#xff1a; 站心坐标系 (AER)东北天坐标系 (ENU)地心地固坐标系 (ECEF)地心惯性坐标系 (ECI)大地坐标系 (LLA) 支持多种参考椭球体&#…...

电脑的常见问题的原因+解决方法

电脑常见问题涵盖软件和硬件两方面&#xff0c;以下是一些常见问题及解决方法&#xff1a; 软件问题 系统运行缓慢 原因&#xff1a;可能是开机启动项过多、系统垃圾文件堆积、病毒或恶意软件入侵、硬件驱动不兼容等。解决方法&#xff1a;利用系统自带的任务管理器或第三方软…...

JavaScript性能优化实战:从8s到0.8s的极致提升

‌摘要‌:页面卡顿、内存泄漏、CPU爆满?本文通过‌6个真实场景‌+‌可运行代码示例‌,手把手教你掌握JS性能优化核心技术!涵盖‌防抖节流、虚拟滚动、Web Workers、内存泄漏排查‌等高频痛点解决方案,最后提供Chrome性能分析工具实战指南,助你打造丝滑的Web应用! 一、性…...

英语学习(GitHub学到的分享)

【英语语法&#xff1a;https://github.com/hzpt-inet-club/english-note】 【离谱的英语学习指南&#xff1a;https://github.com/byoungd/English-level-up-tips/tree/master】 【很喜欢文中的一句话&#xff1a;如果我轻轻松松的学习&#xff0c;生活的幸福指数会提高很多…...

OTP单片机调试工具之—应广单片机ADC调试案例

上一篇文章说到了‘OTP单片机调试工具’的大概使用方法&#xff0c;现在做一个案例来说明情况。 这个案例是使用应广单片机ADC对可调电阻中间抽头电压值进行采样&#xff0c;分别用12bit和8bit进行显示&#xff0c;使用vdd做参考&#xff0c;采样数据没有进行滤波&#xff0c;通…...

Java基础关键_020_集合(四)

目 录 一、Set 集合 二、Map 集合 1.概览 2.说明 3.HashMap 说明 4.LinkedHashMap 说明 5.TreeMap 说明 6.Hashtable 说明 7.Properties 说明 三、Map 接口常用方法 1.put(K key, V value) 和 putAll(Map m) 2.get(Object key) 3.clear() 和 size() 4.contains…...

电商数据分析 电商平台销售数据分析 电商平台数据库设计 揭秘电商怎么做数据分析

《电商参谋数据分析平台方案》&#xff08;28页PPT&#xff09;是一套为电商行业量身定制的一体化解决方案&#xff0c;它通过全链路打通从数据获取到分析的全过程&#xff0c;帮助电商企业实现精细化运营和市场机会的挖掘。该方案针对电商行业在数据获取、加工整合及业务赋能方…...

Hugging Face的Transformers核心模块:Pipelines(参数说明,各种模型类型调用案例)

如果电脑配置不够可以参考文章《学AI-撸羊毛-免费GPU服务器-kaggle-每周30小时-可以进行数据训练&#xff0c;大模型微调》 申请免费服务器执行代码。 什么是Pipelines 将数据预处理、模型调用、结果后处理三部分组装成的流水线使我们能够直接输入文本便获得最终的答案 Pipeli…...

ChatGPT辅助学术写作有哪些挑战?怎么解决?

宝子们毕业之前需要完成的学术论文往往是学生时代最后一项挑战。无论宝子们对此过程多么熟悉&#xff0c;每次着手写新论文时&#xff0c;似乎都需重新规划、从头开始。 值得庆幸的是&#xff0c;借助ChatGPT、DeepSeek这些工具能够为论文旅程提供有力支持。ChatGPT作为备受推崇…...

【MySQL是怎么运行的】二、索引

引擎层有支持索引&#xff0c;如InnoDB和MyISAM&#xff0c;区别就是InnoDB支持事务、外键和行锁 索引物理结构 页&#xff1a;一页16KB&#xff0c;一页包含了多行记录 行&#xff1a;包含元数据和真实数据 元数据&#xff1a; record_type&#xff08;记录的类型&#xff…...

MySQL中有哪些索引

1&#xff0c;B-Tree索引&#xff1a;常见的索引类型 2&#xff0c;哈希索引&#xff1a;基于哈希表实现&#xff0c;只支持等值查询 &#xff0c;只有Memory存储引擎和NDB Cluster存储引擎显示支持哈希索引 3&#xff0c;全文索引&#xff1a;可在字符列上创建&#xff08;T…...

Node.js中HTTPS模块应用详解

1. HTTPS 模块的概念 HTTPS&#xff08;Hypertext Transfer Protocol Secure&#xff09;是 HTTP 的安全版本&#xff0c;通过 SSL/TLS 协议对数据进行加密&#xff0c;确保数据在传输过程中不被窃取或篡改。在 Node.js 中&#xff0c;https 模块提供了创建 HTTPS 服务器和客户…...

facebook游戏投广:提高广告关键数据的方法

在当今竞争激烈的数字营销领域&#xff0c;游戏广告的投放效果直接关系到游戏公司的市场表现和盈利能力。然而&#xff0c;许多游戏公司在广告投放上面临着诸多挑战&#xff0c;如高昂的成本、低效的转化率以及难以追踪的效果。那么&#xff0c;如何才能通过数据分析真正提升游…...

每天五分钟深度学习框架PyTorch:ResNet算法模型完成CAFIR十分类

本文重点 ResNet模型已经搭建完成了&#xff0c;本文我们使用ResNet来跑一下CAFIR10的数据集&#xff0c;看一下分类效果如何&#xff1f; 代码 本文总结 在之前的课程中我们对残差块以及ResNet模型进行了详细的介绍&#xff0c;并且我们对模型训练这些基础的数据集进行了详…...

Python中很常用的100个函数整理

Python 内置函数提供了强大的工具&#xff0c;涵盖数据处理、数学运算、迭代控制、类型转换等。本文总结了 100 个常用内置函数&#xff0c;并配备示例代码&#xff0c;提高编程效率。 1. abs() 取绝对值 print(abs(-10)) # 10 2. all() 判断所有元素是否为真 print(all([…...

nginx与openSSL版本不兼容问题

本人先前使用的nginx-version为1.18.0&#xff0c;openSSL-version为3.0.2&#xff1b; 在源码的安装configure过程中&#xff0c;出现以下报错 error: ‘ENGINE_free’ is deprecated: Since OpenSSL 3.0 [-Werrordeprecated-declarations]734 | ENGINE_free(en…...

【RabbitMQ】事务

事务的简单配置及使用 配置事务管理器声明队列生产者代码测试 RabbitMQ是基于AMQP协议实现的&#xff0c;该协议实现了事务机制&#xff0c;因此RabbitMQ也支持事务机制. SpringAMQP也提供了对事务相关的操作.RabbitMQ事务允许开发者确保消息的发送和接收是原子性的&#xff0c…...

【C#学习笔记03】进制转换与反码、补码、原码

1. 进制转换 计算机中的数据通常以二进制形式存储&#xff0c;但在编程和调试过程中&#xff0c;我们经常需要与十进制、八进制和十六进制打交道。因此&#xff0c;掌握进制转换是C语言学习中的重要一环。 1.1 进制的基本概念 二进制&#xff08;Binary&#xff09;&#xff…...

线性搜索算法

何时使用线性搜索算法&#xff1f; 当处理一个小数据集时。当搜索存储在连续内存中的数据集时。 线性搜索算法在什么情况下优于其他搜索算法&#xff1f; 当列表或数组未排序时&#xff0c;或者当输入的大小相对较小时&#xff0c;首选线性搜索算法。它易于实现&#xff0c;并…...

基于深度文档理解的开源 RAG 引擎RAGFlow的介绍和安装

目录 前言1. RAGFlow 简介1.1 什么是 RAGFlow&#xff1f;1.2 RAGFlow 的核心特点 2. RAGFlow 的安装与配置2.1 硬件与软件要求2.2 下载 RAGFlow 源码2.3 源码编译 Docker 镜像2.4 设置完整版&#xff08;包含 embedding 模型&#xff09;2.5 运行 RAGFlow 3. RAGFlow 的应用场…...

蓝桥杯—走迷宫(BFS算法)

题目描述 给定一个NM 的网格迷宫 G。G 的每个格子要么是道路&#xff0c;要么是障碍物&#xff08;道路用 11表示&#xff0c;障碍物用 0 表示&#xff09;。 已知迷宫的入口位置为 (x1​,y1​)&#xff0c;出口位置为 (x2​,y2​)。问从入口走到出口&#xff0c;最少要走多少…...

基于云函数的自习室预约微信小程序+LW示例参考

全阶段全种类学习资源&#xff0c;内涵少儿、小学、初中、高中、大学、专升本、考研、四六级、建造师、法考、网赚技巧、毕业设计等&#xff0c;持续更新~ 文章目录 [TOC](文章目录) 1.项目介绍2.项目部署3.项目部分截图4.获取方式 1.项目介绍 技术栈工具&#xff1a;云数据库…...

Flutter 学习之旅 之 flutter 不使用插件,实现简单带加载动画的 LoadingToast 功能

Flutter 学习之旅 之 flutter 不使用插件&#xff0c;实现简单带加载动画的 LoadingToast 功能 目录 Flutter 学习之旅 之 flutter 不使用插件&#xff0c;实现简单带加载动画的 LoadingToast 功能 一、简单介绍 二、LoadingToast 三、简单案例实现 四、关键代码 一、简单…...

GStreamer —— 2.17、Windows下Qt加载GStreamer库后运行 - “播放教程 5:色彩平衡“(附:完整源码)

运行效果 介绍 亮度、对比度、色相和饱和度是常见的视频调整&#xff0c; 在 GStreamer 中统称为 Color Balance 设置。 本教程展示了&#xff1a; • 如何找出可用的色彩平衡通道 • 如何更改它们 允许访问颜色平衡设置。如果 元素支持这个接口&#xff0c;只需将其转发给应用…...

在wsl2中安装ubuntu

Linux 是操作系统内核&#xff0c;Ubuntu 是基于Linux的发行版。 虚拟机 是运行操作系统的虚拟环境&#xff0c;可以在物理机上运行多个操作系统&#xff0c;包括Linux和Ubuntu。 1&#xff1a;启用 WSL 功能 以管理员身份打开 PowerShell。(winR&#xff0c;输入powershell&…...

SPFA算法——负权图且没有负环

SPFA算法其实是对Bellman-ford算法的优化&#xff0c;Bellman-ford算法更新最短路是采用的是遍历每一条边&#xff0c;找到最短的边进行更新d[v]min(d[v],d[u]w(u,v))&#xff0c;由 d[v]min(d[v],d[u]w(u,v))可知只有当 d[ u ]变小时才有可能更新&#xff0c;所以用一个队列存…...

5G基本概念

作者:私语茶馆 1. 5G应用场景概述 1.1.5G应用场景 ITU域2015年定义了三大应用场景:eMBB(增强型移动宽带)、uRLLC(低时延高可靠通信)、mMTC(海量物联网通信); emBB:Enhanced Mobile Broadband ,移动互联网应用,是4G MBB(移动宽带)的升级,主要侧重于网络速率、带…...

conda 安装软件报错 Found conflicts! Looking for incompatible packages.

问题描述&#xff1a; 利用 conda 安装某包 conda install -c "nvidia/label/cuda-11.8.0" cuda-nvcc时发现报错&#xff1a; Collecting package metadata (current_repodata.json): done Solving environment: failed with initial frozen solve. Retrying with…...

PySide(PyQT),QGraphicsItem的pos()和scenePos()区别

在QGraphicsItem中&#xff0c;pos()和scenePos()是两个重要的方法&#xff0c;用于描述图形项的位置&#xff0c;但它们的含义和用途有所不同。理解它们的区别对于正确操作和管理QGraphicsItem的位置至关重要。 1. pos()方法 • 定义&#xff1a;pos()返回的是QGraphicsItem在…...

【每日八股】计算机网络篇(四):HTTP

目录 HTTP 与 HTTPS 的区别&#xff1f;HTTPS 加密与认证的过程&#xff1f;ClientHelloServerHello客户端回应服务端回应 HTTPS 一定安全可靠吗&#xff1f;HTTPS 状态码的含义&#xff1f;HTTP 缓存有哪些实现方式&#xff1f;HTTP 1.0、HTTP 1.1、HTTP 2.0 和 HTTP 3.0 的区…...

基于python下载ERA5小时尺度和月尺度的数据

前言&#xff1a;由于ERA5网站的更新&#xff0c;原始的代码都无法使用&#xff0c;这里将会提供下载小时尺度和月尺度的代码。 一、前期的工作 需要重新在ERA5网站上注册新的账号&#xff08;ERA5网站&#xff09;。然后在User guide里&#xff0c;选择API&#xff0c;将代码…...

【一起学Rust | Tauri2.0框架】基于 Rust 与 Tauri 2.0 框架实现软件开机自启

文章目录 前言 一、准备工作1.1 环境搭建1.2 创建 Tauri 项目1.3 添加依赖 二、实现开机自启的基本原理2.1 开机自启的基本概念2.2 Tauri 应用的生命周期 三、Windows 平台实现3.1 Windows 注册表机制3.2 实现步骤3.3 注意事项 四、Linux 平台实现4.1 Linux systemd 服务4.2 实…...

C++20 模块:告别头文件,迎接现代化的模块系统

文章目录 引言一、C20模块简介1.1 传统头文件的局限性1.2 模块的出现 二、模块的基本概念2.1 模块声明2.2 模块接口单元2.3 模块实现单元 三、模块的优势3.1 编译时间大幅减少3.2 更好的依赖管理3.3 命名空间隔离 四、如何使用C20模块4.1 编译器支持4.2 示例项目4.3 编译和运行…...

【技海登峰】Kafka漫谈系列(五)Java客户端之生产者Producer核心组件与实现原理剖析

【技海登峰】Kafka漫谈系列(五)Java客户端之生产者Producer核心组件与实现原理剖析 向Kafka Broker服务节点中发送主题消息数据的应用程序被称为生产者,生产者与消费者均属于Kafka客户端,几乎所有主流语言都支持调用客户端API。官方提供了基于Java实现的kafka-clients,用于…...