NLP:人名分類器案例分享

本文目錄:

  • 一、案例介紹
    • (一)關于人名分類
    • (二)人名分類數據預覽
  • 二、案例步驟
    • (一)導入工具包
    • (二)數據預處理
      • 1. 獲取常用的字符數量
      • 2. 國家名種類數和個數
      • 3.讀數據到內存
      • 4.構建數據源NameClassDataset
      • 5.構建迭代器遍歷數據
  • 三、構建RNN模型(選擇LSTM模型)
    • (一)構建模型
    • (二)模型測試
  • 四、構建訓練函數并進行訓練
    • (一)構建RNN訓練函數
    • (二)LSTM模型訓練
    • (三)模型訓練日志數據制圖
    • (四)模型訓練結果分析
      • 1.損失對比曲線分析
      • 2 .訓練耗時分析
      • 3. 訓練準確率分析
      • 4.結論
  • 五、模型預測
  • 最后,附贈代碼完整版(包括傳統RNN、LSTM和GRU建模及預測)

前言:前面介紹了傳統RNN、LSTM、GRU,本篇文章分享綜合案例。

一、案例介紹

(一)關于人名分類

以一個人名為輸入, 使用模型幫助我們判斷它最有可能是來自哪一個國家的人名, 這在某些國際化公司的業務中具有重要意義, 在用戶注冊過程中, 會根據用戶填寫的名字直接給他分配可能的國家或地區選項, 以及該國家或地區的國旗, 限制手機號碼位數等等。

(二)人名分類數據預覽

數據存放路徑:$(home)/data/name_classfication.txt

數據格式說明 每一行第一個單詞為人名,第二個單詞為國家名。中間用制表符tab分割。

Huffmann    German
Hummel  German
Hummel  German
Hutmacher   German
Ingersleben German
Jaeger  German
Jager   German
Deng    Chinese
Ding    Chinese
Dong    Chinese
Dou Chinese
Duan    Chinese
Eng Chinese
Fan Chinese
Fei Chinese
Abaimov Russian
Abakeliya   Russian
Abakovsky   Russian
Abakshin    Russian
Abakumoff   Russian
Abakumov    Russian
Abakumtsev  Russian
Abakushin   Russian
Abalakin    Russian

二、案例步驟

整個案例的實現可分為以下五個步驟:

第一步導入必備的工具包

第二步對data文件中的數據進行處理,滿足訓練要求

第三步構建RNN模型(選擇 LSTM)

第四步構建訓練函數并進行訓練

第五步構建預測函數并進行預測

(一)導入工具包

# 導入torch工具
import torch
# 導入nn準備構建模型
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
# 導入torch的數據源 數據迭代器工具包
from  torch.utils.data import Dataset, DataLoader
# 用于獲得常見字母及字符規范化
import string
# 導入時間工具包
import time
# 引入制圖工具包  
import matplotlib.pyplot as plt
# 從io中導入文件打開方法
from io import open

(二)數據預處理

這里需要對data文件中的數據進行處理,滿足訓練要求。

1. 獲取常用的字符數量

# 獲取所有常用字符包括字母和常用標點
all_letters = string.ascii_letters + " .,;'"# 獲取常用字符數量
n_letters = len(all_letters)print("n_letter:", n_letters)

運行結果:

n_letter: 57

2. 國家名種類數和個數

# 國家名 種類數
categorys = ['Italian', 'English', 'Arabic', 'Spanish', 'Scottish', 'Irish', 'Chinese', 'Vietnamese', 'Japanese','French', 'Greek', 'Dutch', 'Korean', 'Polish', 'Portuguese', 'Russian', 'Czech', 'German']
# 國家名 個數
categorynum = len(categorys)
print('categorys--->', categorys)

運行結果:

categorys---> ['Italian', 'English', 'Arabic', 'Spanish', 'Scottish', 'Irish', 'Chinese', 'Vietnamese', 'Japanese', 'French', 'Greek', 'Dutch', 'Korean', 'Polish', 'Portuguese', 'Russian', 'Czech', 'German']
categorynum---> 18

3.讀數據到內存

# 思路分析
# 1 打開數據文件 open(filename, mode='r', encoding='utf-8')
# 2 按行讀文件、提取樣本x 樣本y line.strip().split('\t')
# 3 返回樣本x的列表、樣本y的列表 my_list_x, my_list_y
def read_data(filename):my_list_x, my_list_y= [], []# 打開文件with  open(filename, mode='r', encoding='utf-8') as f:# 按照行讀數據for line in f.readlines():if len(line) <= 5:continue# 按照行提取樣本x 樣本y(x, y) = line.strip().split('\t')my_list_x.append(x)my_list_y.append(y)# 打印樣本的數量print('my_list_x->', len(my_list_x))print('my_list_y->', len(my_list_y))# 返回樣本x的列表、樣本y的列表return my_list_x, my_list_y

4.構建數據源NameClassDataset

# 原始數據 -> 數據源NameClassDataset --> 數據迭代器DataLoader
# 構造數據源 NameClassDataset,把語料轉換成x y
# 1 init函數 設置樣本x和y self.my_list_x self.my_list_y 條目數self.sample_len
# 2 __len__(self)函數  獲取樣本條數
# 3 __getitem__(self, index)函數 獲取第幾條樣本數據
#       按索引 獲取數據樣本 x y
#       樣本x one-hot張量化 tensor_x[li][all_letters.find(letter)] = 1
#       樣本y 張量化 torch.tensor(categorys.index(y), dtype=torch.long)
#       返回tensor_x, tensor_y
class NameClassDataset(Dataset):def __init__(self, my_list_x, my_list_y):# 樣本xself.my_list_x = my_list_x# 樣本yself.my_list_y = my_list_y# 樣本條目數self.sample_len = len(my_list_x)# 獲取樣本條數def __len__(self):return self.sample_len# 獲取第幾條 樣本數據def __getitem__(self, index):# 對index異常值進行修正 [0, self.sample_len-1]index = min(max(index, 0), self.sample_len-1)# 按索引獲取 數據樣本 x yx = self.my_list_x[index]y = self.my_list_y[index]# 樣本x one-hot張量化tensor_x = torch.zeros(len(x), n_letters)# 遍歷人名 的 每個字母 做成one-hot編碼for li, letter in enumerate(x):# letter2indx 使用all_letters.find(letter)查找字母在all_letters表中的位置 給one-hot賦值tensor_x[li][all_letters.find(letter)] = 1# 樣本y 張量化tensor_y = torch.tensor(categorys.index(y), dtype=torch.long)# 返回結果return tensor_x, tensor_y

分析

文本張量化,這里也就是人名張量化是通過one-hot編碼來完成。

