從零開始實現大語言模型(十三):預訓練大語言模型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的訓練樣本,然后執行這個操作直至收斂的過程。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/72698.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/72698.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/72698.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

QWQ大模型評測榜單

評測榜單說明 在數學推理基準AIME24上&#xff0c;QwQ-32B達到了79.5分&#xff0c;幾乎與DeepSeek-R1-617B的79.8分持平&#xff0c;遠超OpenAI o1-mini的63.6分&#xff0c;及相同尺寸的R1蒸餾模型。 在編程能力方面&#xff0c;QwQ-32B 在LiveCodeBench上獲得了63.4分&…

bash: uwsgi: 未找到命令

針對你提出的“bash: uwsgi: command not found”問題&#xff0c;以下是一些可能的解決方案&#xff0c;請按照步驟逐一排查&#xff1a; ?1、檢查uwsgi命令是否正確?&#xff1a; 確保你輸入的命令是uwsgi&#xff0c;而不是uWSGI或其他變體。 ?2、確認uwsgi是否已安裝?&…

超圖(Hypergraph)

超圖&#xff08;Hypergraph&#xff09;是圖結構學習&#xff08;Graph Learning&#xff09;中的一種擴展形式&#xff0c;它比傳統圖&#xff08;Graph&#xff09;更具表達能力&#xff0c;適用于建模復雜的多元關系。 超圖是一種由 超節點&#xff08;Hypernodes&#xff…

PyTorch中的線性變換:nn.Parameter VS nn.Linear

self.weight nn.Parameter(torch.randn(in_channels, out_channels)) 和 self.linear nn.Linear(in_channels, out_channels) 并不完全一致&#xff0c;盡管它們都可以用于實現線性變換&#xff08;即全連接層&#xff09;&#xff0c;但它們的使用方式和內部實現有所不同。 …

鴻蒙生態日日新,夸克、順豐速運、駕校一點通等多款應用功能更新

3月5日鴻蒙生態日日新PLOG&#xff1a;吉事辦、健康甘肅等政務服務App上架原生鴻蒙應用市場&#xff1b;夸克、順豐速運、駕校一點通等多款應用功能更新。

基于SpringBoot的智慧停車場小程序(源碼+論文+部署教程)

運行環境 ? 前端&#xff1a;小程序 Vue ? 后端&#xff1a;Java ? IDE工具&#xff1a;IDEA&#xff08;可自行選擇&#xff09; HBuilderX 微信開發者工具 ? 技術棧&#xff1a;小程序 SpringBoot Vue MySQL 主要功能 智慧停車場微信小程序主要包含小程序端和…

致同報告:香港財政赤字加劇,擴大稅基與增收迫在眉睫

2月26日香港政府2025-26年度財政預算案&#xff0c;&#xff08;以下簡稱“預算案”&#xff09;發布&#xff0c;香港財政司司長陳茂波提出一系列旨在減少開支并振興香港經濟的措施&#xff0c;以應對日益增長的財政赤字。主要提案包括對所有公務員實施凍薪、針對性稅務寬減措…

在Spring Boot項目中分層架構

常見的分層架構包括以下幾層: 1. Domain 層(領域層) 作用:領域層是業務邏輯的核心,包含與業務相關的實體類、枚舉、值對象等。它是對業務領域的抽象,通常與數據庫表結構直接映射。 主要組件: 實體類(Entity):與數據庫表對應的Java類,通常使用JPA或MyBatis等ORM框架…

實訓任務2.2 使用Wireshark捕獲數據包并分析

目錄 【實訓目標】 【實訓環境】 【實訓內容】 【實訓步驟】 1.啟動WireShark 2. 使用Wireshark捕獲數據包 &#xff08;1&#xff09;選擇網絡接口 &#xff08;2&#xff09;捕獲數據包 &#xff08;1&#xff09;設置Wireshark過濾器并捕獲數據包 &#xff08;2&…

工業自動化核心:BM100 信號隔離器的強大力量

安科瑞 呂夢怡 18706162527 BM100系列信號隔離器可以對電流、電壓等電量參數或溫度、電阻等非電量參數進行快速精確測量&#xff0c;經隔 離轉換成標準的模擬信號輸出。既可以直接與指針表、數顯表相接&#xff0c;也可以與自控儀表&#xff08;如PLC&#xff09;、各種 A/D …

并發編程——累加器