# 將字符串(單詞粒度)轉化為張量表示,如:"ab" --->
# tensor([[[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., 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.]]])

5.構建迭代器遍歷數據

def dm_test_NameClassDataset():# 1 獲取數據myfilename = './data/name_classfication.txt'my_list_x, my_list_y = read_data(myfilename)print('my_list_x length', len(my_list_x))print('my_list_y length', len(my_list_y))# 2 實例化dataset對象nameclassdataset = NameClassDataset(my_list_x, my_list_y)# 3 實例化dataloadermydataloader = DataLoader(dataset=nameclassdataset, batch_size=1, shuffle=True)for  i, (x, y) in enumerate (mydataloader):print('x.shape', x.shape, x)print('y.shape', y.shape, y)break

運行結果:

my_list_x length 20074
my_list_y length 20074
x.shape torch.Size([1, 5, 57]) tensor([[[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., 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., 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., 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., 0., 0., 0.,0., 0., 0., 0., 0., 0., 0., 0., 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.],[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.]]])
y.shape torch.Size([1]) tensor([15])

三、構建RNN模型(選擇LSTM模型)

(一)構建模型

# LSTM類 實現思路分析:
# 1 init函數 準備三個層 self.rnn self.linear self.softmax=nn.LogSoftmax(dim=-1)
#    def __init__(self, input_size, hidden_size, output_size, num_layers=1)# 2 forward(input, hidden)函數
#   讓數據經過三個層 返回softmax結果和hn
#   形狀變化 [seqlen,1,57],[1,1,128]) -> [seqlen,1,128],[1,1,128]# 3 初始化隱藏層輸入數據 inithidden()
#   形狀[self.num_layers, 1, self.hidden_size]
class LSTM(nn.Module):def __init__(self, input_size, hidden_size, output_size, num_layers=1):super(LSTM, self).__init__()# 1 init函數 準備三個層 self.rnn self.linear self.softmax=nn.LogSoftmax(dim=-1)self.input_size = input_sizeself.hidden_size = hidden_sizeself.output_size = output_sizeself.num_layers = num_layers# 定義rnn層self.rnn = nn.LSTM(self.input_size, self.hidden_size, self.num_layers)# 定義linear層self.linear = nn.Linear(self.hidden_size, self.output_size)# 定義softmax層self.softmax = nn.LogSoftmax(dim=-1)def forward(self, input, hidden, c):# 讓數據經過三個層 返回softmax結果和 hn c# 數據形狀 [6,57] -> [6,1,52]input = input.unsqueeze(1)# 把數據送給模型 提取事物特征# 數據形狀 [seqlen,1,57],[1,1,128], [1,1,128]) -> [seqlen,1,18],[1,1,128],[1,1,128]rr, (hn, cn) = self.rnn(input, (hidden, c))# 數據形狀 [seqlen,1,128] - [1, 128]tmprr = rr[-1]tmprr = self.linear(tmprr)return self.softmax(tmprr), hn, cndef inithidden(self):# 初始化隱藏層輸入數據 inithidden()hidden = c = torch.zeros(self.num_layers, 1, self.hidden_size)return hidden, c

(二)模型測試

def dm_test_rnn_lstm_gru():# one-hot編碼特征57(n_letters),也是RNN的輸入尺寸input_size = 57# 定義隱層的最后一維尺寸大小n_hidden = 128# 輸出尺寸為語言類別總數n_categories # 1個字符預測成18個類別output_size = 18# 1 獲取數據myfilename = './data/name_classfication.txt'my_list_x, my_list_y  = read_data(myfilename)print('categorys--->', categorys)# 2 實例化dataset對象nameclassdataset = NameClassDataset(my_list_x, my_list_y)# 3 實例化dataloadermydataloader = DataLoader(dataset=nameclassdataset, batch_size=1, shuffle=True)my_lstm = LSTM(n_letters, n_hidden, categorynum)print('lstm 模型', my_lstm)for  i, (x, y) in enumerate (mydataloader):# print('x.shape', x.shape, x)# print('y.shape', y.shape, y)hidden, c = my_lstm.inithidden()output, hidden, c = my_lstm(x[0], hidden, c)print("lstm output.shape--->:", output.shape, output)if (i == 0):break

運行結果:

lstm 模型 LSTM((rnn): LSTM(57, 128)(linear): Linear(in_features=128, out_features=18, bias=True)(softmax): LogSoftmax(dim=-1)
)
lstm output.shape--->: torch.Size([1, 18]) tensor([[-2.9283, -3.0017, -2.8902, -2.8179, -2.8484, -2.8152, -2.9654, -2.8846,-2.8642, -2.8602, -2.8860, -2.9505, -2.8806, -2.9436, -2.8388, -2.9312,-2.9241, -2.8211]], grad_fn=<LogSoftmaxBackward0>)

四、構建訓練函數并進行訓練

(一)構建RNN訓練函數

# 思路分析
# 從文件獲取數據、實例化數據源對象nameclassdataset 數據迭代器對象mydataloader
# 實例化模型對象my_rnn 損失函數對象mycrossentropyloss=nn.NLLLoss() 優化器對象myadam
# 定義模型訓練的參數
#       starttime total_iter_num total_loss  total_loss_list total_acc_num  total_acc_list
# 外層for循環 控制輪數 for epoch_idx in range(epochs)
# 內層for循環 控制迭代次數 for i, (x, y) in enumerate(mydataloader)# 給模型喂數據   # 計算損失  # 梯度清零 # 反向傳播  # 梯度更新# 計算輔助信息   # 累加總損失和準確數 每100次訓練計算一個總體平均損失 總體平均準確率 每2000次訓練 打印日志# 其他          # 預測對錯 i_predit_tag = (1 if torch.argmax(output).item() == y.item() else 0)# 模型保存# torch.save(my_rnn.state_dict(), './my_rnn_model_%d.bin' % (epoch_idx + 1))
# 返回 平均損失列表total_loss_list, 時間total_time, 平均準確total_acc_list

(二)LSTM模型訓練

def my_train_lstm():# 獲取數據myfilename = './data/name_classfication.txt'my_list_x, my_list_y = read_data(myfilename)# 實例化dataset對象nameclassdataset = NameClassDataset(my_list_x, my_list_y)# 實例化 模型input_size = 57n_hidden = 128output_size = 18my_lstm = LSTM(input_size, n_hidden, output_size)print('my_lstm模型--->', my_lstm)# 實例化 損失函數 adam優化器mycrossentropyloss = nn.NLLLoss()myadam = optim.Adam(my_lstm.parameters(), lr=mylr)# 定義模型訓練參數starttime = time.time()total_iter_num = 0  # 已訓練的樣本數total_loss = 0.0  # 已訓練的損失和total_loss_list = []  # 每100個樣本求一次平均損失 形成損失列表total_acc_num = 0  # 已訓練樣本預測準確總數total_acc_list = []  # 每100個樣本求一次平均準確率 形成平均準確率列表# 外層for循環 控制輪數for epoch_idx in range(epochs):# 實例化dataloadermydataloader = DataLoader(dataset=nameclassdataset, batch_size=1, shuffle=True)# 內層for循環 控制迭代次數for i, (x, y) in enumerate(mydataloader):# 給模型喂數據hidden, c = my_lstm.inithidden()output, hidden, c = my_lstm(x[0], hidden, c)# 計算損失myloss = mycrossentropyloss(output, y)# 梯度清零myadam.zero_grad()# 反向傳播myloss.backward()# 梯度更新myadam.step()# 計算總損失total_iter_num = total_iter_num + 1total_loss = total_loss + myloss.item()# 計算總準確率i_predit_tag = (1 if torch.argmax(output).item() == y.item() else 0)total_acc_num = total_acc_num + i_predit_tag# 每100次訓練 求一次平均損失 平均準確率if (total_iter_num % 100 == 0):tmploss = total_loss/total_iter_numtotal_loss_list.append(tmploss)tmpacc = total_acc_num/total_iter_numtotal_acc_list.append(tmpacc)# 每2000次訓練 打印日志if (total_iter_num % 2000 == 0):tmploss = total_loss / total_iter_numprint('輪次:%d, 損失:%.6f, 時間:%d,準確率:%.3f' %(epoch_idx+1, tmploss, time.time() - starttime, tmpacc))# 每個輪次保存模型torch.save(my_lstm.state_dict(), './my_lstm_model_%d.bin' % (epoch_idx + 1))# 計算總時間total_time = int(time.time() - starttime)return total_loss_list, total_time, total_acc_list

(三)模型訓練日志數據制圖

def dm_test_train_rnn_lstm_gru():total_loss_list_rnn, total_time_rnn, total_acc_list_rnn = my_train_rnn()total_loss_list_lstm, total_time_lstm, total_acc_list_lstm = my_train_lstm()total_loss_list_gru, total_time_gru, total_acc_list_gru = my_train_gru()# 繪制損失對比曲線# 創建畫布0plt.figure(0)# # 繪制損失對比曲線plt.plot(total_loss_list_rnn, label="RNN")plt.plot(total_loss_list_lstm, color="red", label="LSTM")plt.plot(total_loss_list_gru, color="orange", label="GRU")plt.legend(loc='upper left')plt.savefig('./img/RNN_LSTM_GRU_loss2.png')plt.show()# 繪制柱狀圖# 創建畫布1plt.figure(1)x_data = ["RNN", "LSTM", "GRU"]y_data = [total_time_rnn, total_time_lstm, total_time_gru]# 繪制訓練耗時對比柱狀圖plt.bar(range(len(x_data)), y_data, tick_label=x_data)plt.savefig('./img/RNN_LSTM_GRU_period2.png')plt.show()# 繪制準確率對比曲線plt.figure(2)plt.plot(total_acc_list_rnn, label="RNN")plt.plot(total_acc_list_lstm, color="red", label="LSTM")plt.plot(total_acc_list_gru, color="orange", label="GRU")plt.legend(loc='upper left')plt.savefig('./img/RNN_LSTM_GRU_acc2.png')plt.show()

模型訓練日志輸出:

輪次:3, 損失:0.805885, 時間:118,準確率:0.759
輪次:3, 損失:0.794148, 時間:123,準確率:0.762
輪次:3, 損失:0.783356, 時間:128,準確率:0.765
輪次:3, 損失:0.774931, 時間:133,準確率:0.767
輪次:3, 損失:0.765427, 時間:137,準確率:0.769
輪次:3, 損失:0.757254, 時間:142,準確率:0.771
輪次:3, 損失:0.750375, 時間:147,準確率:0.773
輪次:3, 損失:0.743092, 時間:152,準確率:0.775
輪次:4, 損失:0.732983, 時間:157,準確率:0.778
輪次:4, 損失:0.723816, 時間:162,準確率:0.780
輪次:4, 損失:0.716507, 時間:167,準確率:0.782
輪次:4, 損失:0.708377, 時間:172,準確率:0.785
輪次:4, 損失:0.700820, 時間:177,準確率:0.787
輪次:4, 損失:0.694714, 時間:182,準確率:0.788
輪次:4, 損失:0.688386, 時間:187,準確率:0.790
輪次:4, 損失:0.683056, 時間:191,準確率:0.791
輪次:4, 損失:0.677051, 時間:196,準確率:0.793
輪次:4, 損失:0.671668, 時間:201,準確率:0.794

(四)模型訓練結果分析

1.損失對比曲線分析

在這里插入圖片描述
左圖:1個輪次損失對比曲線,右圖4個輪次損失對比曲線

模型訓練的損失降低快慢代表模型收斂程度。由圖可知, 傳統RNN的模型第一個輪次開始收斂情況最好,然后是GRU, 最后是LSTM, 這是因為RNN模型簡單參數少,見效快。隨著訓練數據的增加,GRU效果最好、LSTM效果次之、RNN效果排最后。

所以在以后的模型選用時, 要通過對任務的分析以及實驗對比, 選擇最適合的模型。

2 .訓練耗時分析

訓練耗時對比圖:
在這里插入圖片描述
模型訓練的耗時長短代表模型的計算復雜度,由圖可知, 也正如我們之前的理論分析,傳統RNN復雜度最低, 耗時幾乎只是后兩者的一半, 然后是GRU,最后是復雜度最高的LSTM。

3. 訓練準確率分析

訓練準確率對比圖:
在這里插入圖片描述
由圖可知, GRU效果最好、LSTM效果次之、RNN效果排最后。

4.結論

模型選用一般應通過實驗對比,并非越復雜或越先進的模型表現越好,而是需要結合自己的特定任務,從對數據的分析和實驗結果中獲得最佳答案。

五、模型預測

def my_predict_lstm(x):n_letters = 57n_hidden = 128n_categories = 18# 輸入文本, 張量化one-hotx_tensor = lineToTensor(x)# 實例化模型 加載已訓練模型參數my_lstm = LSTM(n_letters, n_hidden, n_categories)my_lstm.load_state_dict(torch.load(my_path_lstm))with torch.no_grad():# 模型預測hidden, c = my_lstm.inithidden()output, hidden, c = my_lstm(x_tensor, hidden, c)# 從預測結果中取出前3名# 3表示取前3, 1表示要排序的維度, True表示是否返回最大或是最下的元素topv, topi = output.topk(3, 1, True)print('rnn =>', x)for i in range(3):value = topv[0][i]category_idx = topi[0][i]category = categorys[category_idx]print('\t value:%d  category:%s' % (value, category))print('\t value:%d  category:%s' % (value, category))