目錄 1 AtomicLong 1.1 核心功能 1.2 實現原理&#xff1a; (1&#xff09;基于 Unsafe 的底層操作 (2) volatile字段的內存可見性 (3&#xff09;CAS 操作與 ABA 問題 1.3 性能分析 1.4 使用場景 2 LongAdder 核心設計原理 1 分段存儲 2 分散更新策略 3.處理高競…

大模型管理工具:LLaMA-Factory

目錄 一、安裝與環境配置 二、?啟動 Web 界面 三、數據準備 四、模型訓練 五、模型評估 七、模型導出 八、API服務部署 LLaMA-Factory 是一個開源的大語言模型&#xff08;LLM&#xff09;微調框架&#xff0c;旨在簡化大規模模型的訓練、微調和部署流程。它支持多種主…

推流項目的ffmpeg配置和流程重點總結一下

ffmpeg的初始化配置&#xff0c;在合成工作都是根據這個ffmpeg的配置來做的&#xff0c;是和成ts流還是flv&#xff0c;是推動遠端還是保存到本地&#xff0c; FFmpeg 的核心數據結構&#xff0c;負責協調編碼、封裝和寫入操作。它相當于推流的“總指揮”。 先來看一下ffmpeg的…

大語言模型從理論到實踐(第二版)-學習筆記(緒論)

大語言模型的基本概念 1.理解語言是人工智能算法獲取知識的前提 2.語言模型的目標就是對自然語言的概率分布建模 3.詞匯表 V 上的語言模型&#xff0c;由函數 P(w1w2 wm) 表示&#xff0c;可以形式化地構建為詞序列 w1w2 wm 的概率分布&#xff0c;表示詞序列 w1w2 wm…

strace工具的交叉編譯

1、下載源碼 git clone https://github.com/strace/strace.git cd strace 2、運行 bootstrap 腳本&#xff08;如果需要&#xff09; 如果源碼中沒有 configure 腳本&#xff0c;運行以下命令生成&#xff1a; ./bootstrap 3. 配置編譯參數 運行 configure 腳本&#xff…

Vue 3 組件庫持續集成 (CI) 實戰:GitHub Actions 自動化測試與 Storybook 文檔構建 - 構建高效可靠的組件庫 CI 流程

引言 歡迎再次回到 Vue 3 + 現代前端工程化 系列技術博客! 在昨天的第十篇博客中,我們深入學習了代碼覆蓋率分析,掌握了利用 Jest 代碼覆蓋率報告提升單元測試有效性的方法,進一步鞏固了組件庫的質量防線。 今天,我們將邁向 自動化流程 的構建,聚焦于 持續集成 (Continu…

無穿戴動捕數字人互動方案 | 暢享零束縛、高沉浸的虛實交互體驗

在數字化浪潮席卷而來的當下&#xff0c;虛擬人互動體驗正逐漸成為各領域的新寵。長久以來&#xff0c;虛擬人驅動主要依靠穿戴式動作捕捉設備&#xff0c;用戶需要通過佩戴傳感器或標記點來實現動作捕捉。然而&#xff0c;隨著技術的不斷突破&#xff0c;一種全新的無穿戴動作…

03 HarmonyOS Next儀表盤案例詳解(二):進階篇

溫馨提示&#xff1a;本篇博客的詳細代碼已發布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下載運行哦&#xff01; 文章目錄 前言1. 響應式設計1.1 屏幕適配1.2 彈性布局 2. 數據展示與交互2.1 數據卡片渲染2.2 圖表區域 3. 事件處理機制3.1 點擊事件處理3.2 手勢…

python-leetcode-統計構造好字符串的方案數

2466. 統計構造好字符串的方案數 - 力扣&#xff08;LeetCode&#xff09; 這個問題可以用**動態規劃&#xff08;DP&#xff09;**來解決&#xff0c;思路如下&#xff1a; 思路 1. 定義 DP 數組 設 dp[i] 表示長度為 i 的好字符串的個數。 2. 狀態轉移方程 我們可以在 dp…

MySQL------存儲引擎和用戶和授權

9.存儲引擎 1.兩種引擎 MyISAM和InnoDB 2.兩種區別 1.事務&#xff1a; MyISAM不支持事務 2.存儲文件: innodb : frm、ibd MyISAM: frm、MYD、MYI 3.數據行鎖定: MyISAM不支持 4.全文索引: INNODB不支持&#xff0c;所以MYISAM做select操作速度很快 5.外鍵約束: MyISAM…