運行結果:

rnn => zhangvalue:0  category:Chinesevalue:-1  category:Russianvalue:-1  category:German

本案例也可以構建傳統rnn模型或者gru模型進行目標完成,具體大家可自行嘗試。

最后,附贈代碼完整版(包括傳統RNN、LSTM和GRU建模及預測)

# -*-coding:utf-8-*-
# 導入torch工具
import torch
# 導入nn準備構建模型
import torch.nn as nn
#導入優化器optim
import torch.optim as optim
# 導入torch的數據源 數據迭代器工具包
from  torch.utils.data import Dataset, DataLoader
# 用于獲得常見字母及字符規范化
import string
# 導入時間工具包
import time
# 引入制圖工具包
import matplotlib.pyplot as plt
from tqdm import tqdm
import json# 1.todo: 獲取常用的字符數量
# 此次將人名變成向量的過程:將人名中的每個字母(字符)進行one-hot張量表示,然后拼接代表整個人名的向量表示
# 因為人名的組成大部分都是由大小寫英文字母以及某些特殊的字符組成,這里一個展示是57個,其實就是one-hot編碼的維度all_letters = string.ascii_letters+" .,;'"
print(f'all_letters--》{all_letters}')
print(f'{all_letters.find("A")}')
n_letters = len(all_letters)
print('字符的總個數', n_letters)# 2 todo: 獲取國家的類別個數
# 國家名 種類數
categorys = ['Italian', 'English', 'Arabic', 'Spanish', 'Scottish', 'Irish', 'Chinese', 'Vietnamese', 'Japanese','French', 'Greek', 'Dutch', 'Korean', 'Polish', 'Portuguese', 'Russian', 'Czech', 'German']
# 國家名 個數
categorynum = len(categorys)
print('categorys--->', categorynum)# 3 todo. 讀取數據到內存中
def read_data(filename):# 定義兩個空列表,分別存儲人名和國家名my_list_x, my_list_y = [], []# 讀取數據with open(filename, 'r', encoding='utf-8') as fr:for line in fr.readlines():# 數據清洗if len(line) <= 5:continuex, y = line.strip().split('\t')my_list_x.append(x)my_list_y.append(y)return my_list_x, my_list_y# 4 todo. 構建dataset類
class NameClassDataset(Dataset):def __init__(self, my_list_x, my_list_y):# 如果繼承的父類沒有__init__方法,那么此時可以省略掉super().__init__(),當然要是寫上也不會報錯# super().__init__()# 獲取樣本xself.my_list_x = my_list_x# 獲取樣本x對應的標簽yself.my_list_y = my_list_y# 獲取樣本的長度self.sample_len = len(my_list_x)def __len__(self):return self.sample_lendef __getitem__(self, item):# item代表就是索引index = min(max(item, 0), self.sample_len-1)# 根據索引取出對應的x和yx = self.my_list_x[index]# print(f'x---->{x}')y = self.my_list_y[index]# print(f'y---》{y}')# 初始化全零的一個張量tensor_x = torch.zeros(len(x), n_letters)# 遍歷人名的每個字母變成one-hot編碼for idx, letter in enumerate(x):tensor_x[idx][all_letters.find(letter)] = 1# print(f'tensor_x--》{tensor_x}')tensor_y = torch.tensor(categorys.index(y), dtype=torch.long)return tensor_x, tensor_y# 5 todo. 實例化Dataloader
def get_dataloader():my_list_x, my_list_y = read_data(filename='./data/name_classfication.txt')nameClass_dataset = NameClassDataset(my_list_x, my_list_y)# 實例化Dataloadertrain_dataloader = DataLoader(dataset=nameClass_dataset,batch_size=1,shuffle=True)# for tensor_x, tensor_y in train_dataloader:#     print(f'tensor_x--》{tensor_x.shape}')#     print(f'tensor_y--》{tensor_y.shape}')#     breakreturn train_dataloader# 6 todo. 定義RNN模型
class NameRNN(nn.Module):def __init__(self, input_size, hidden_size, output_size, num_layers=1):super().__init__()# input_size-->輸入x單詞的詞嵌入維度self.input_size = input_size# hidden_size-->RNN輸出的隱藏層維度self.hidden_size = hidden_size# output_size-->國家類別的總個數self.output_size = output_size# num_layers:幾層隱藏層self.num_layers = num_layers# 實例化RNN對象# batch_first=False,默認self.rnn = nn.RNN(input_size, hidden_size, num_layers)# 定義輸出層self.out = nn.Linear(hidden_size, output_size)# 定義logsoftmax層self.softmax = nn.LogSoftmax(dim=-1)def forward(self, input_x, hidden):# input_x按照講義,輸入的時候,是個二維的【seq_len, input_size】-->[6, 57]# hidden:初始化隱藏層的值:[1, 1, 128]# 升維度,在dim=1的維度進行升維:input_x-->[6, 1, 57]input_x = input_x.unsqueeze(dim=1)# 將input_x和hidden送入rnn:rnn_output-->shape--[6,1,128];hn-->[1, 1, 128]rnn_output, hn = self.rnn(input_x, hidden)# 將上述rnn的結果經過輸出層;rnn_output[-1]獲取最后一個單詞的詞向量代表整個句子的語意# temp_vec-->[1, 128]temp_vec = rnn_output[-1]# 將temp_vec送入輸出層:result-->[1, 18]result = self.out(temp_vec)return self.softmax(result), hndef inithidden(self):return torch.zeros(self.num_layers, 1, self.hidden_size)# 7 todo. 定義LSTM模型
class NameLSTM(nn.Module):def __init__(self, input_size, hidden_size, output_size, num_layers=1):super().__init__()# input_size-->輸入x單詞的詞嵌入維度self.input_size = input_size# hidden_size-->RNN輸出的隱藏層維度self.hidden_size = hidden_size# output_size-->國家類別的總個數self.output_size = output_size# num_layers:幾層隱藏層self.num_layers = num_layers# 實例化LSTM對象self.lstm = nn.LSTM(input_size, hidden_size, num_layers)# 定義輸出層self.out = nn.Linear(hidden_size, output_size)# 定義logsoftmax層self.softmax = nn.LogSoftmax(dim=-1)def forward(self, input_x, h0, c0):# input_x-shape-->[seq_len, embed_dim]-->[6, 57]# h0,c0-->shape-->[num_layers, batch_size, hidden_size]-->[1, 1, 128]# 1.先對input_x升維度;shape-->[6, 1, 57]input_x = input_x.unsqueeze(dim=1)# 2.將input_x, h0,c0送入lstm模型# lstm_output-->shape=-->[6, 1, 128]lstm_output, (hn, cn) = self.lstm(input_x, (h0, c0))# 3.取出lstm輸出結果中最后一個單詞對應的隱藏層輸出結果送入輸出層# temp_vec-->shape-->[1, 128]temp_vec = lstm_output[-1]# 送入輸出層result->shape-->[1, 18]result = self.out(temp_vec)return self.softmax(result), hn, cndef inithidden(self):h0 = torch.zeros(self.num_layers, 1, self.hidden_size)c0 = torch.zeros(self.num_layers, 1, self.hidden_size)return h0, c0# 8 todo. 定義GRU模型
class NameGRU(nn.Module):def __init__(self, input_size, hidden_size, output_size, num_layers=1):super().__init__()# input_size-->輸入x單詞的詞嵌入維度self.input_size = input_size# hidden_size-->RNN輸出的隱藏層維度self.hidden_size = hidden_size# output_size-->國家類別的總個數self.output_size = output_size# num_layers:幾層隱藏層self.num_layers = num_layers# 實例化GRU對象# batch_first=False,默認self.gru = nn.GRU(input_size, hidden_size, num_layers)# 定義輸出層self.out = nn.Linear(hidden_size, output_size)# 定義logsoftmax層self.softmax = nn.LogSoftmax(dim=-1)def forward(self, input_x, hidden):# input_x按照講義,輸入的時候,是個二維的【seq_len, input_size】-->[6, 57]# hidden:初始化隱藏層的值:[1, 1, 128]# 升維度,在dim=1的維度進行升維:input_x-->[6, 1, 57]input_x = input_x.unsqueeze(dim=1)# 將input_x和hidden送入rnn:rnn_output-->shape--[6,1,128];hn-->[1, 1, 128]rnn_output, hn = self.gru(input_x, hidden)# 將上述gru的結果經過輸出層;rnn_output[-1]獲取最后一個單詞的詞向量代表整個句子的語意# temp_vec-->[1, 128]temp_vec = rnn_output[-1]# 將temp_vec送入輸出層:result-->[1, 18]result = self.out(temp_vec)return self.softmax(result), hndef inithidden(self):return torch.zeros(self.num_layers, 1, self.hidden_size)my_lr = 1e-3
epochs = 1# 9 todo: 定義RNN模型的訓練函數
def train_rnn():# 1.讀取txt文檔數據my_list_x, my_list_y = read_data(filename='./data/name_classfication.txt')# 2.實例化Dataset對象name_dataset = NameClassDataset(my_list_x, my_list_y)# 3.實例化自定義的RNN模型對象input_size = n_letters # 57hidden_size = 128output_size = categorynum # 18name_rnn = NameRNN(input_size, hidden_size, output_size)# 4.實例化損失函數對象以及優化器對象rnn_nllloss = nn.NLLLoss()rnn_adam = optim.Adam(name_rnn.parameters(), lr=my_lr)# 5.定義訓練日志的參數start_time = time.time()total_iter_num = 0 # 已經訓練的樣本的總數total_loss = 0.0 # 已經訓練的樣本的總損失total_loss_list = [] # 每隔100個樣本我們計算一下平均損失,并保存total_acc_num = 0 # 已經訓練的樣本中預測正確的個數total_acc_list = []# 每隔100個樣本我們計算一下平均準確率,并保存# 6. 開始外部迭代for epoch_idx in range(epochs):# 6.1 實例化Dataloader的對象train_dataloader = DataLoader(dataset=name_dataset, batch_size=1, shuffle=True)# 6.2 開始遍歷迭代器,內部迭代for idx, (tensor_x, tensor_y) in enumerate(tqdm(train_dataloader)):# 6.3 準備模型需要的數據tensor_x0 = tensor_x[0] # [seq_length, input_size]h0 = name_rnn.inithidden()# print(f'tensor_y--》{tensor_y}')# 6.4 將數據送入模型得到預測結果output-->shape-->[1, 18]output, hn = name_rnn(tensor_x0, h0)# print(f'output--》{output}')# 6.5 計算損失my_loss = rnn_nllloss(output, tensor_y)# print(f'my_loss--》{my_loss}')# 6.6 梯度清零rnn_adam.zero_grad()# 6.7 反向傳播my_loss.backward()# 6.8 梯度更新rnn_adam.step()# 6.9 統計已經訓練的樣本的總個數total_iter_num = total_iter_num + 1# 6.10 統計已經訓練的樣本總損失total_loss = total_loss + my_loss.item()# 6.11 統計已經訓練的樣本中預測正確的樣本總個數# torch.argmax(output)取出預測結果中最大概率值對應的索引predict_id = 1 if torch.argmax(output).item() == tensor_y.item() else 0total_acc_num = total_acc_num + predict_id# 6.12 每間隔100步,保存平均損失已經平均準確率if (total_iter_num % 100) == 0:# 計算平均損失并保存avg_loss = total_loss / total_iter_numtotal_loss_list.append(avg_loss)# 計算平均準確率并保存avg_acc = total_acc_num / total_iter_numtotal_acc_list.append(avg_acc)# 6.13 每間隔2000步,打印日志if (total_iter_num % 2000) == 0:temp_avg_loss = total_loss / total_iter_numtemp_avg_acc = total_acc_num / total_iter_numprint('輪次:%d, 損失:%.6f, 時間:%d,準確率:%.3f' %(epoch_idx+1, temp_avg_loss, time.time() - start_time, temp_avg_acc))# 7保存模型torch.save(name_rnn.state_dict(), './save_model/szAI_%d.bin'%(epoch_idx+1))total_time = time.time() - start_timernn_dict = {"total_loss_list": total_loss_list,"total_time": total_time,"total_acc_list": total_acc_list}with open('name_classify_rnn.json', 'w', encoding='utf-8') as fw:fw.write(json.dumps(rnn_dict))
def train_lstm():my_list_x, my_list_y = read_data(filename='./data/name_classfication.txt')# 2.實例化Dataset對象name_dataset = NameClassDataset(my_list_x, my_list_y)# 3.實例化自定義的RNN模型對象input_size = n_letters  # 57hidden_size = 128output_size = categorynum  # 18name_lstm = NameLSTM(input_size, hidden_size, output_size)# 4.實例化損失函數對象以及優化器對象rnn_nllloss = nn.NLLLoss()rnn_adam = optim.Adam(name_lstm.parameters(), lr=my_lr)# 5.定義訓練日志的參數start_time = time.time()total_iter_num = 0  # 已經訓練的樣本的總數total_loss = 0.0  # 已經訓練的樣本的總損失total_loss_list = []  # 每隔100個樣本我們計算一下平均損失,并保存total_acc_num = 0  # 已經訓練的樣本中預測正確的個數total_acc_list = []  # 每隔100個樣本我們計算一下平均準確率,并保存# 6. 開始外部迭代for epoch_idx in range(epochs):# 6.1 實例化Dataloader的對象train_dataloader = DataLoader(dataset=name_dataset, batch_size=1, shuffle=True)# 6.2 開始遍歷迭代器,內部迭代for idx, (tensor_x, tensor_y) in enumerate(tqdm(train_dataloader)):# 6.3 準備模型需要的數據tensor_x0 = tensor_x[0]  # [seq_length, input_size]h0,c = name_lstm.inithidden()# print(f'tensor_y--》{tensor_y}')# 6.4 將數據送入模型得到預測結果output-->shape-->[1, 18]output, hn,cn = name_lstm(tensor_x0, h0,c)# print(f'output--》{output}')# 6.5 計算損失my_loss = rnn_nllloss(output, tensor_y)# print(f'my_loss--》{my_loss}')# 6.6 梯度清零rnn_adam.zero_grad()# 6.7 反向傳播my_loss.backward()# 6.8 梯度更新rnn_adam.step()# 6.9 統計已經訓練的樣本的總個數total_iter_num = total_iter_num + 1# 6.10 統計已經訓練的樣本總損失total_loss = total_loss + my_loss.item()# 6.11 統計已經訓練的樣本中預測正確的樣本總個數# torch.argmax(output)取出預測結果中最大概率值對應的索引predict_id = 1 if torch.argmax(output).item() == tensor_y.item() else 0total_acc_num = total_acc_num + predict_id# 6.12 每間隔100步,保存平均損失已經平均準確率if (total_iter_num % 100) == 0:# 計算平均損失并保存avg_loss = total_loss / total_iter_numtotal_loss_list.append(avg_loss)# 計算平均準確率并保存avg_acc = total_acc_num / total_iter_numtotal_acc_list.append(avg_acc)# 6.13 每間隔2000步,打印日志if (total_iter_num % 2000) == 0:temp_avg_loss = total_loss / total_iter_numtemp_avg_acc = total_acc_num / total_iter_numprint('輪次:%d, 損失:%.6f, 時間:%d,準確率:%.3f' % (epoch_idx + 1, temp_avg_loss, time.time() - start_time, temp_avg_acc))# 7保存模型torch.save(name_lstm.state_dict(), './save_model/_%d.bin' % (epoch_idx + 1))total_time=time.time()-start_time# 9. 將損失列表和準確率列表以及時間保存到字典并存儲到文件里lstm_dict = {"total_loss_list": total_loss_list,"total_time": total_time,"total_acc_list": total_acc_list}with open('name_classify_lstm.json', 'w', encoding='utf-8') as fw:fw.write(json.dumps(lstm_dict))
def train_gru():# 1.讀取txt文檔數據my_list_x, my_list_y = read_data(filename='./data/name_classfication.txt')# 2.實例化Dataset對象name_dataset = NameClassDataset(my_list_x, my_list_y)# 3.實例化自定義的RNN模型對象input_size = n_letters # 57hidden_size = 128output_size = categorynum # 18name_gru = NameGRU(input_size, hidden_size, output_size)# 4.實例化損失函數對象以及優化器對象rnn_nllloss = nn.NLLLoss()rnn_adam = optim.Adam(name_gru.parameters(), lr=my_lr)# 5.定義訓練日志的參數start_time = time.time()total_iter_num = 0 # 已經訓練的樣本的總數total_loss = 0.0 # 已經訓練的樣本的總損失total_loss_list = [] # 每隔100個樣本我們計算一下平均損失,并保存total_acc_num = 0 # 已經訓練的樣本中預測正確的個數total_acc_list = []# 每隔100個樣本我們計算一下平均準確率,并保存# 6. 開始外部迭代for epoch_idx in range(epochs):# 6.1 實例化Dataloader的對象train_dataloader = DataLoader(dataset=name_dataset, batch_size=1, shuffle=True)# 6.2 開始遍歷迭代器,內部迭代for idx, (tensor_x, tensor_y) in enumerate(tqdm(train_dataloader)):# 6.3 準備模型需要的數據tensor_x0 = tensor_x[0] # [seq_length, input_size]h0 = name_gru.inithidden()# print(f'tensor_y--》{tensor_y}')# 6.4 將數據送入模型得到預測結果output-->shape-->[1, 18]output, hn = name_gru(tensor_x0, h0)# print(f'output--》{output}')# 6.5 計算損失my_loss = rnn_nllloss(output, tensor_y)# print(f'my_loss--》{my_loss}')# 6.6 梯度清零rnn_adam.zero_grad()# 6.7 反向傳播my_loss.backward()# 6.8 梯度更新rnn_adam.step()# 6.9 統計已經訓練的樣本的總個數total_iter_num = total_iter_num + 1# 6.10 統計已經訓練的樣本總損失total_loss = total_loss + my_loss.item()# 6.11 統計已經訓練的樣本中預測正確的樣本總個數# torch.argmax(output)取出預測結果中最大概率值對應的索引predict_id = 1 if torch.argmax(output).item() == tensor_y.item() else 0total_acc_num = total_acc_num + predict_id# 6.12 每間隔100步,保存平均損失已經平均準確率if (total_iter_num % 100) == 0:# 計算平均損失并保存avg_loss = total_loss / total_iter_numtotal_loss_list.append(avg_loss)# 計算平均準確率并保存avg_acc = total_acc_num / total_iter_numtotal_acc_list.append(avg_acc)# 6.13 每間隔2000步,打印日志if (total_iter_num % 2000) == 0:temp_avg_loss = total_loss / total_iter_numtemp_avg_acc = total_acc_num / total_iter_numprint('輪次:%d, 損失:%.6f, 時間:%d,準確率:%.3f' %(epoch_idx+1, temp_avg_loss, time.time() - start_time, temp_avg_acc))# 7保存模型torch.save(name_gru.state_dict(), './save_model/gru_%d.bin'%(epoch_idx+1))total_time = time.time() - start_timegru_dict = {"total_loss_list": total_loss_list,"total_time": total_time,"total_acc_list": total_acc_list}with open('name_classify_gru.json', 'w', encoding='utf-8') as fw:fw.write(json.dumps(gru_dict))
def draw_picture():with (open('name_classify_gru.json','r') as fg,open('name_classify_rnn.json','r') as fr,open('name_classify_lstm.json','r') as fl):fr=json.loads(fr.read())fg=json.loads(fg.read())fl=json.loads(fl.read())plt.figure(0)plt.plot(fr['total_loss_list'],label='rnn')plt.plot(fl['total_loss_list'],label='lstm')plt.plot(fg['total_loss_list'],label='gru')plt.legend(loc='upper left')plt.show()plt.figure(1)x_list=["RNN", "LSTM", "GRU"]plt.bar(range(len(x_list)),y=[fr['total_time'],fl['total_time'],fg['total_time']],tick_label=x_list)plt.show()plt.figure(2)plt.plot(fr['total_acc_list'], label='rnn')plt.plot(fl['total_acc_list'], label='lstm')plt.plot(fg['total_acc_list'], label='gru')plt.legend(loc='upper left')plt.show()
def str_to_vec(x):len_letter=len(x)tensor_x = torch.zeros(len_letter, n_letters)for idx,letter in enumerate(x):tensor_x[idx][all_letters.find(letter)]=1return tensor_x
#模型預測
def my_predict_rnn(x):n_letters = 57n_hidden = 128n_categories = 18# 輸入文本, 張量化one-hotx_tensor = str_to_vec(x)# 實例化模型 加載已訓練模型參數my_rnn = NameRNN(n_letters, n_hidden, n_categories)my_rnn.load_state_dict(torch.load( './save_model/szAI_1.bin'))with torch.no_grad():# 模型預測output, hidden = my_rnn(x_tensor, my_rnn.inithidden())# 從預測結果中取出前3名# 3表示取前3, 1表示要排序的維度, True表示是否返回最大或是最下的元素topv, topi = output.topk(3, 1, True)print('rnn =>', x)for i in range(3):value = topv[0][i]category_idx = topi[0][i]category = categorys[category_idx]print('\t value:%d  category:%s' %(value, category))
def my_predict_lstm(x):n_letters = 57n_hidden = 128n_categories = 18# 輸入文本, 張量化one-hotx_tensor = str_to_vec(x)# 實例化模型 加載已訓練模型參數my_rnn = NameLSTM(n_letters, n_hidden, n_categories)my_rnn.load_state_dict(torch.load( './save_model/_1.bin'))with torch.no_grad():# 模型預測hidden, c=my_rnn.inithidden()output, hidden ,c= my_rnn(x_tensor,hidden,c )# 從預測結果中取出前3名# 3表示取前3, 1表示要排序的維度, True表示是否返回最大或是最下的元素topv, topi = output.topk(3, 1, True)print(topi,topv)  #一個是值,一個是索引print('lstm =>', x)for i in range(3):value = topv[0][i]category_idx = topi[0][i]category = categorys[category_idx]print('\t value:%d    category:%s' %(value, category))
def my_predict_gru(x):n_letters = 57n_hidden = 128n_categories = 18# 輸入文本, 張量化one-hotx_tensor = str_to_vec(x)# 實例化模型 加載已訓練模型參數my_rnn = NameGRU(n_letters, n_hidden, n_categories)my_rnn.load_state_dict(torch.load( './save_model/gru_1.bin'))with torch.no_grad():# 模型預測hidden=my_rnn.inithidden()output, hidden= my_rnn(x_tensor,hidden)# 從預測結果中取出前3名# 3表示取前3, 1表示要排序的維度, True表示是否返回最大或是最下的元素topv, topi = output.topk(3, 1, True)print(topi,topv)  #一個是值,一個是索引print('lstm =>', x)for i in range(3):value = topv[0][i]category_idx = topi[0][i]category = categorys[category_idx]print('\t value:%d    category:%s' %(value, category))if __name__ == '__main__':# train_dataloader = get_dataloader()# # name_lstm= NameLSTM(input_size=n_letters, hidden_size=128, output_size=categorynum)# name_gru= NameGRU(input_size=n_letters, hidden_size=128, output_size=categorynum)# print(name_gru)# for tensor_x, tensor_y in train_dataloader:#     h0 = name_gru.inithidden()#     x0 = tensor_x[0]#     output, hn= name_gru(x0, h0)#     print(f'output--》{output.shape}')#     print(f'output--》{output}')#     print(f'hn--》{hn.shape}')#     break# train_rnn()# train_lstm()# train_gru()# draw_picture()# tensor_x=str_to_vec('zhang')# print(tensor_x)my_predict_rnn('zhang')my_predict_lstm('zhang')my_predict_gru('zhang')my_predict_rnn('Benesch')my_predict_lstm('Benesch')my_predict_gru('Benesch')

今日分享結束。

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

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

相關文章

3分鐘實戰!用DeepSeek+墨刀AI生成智能對話APP原型圖

如今&#xff0c;AI生成原型圖已經逐漸成為產品經理的一項常用輔助技能&#xff0c;不僅能加快設計進程&#xff0c;還能顯著提升前期溝通效率。最近我嘗試將大語言模型工具與AI原型工具結合測試&#xff0c;目標是看看是否能生成更高質量的原型頁面。直到我使用DeepSeek墨刀AI…

CentOS網絡配置與LAMP環境搭建指南

一、CentOS配置網絡1、查看網卡名稱ifconfig2、找到網卡對應配置文件網卡存放路徑 &#xff1a;/etc/sysconfig/network-scriptscd /etc/sysconfig/network-scripts3、修改網卡對應配置文件使用 vi/vim 打開文件&#xff0c;查看以下內容vim ifcfg-ens33將ONBOOTno 改為 ONBOOT…

TinyMCE 富文本編輯器在 vue2 中的使用 @tinymce/tinymce-vue

TinyMCE是一款功能強大、高度可定制的富文本編輯器。官方文檔 TinyMCE DOCS tinymce-vue包的版本4及更高版本支持Vue.js 3。但不支持Vue.js 2.x。對于Vue.js 2。X應用程序&#xff0c;使用tinymce-vue版本3。 安裝TinyMCE和Vue集成包 npm install tinymce/tinymce-vue3 tiny…

LP-MSPM0G3507學習--04GPIO控制

關鍵函數&#xff1a; DL_GPIO_readPins(GPIO_Regs* gpio, uint32_t pins):同時讀一組端口DL_GPIO_writePins(GPIO_Regs* gpio, uint32_t pins)&#xff1a;同時寫一組端口DL_GPIO_setPins(GPIO_Regs* gpio, uint32_t pins)&#xff1a;對指定某組端口的某管腳置高DL_GPIO_cle…

LVS(Linux virtual server)-實現四層負載均衡

一、簡介LVS:Linux Virtual Server&#xff0c;負載調度器&#xff0c;內核集成&#xff0c;章文嵩&#xff0c;阿里的四層SLB(Server LoadBalance)是基 于LVSkeepalived實現LVS 官網: http://www.linuxvirtualserver.org/二、LVS運行原理2.1LVS 的集群結構2.2lvs相關概念RS&am…

Kubernetes CNI網絡插件性能瓶頸排查與優化實踐

Kubernetes CNI網絡插件性能瓶頸排查與優化實踐 CNI&#xff08;Container Network Interface&#xff09;是 Kubernetes 網絡層的核心組件&#xff0c;不同 CNI 插件實現了容器間網絡通信、多租戶隔離、流量限速等功能。然而在大規模集群或高并發業務場景下&#xff0c;CNI 插…

20250720-6-Kubernetes 調度-nodeName字段,DaemonS_筆記

一、污點與容忍&#xfeff;1. 給節點添加污點&#xfeff;1&#xff09;命令格式基本語法&#xff1a;kubectl taint node [node] keyvalue:[effect]示例&#xff1a;kubectl taint node k8s-node1 gpuyes:NoSchedule操作說明&#xff1a;與打標簽命令類似&#xff0c;將"…

微軟開源項目 Detours 詳細介紹與使用實例分享

目錄 1、Detours概述 2、Detours功能特性 3、Detours工作原理 4、Detours應用場景 5、Detours兼容性 6、Detours具體使用方法 7、Detours使用實例 - 使用Detours攔截系統庫中的UnhandledExceptionFilter接口,實現對程序異常的攔截 C++軟件異常排查從入門到精通系列教程…

研發知識系統選型實戰:從 Notion 到 Gitee Wiki 的迭代經驗

關鍵詞&#xff1a;知識管理、版本控制、協作編輯、國產平臺、研發效能 在日常研發管理中&#xff0c;知識管理平臺往往被視為“非核心工具”&#xff0c;但它的好壞直接影響著團隊交接效率、文檔可用性以及協作深度。過去幾年&#xff0c;我們團隊先后使用過 Notion、Confluen…

從一開始的網絡攻防(三):sqlmap快速上手

一、確定目標 使用sqlmap的第一步是確定探測的目標&#xff0c;一般有四種&#xff1a; 數據庫URL文件Google批量掃 環境 Target IP: 192.168.8.133 Port: 13306(Mysql)、8088(sqli_labs) mysql&#xff1a; docker pull的最新mysql sqlmap github&#xff1a;https://g…

《Anaconda 精簡路徑治理》系列 · 番外篇Conda 虛擬環境路徑結構方案全解——六種路徑布局對比、優劣與治理建議

Python 多版本環境治理理念驅動的系統架構設計&#xff1a;三維治理、四級隔離、五項自治 原則-CSDN博客 Anaconda 路徑精簡后暴露 python 及工具到環境變量的配置記錄-CSDN博客 【終極實戰】Conda/Poetry/Virtualenv/Pipenv/Hatch 多工具協同 AnacondaPyCharm&#xff1a;構建…

容器基礎知識3-kubectl、kubeadm 和 kubelet,kube-proxy

kubectl、kubeadm 和 kubelet&#xff0c;kube-proxy的概念和關系一、kubeadm&#xff1a;K8s 集群的 “搭建工程師”核心定位如果把 K8s 集群比作一棟大樓&#xff0c;kubeadm 就是負責 “打地基、搭框架” 的工程師&#xff0c;專門用來快速搭建 K8s 集群的工具。具體工作內容…

langchain調用本地ollama語言模型和嵌入模型

參考&#xff1a;ollama兼容OpenAIEmbeddings的解決思路 解決代碼&#xff1a; 訪問embedding模型代碼 # 測試以下兩個引用都可以 from langchain_openai import OpenAIEmbeddings #from langchain_community.embeddings import OpenAIEmbeddings from typing import List,…

gitlab私有化部署

以下是整理好的Markdown格式文檔&#xff0c;詳細描述了從下載鏡像、啟動鏡像、修改external_url以及設置或重置root密碼的步驟。 GitLab 安裝與配置指南 本文檔將指導您完成GitLab的安裝和基本配置過程&#xff0c;包括下載鏡像、啟動容器、修改外部訪問URL(external_url)及設…

CCLink IE轉ModbusTCP網關配置無紙記錄器(上篇)

本研究案例采用CCLink IE轉ModbusTCP網關技術&#xff0c;實現了將記錄儀數據傳輸至三菱PLCPLC的過程。具體操作步驟如下所述。在確保無紙記錄儀與PT100傳感器傳感器的連接無誤后&#xff0c;應將無紙記錄儀與個人計算機&#xff08;PC&#xff09;通過以太網線進行連接&#x…

近期工作感想:職業規劃篇

最近整理博客時&#xff0c;撞見意外的驚喜——17年剛畢業那會兒寫的職業規劃&#xff0c;靜靜躺在回收站里。 重讀那些碎碎念&#xff0c;忍不住想笑&#xff1a;那時候的焦慮太真切了&#xff0c;哪敢想后來會遇到這么多大佬&#xff0c;推著我往前一直陰暗爬行&#x1f602;…

Matlab自學筆記六十四:求解自變量帶有約束條件的方程

1.說明 有一些方程由于實際問題的需要&#xff0c;需要設置一些限制約束條件&#xff0c;例如x>0等&#xff0c;若使用Matlab編程求解&#xff0c;首先嘗試使用符號運算求解&#xff08;符號運算可參考文章54&#xff1a;Matlab自學筆記五十四&#xff1a;符號數學工具箱和…

Flutter狀態管理篇之ChangeNotifier(二)

目錄 前言 一、ChangeNotifier定義 1.ChangeNotifier定義 2.Listenable的定義 二、繼承體系 三、核心方法解析 1.類結構與屬性分析 1.Listenable的定義 2..核心字段 1.屬性解析 1._count 2._listeners 3.為什么不用const [] 4._notificationCallStackDep…

大帶寬服務器對于高流量網站的作用

隨著科學技術的快速發展&#xff0c;越來越多的網站面臨著高流量的訪問需求&#xff0c;在同一時間中會有著大量的用戶進行訪問&#xff0c;同時也提高了該企業的知名度&#xff0c;但是這對于服務器的性能需求也在逐漸增高&#xff0c;而大帶寬服務器卓越的性能和穩定的傳輸能…

2025年算法備案發號規律總結與下半年發號預測

上半年發號規律總結圖太糊&#xff1f;可看下方表格&#xff08;左劃看全表&#xff09;&#x1f447;今年批次算法備案總批次發布時間所發當批算法材料提交時間段審核周期25年第一批第十批2025/3/122025年1月&#xff08;春節前&#xff09;約2個月25年第二批第十一批2025/5/1…