HuggingFace-利用BERT預訓練模型實現中文情感分類(下游任務)

準備數據集

使用編碼工具

首先需要加載編碼工具,編碼工具可以將抽象的文字轉成數字,便于神經網絡后續的處理,其代碼如下:

# 定義數據集
from transformers import BertTokenizer, BertModel, AdamW
# 加載tokenizer
token = BertTokenizer.from_pretrained('bert-base-chinese')
print('token', token)

out:
token BertTokenizer(name_or_path=‘bert-base-chinese’, vocab_size=21128, model_max_length=512, is_fast=False, padding_side=‘right’, truncation_side=‘right’, special_tokens={‘unk_token’: ‘[UNK]’, ‘sep_token’: ‘[SEP]’, ‘pad_token’: ‘[PAD]’, ‘cls_token’: ‘[CLS]’, ‘mask_token’: ‘[MASK]’}, clean_up_tokenization_spaces=True), added_tokens_decoder={
0: AddedToken(“[PAD]”, rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),
100: AddedToken(“[UNK]”, rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),
101: AddedToken(“[CLS]”, rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),
102: AddedToken(“[SEP]”, rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),
103: AddedToken(“[MASK]”, rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),
}

由上可知bert-base-chinese模型的字典中共有21128個詞,編碼器編碼句子的最大長度為512個詞,并且能夠看到bert-base-chinese模型所使用的一些特殊符號,例如SEK,PAD等。

這里使用的編碼工具是bert-base-chinese,編碼工具和預訓練模型往往是成對使用的,后續將使用同名的預訓練語言模型作為backbone。

編碼工具的試算

加載完成編碼工具之后可以進行一次試算,觀察編碼工具的輸入和輸出,代碼如下:

data = token.batch_encode_plus(batch_text_or_text_pairs=['關注博主,不迷路。','俺要帶你上高速。'], truncation=True,padding='max_length',max_length=12,return_tensors='pt',return_length=True)
# 查看編碼輸出
for k,v in out.items():print(k,v.shape)
# 把編碼還原成句子
print(token.decode(out['input_ids'][0]))

out:
input_ids torch.Size([2, 17])
token_type_ids torch.Size([2, 17])
length torch.Size([2])
attention_mask torch.Size([2, 17])
[CLS] 關 注 博 主 , 不 迷 路 。 [SEP] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD]
[CLS] 俺 要 帶 你 上 高 速 。 [SEP] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD]

編碼工具的參數說明

對于編碼工具的使用,特別是參數值的含義可以參考下面的兩段代碼:

"""使用簡單的編碼"""
# 編碼兩個句子
out = tokenizer.encode(# 句子1text = sents[0],text_pair = sents[1],# 當句子長度大于max_length時進行截斷truncation=True,# 一律補充pad到max_length長度padding = 'max_length',add_special_tokens = True,# 許多大模型的階段也是使用512作為最終的max_lengthmax_length=30,return_tensors=None,
)
"""增強的編碼函數"""
# 增強的編碼函數
out = tokenizer.encode_plus(text = sents[0],text_pair = sents[1],#當句子長度大于max_length時進行截斷操作truncation = True,#一律補零到max_length長度padding='max_length',max_length=30,add_special_tokens=True,#可以取值tf,pt,np,默認返回list--->tensorflow,pytorch,numpyreturn_tensors=None,#返回token_type_idsreturn_token_type_ids=True,#返回attention_maskreturn_attention_mask=True,#返回special_tokens_mask 特殊符號標識return_special_tokens_mask=True,#返回offset_mapping標識每個詞的起始和結束位置---》這個參數只能BertTokenizerFast使用#return_offsets_mapping=True,#返回length 標識長度return_length=True
)

從上面的代碼中的參數max_length=500可以看出經過編碼后的句子的長度一定是12個詞的長度。如果源句子超出則會進行截斷,如果源句子不足則會進行填充PAD,其運行結果如下:

{'input_ids': tensor([[ 101, 1068, 3800, 1300,  712, 8024,  679, 6837, 6662,  511,  102,    0],[ 101,  939, 6206, 2372,  872,  677, 7770, 6862,  511,  102,    0,    0]]), 'token_type_ids': 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]]), 'length': tensor([11, 10]), 'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0]])}
input_ids torch.Size([2, 12])
token_type_ids torch.Size([2, 12])
length torch.Size([2])
attention_mask torch.Size([2, 12])
[CLS] 關 注 博 主 , 不 迷 路 。 [SEP] [PAD]
[CLS] 俺 要 帶 你 上 高 速 。 [SEP] [PAD] [PAD]

在這里插入圖片描述
編碼工具首先是對一條完整的句子進行了tokenizer,把句子分成了一個個token。同時,對于不同的編碼工具,分詞的結果也不一定一致。這里采用的bert-base-chinese編碼工具中,它是以字為詞,即把每個字當做一個詞進行處理。
這些編碼的結果對于預訓練模型的計算十分重要,在后面將會使用編碼器將所有的句子進行編碼,用于輸入到預訓練模型中進行計算。

定義數據集

這里使用的數據集為ChnSentiCorp數據集,Dataset類如下:

# import torch
from datasets import load_dataset
class Dataset(torch.utils.data.Dataset):def __init__(self, split):self.dataset = load_dataset(path='lansinuote/ChnSentiCorp', split=split)def __len__(self):return len(self.dataset)def __getitem__(self, i):text = self.dataset[i]['text']label = self.dataset[i]['label']return text, label
dataset = Dataset('train')
print(len(dataset))
print(dataset[0])

在上述代碼中加載了ChnSentiCorp數據集,并使用Pytorch中的Dataset對象進行封裝,利用__getitem__()得到每一條數據,每條數據中包含textlabels兩個字段,最后初始化訓練數據集并查看訓練數據集的長度和第一條數據樣例。

out: 9600
('選擇珠江花園的原因就是方便,有電動扶梯直接到達海邊,周圍餐館、食廊、商場、超市、攤位一應俱全。酒店裝修一般,但還算整潔。 泳池在大堂的屋頂,因此很小,不過女兒倒是喜歡。 包的早餐是西式的,還算豐富。 服務嗎,一般', 1)

由上面的輸出可知訓練數據集包括9600條數據,每條數據包含一條評論文本和一個標識,表明這一條評論是好評還是差評。注意:這里的數據集是單純的原始文本數據,并沒有進行編碼。

定義計算設備

這里將使用CUDA作為計算設備,這樣可以極大加速模型的訓練和測試的過程,代碼如下:

device = 'cpu'
if torch.cuda.is_available():device = 'CUDA'
print('選用的計算設備:',device)

在該段代碼中默認使用CPU進行計算,如果存在CUDA的話則選用CUDA作為計算設備。

定義數據整理函數

正如上面所述的那樣,ChnSentiCorp數據集中的每一條數據是抽象的文本數據,并沒有進行任何的編碼操作,而預訓練模型是需要編碼之后的數據才能進行計算,所以需要一個將文本句子轉成編碼的過程。
另外,在訓練模型時數據集往往很大,如果一條一條地處理則效率會太低,在現實中我們往往一批一批地處理數據,這樣可以快速地處理數據集,同時從梯度下降的角度來講,批數據的梯度方差相較于一條條數據的梯度小,可以讓模型更加穩定地更新參數

# 定義批處理函數
def collate_fn(data):sents = [i[0] for i in data]labels = [i[1] for i in data]# 編碼data = token.batch_encode_plus(batch_text_or_text_pairs=sents, truncation=True,padding='max_length',max_length=500,return_tensors='pt',return_length=True)# input_ids:編碼之后的數字# attention_masks:補0的位置都是0,其他位置都是1input_ids = data['input_ids']attention_mask = data['attention_mask']token_type_ids = data['token_type_ids']labels = torch.LongTensor(labels)# print(data['length'],data['length'].max())return input_ids, attention_mask, token_type_ids, labels

在這段代碼中,參數data表示一批數據,取出其中的句子和標識,它們都是list類型,在上述代碼中會將兩者分別賦給sentslabels,然后是使用編碼器編碼該批句子,在參數中將編碼后的結果指定為固定的500個詞的大小,與上面的例子同理超出500個詞的部分會被截斷(這里是通過truncation=True控制),同時少于500個詞的句子會被[PAD]填充(這里主要是通過 padding='max_length'控制)。另外,在編碼過程中通過 return_tensors='pt'參數,將編碼后的結果返回torch中的tensor類型,免去了后面轉換數據格式的麻煩(也就是說后面可以通過數據格式轉換可以將‘tf’轉成‘pt’格式)。
之后取出編碼后的結果,并將labels也轉成Pytorch中的Tensor格式,再把它們移動到之前已經定義好的計算設備device上,最后把這些數據全部返回,到這里數據整理函數的工作已經全部完成。

數據處理函數的例子

上述定義了數據處理函數,為了實驗其效果也可使用下面的例子:(本用例已加狗頭保命~)在這里插入圖片描述

data = [('選擇新大的原因當然不是為了延畢。',1),('筆記本的內存確實小。',0),('宿舍沒有風扇。其他都很好。',1),('今天才知道這本書還有第10000卷,真是太屌了。',1),('機器的背面似乎被撕了張什么標簽,殘膠還在。',0),('為什么有人在校園里尖叫,是瘋了還是giao。',0)
]# 狗頭保命版試算
input_ids,attention_mask,token_type_ids,labels = collate_fn(data)
print('input_ids.shape',input_ids.shape)
print('attention_mask.shape',attention_mask.shape)
print('token_type_ids.shape',token_type_ids.shape)
print('labels:',labels)

在該段代碼中首先是模擬了一批數據,這批數據中包含4個句子,通過將該批數據輸入到整理函數以后,運行結果如下:

input_ids.shape torch.Size([6, 500])
attention_mask.shape torch.Size([6, 500])
token_type_ids.shape torch.Size([6, 500])
labels: tensor([1, 0, 1, 1, 0, 0])

可見編碼之后的結果都是確定的500個詞的長度,并且每個結果都會被移動到可用的計算設備上,這樣可以方便后續的計算。

定義數據加載器

上述代碼中定義了數據集和數據整理函數以后,下面我們將定義一個數據加載器DataLoader,它可以使用數據整理函數來完成成批地處理數據集中的數據,通俗來講每一批的數據我們可以稱為batch

# 定義數據加載器并查看數據樣例
loader = torch.utils.data.DataLoader(dataset=dataset, batch_size=16,collate_fn=collate_fn,shuffle=True,drop_last=True)

對于上述代碼,我們使用了Pytorch提供的工具類定義數據集加載器,其參數說明可參考下圖:
在這里插入圖片描述

數據加載器的例子

為了更好地使用數據加載器,這里我們查看一批數據樣例,將這批數據輸入到數據加載器中,可以發現其結果會與數據整理函數的運行結果相似,只不過是句子的數量增多了。

上述代碼依次打印了加載器中批次數目、加載器中輸入數據的input_ids和掩蔽注意力的形狀
attention_mask_shape、詞元的ids類型形狀token_type_ids_shape以及標簽labels

for i, (input_ids, attention_mask, token_type_ids, labels) in enumerate(loader):break
print(len(loader))
print('input_ids', input_ids)
print('attention_mask_shape', attention_mask.shape)
print('token_type_ids_shape', token_type_ids.shape)
print('labels', labels)
  1. input_ids 就是編碼后的詞
  2. token_type_ids 第一個句子和特殊符號的位置是0,第二個句子的位置是1
  3. attention_mask pad的位置是0,其他位置都是1
  4. special_tokens_mask 特殊符號的位置是1,其他位置都是0

定義模型

因為我們是要利用Huggingface的預訓練語言模型,所以需要做兩件事情:加載預訓練模型PLM以及定義下游任務模型。

加載預訓練模型

這里使用的BERT預訓練模型,模型名稱為bert-base-chinese,這里的名稱和編碼器的名稱是一致的,因為往往模型和其編碼工具配套使用。另外,BERT模型不是必須的模型,進行中文情感分類也可以使用其他支持中文的模型,例如BART等。

from transformers import BertModel
# 加載預訓練模型
pretrained = BertModel.from_pretrained('bert-base-chinese')
# 統計參數量
sum(i.numel() for i in pretrained.parameters()) / 10000
out:10226.7648

由上可知bert-base-chinese模型的參數量超過1億個,這個模型的體量還是比較大的。由于它的體量比較大,所以如果要訓練它,對計算資源的要求較高,而對于本次的二分類任務則可以選擇不訓練它,只是作為一個特征提取器。這樣就可以避免訓練這個笨重的模型,不需要計算它的梯度,進而不更新它的參數,所以需要凍結它的參數:

# 當不進行訓練時不需要計算梯度
for param in pretrained.parameters():param.requires_grad_(False)

定義好PLM后,需要進行一次試算,觀察模型的輸入和輸出結果:

# 設定計算設備
pretrained.to(device)
# 模型試算
out = pretrained(input_ids=input_ids, attention_mask=attention_mask, token_type_ids=token_type_ids)
print(out.last_hidden_state.shape)

這里可能會報錯:

RuntimeError: Expected all tensors to be on the same device, but found at least two devices, cuda:0 and cpu! (when checking argument for argument index in method wrapper_CUDA__index_select)

這是因為之前我們忘了將input_ids等參數放到cuda上,所以需要改一下代碼:

for i, (input_ids, attention_mask, token_type_ids, labels) in enumerate(loader):break
input_ids = input_ids.to(device)
attention_mask = attention_mask.to(device)
token_type_ids = token_type_ids.to(device)
labels = labels.to(device)
print(len(loader))
print('input_ids', input_ids)
print('attention_mask_shape', attention_mask.shape)
print('token_type_ids_shape', token_type_ids.shape)
print('labels', labels)
print(input_ids.is_cuda)

這里如果有顯卡的話會輸出True,然后上面的程序報錯也會消除,同時輸出:

torch.Size([16, 500, 768])

上述代碼中將我們的16個樣例數據(在定義數據加載器部分)輸入到預訓練模型中,得到的計算結果和我們預想的是一致的。首先從第一個維度16可以看出是和我們的樣例輸入的句子數量有關的,隨后的500是指每句話中包含了500個單詞,因為max_length=500(在數據整理函數中定義),這就把之前所有的內容都串起來了。最后的768表示將每一個詞抽成一個768維的向量。到此為止,我們已經通過預訓練模型成功地把16句話轉換成為了一個特征向量矩陣,這樣就可以接入下面的下游任務模型做分類或者回歸任務。

定義下游任務模型

下游任務模型的任務是對backbone抽取的特征進行進一步的計算,得到符合業務需求的計算結果,這里做的是一個二分類的結果,因為我們數據集中的labels只有兩種。

# 定義下游任務模型
class Model(torch.nn.Module):def __init__(self):super(Model, self).__init__()self.fc = torch.nn.Linear(768, 2).to(device)def forward(self, input_ids, attention_mask, token_type_ids):with torch.no_grad():out = pretrained(input_ids=input_ids,attention_mask=attention_mask,token_type_ids=token_type_ids)out = self.fc(out.last_hidden_state[:, 0])out = out.softmax(dim=1)return outmodel = Model()
# 設置計算設備
model.to(device)

在這段代碼中,定義了一個下游任務模型,該模型包括一個全連接的LinearModel,權重矩陣是768x2,所以它能夠將一個768維度的向量轉換成一個二維空間中。
上述的下游任務模型的計算流程為:

在這里插入圖片描述
這里之所以丟棄后面466個詞的特征,是因為BERT模型所致,具體的內容可以參考BERT模型的論文:BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding

下游任務模型試算

在最后我們使用剛才使用的batch=16的數據進行試算:

# 試算
print(model(input_ids=input_ids,attention_mask=attention_mask,token_type_ids=token_type_ids).shape)

其輸出結果為:

torch.Size([16, 2])

由此可見這就是我們一開始所要求的16句話進行二分類的結果。

訓練和測試

模型訓練

模型定義完成之后,我們就可以對該模型進行訓練了~代碼如下:

from transformers import AdamW
from transformers.optimization import get_scheduler
def train():# 定義優化器optimizer = torch.optim.AdamW(model.parameters(), lr=5e-4)# 定義損失函數criterion = torch.nn.CrossEntropyLoss()# 定義學習率調節器scheduler = get_scheduler(name='linear',num_warmup_steps=0,num_training_steps=len(loader),optimizer=optimizer)# 將模型切換到訓練模式model.train()# 按批次進行遍歷訓練數據集中的數據for i, (input_ids, attention_mask, token_type_ids, labels) in enumerate(loader):input_ids = input_ids.to(device)attention_mask = attention_mask.to(device)token_type_ids = token_type_ids.to(device)labels = labels.to(device)# 模型計算out = model(input_ids=input_ids, attention_mask=attention_mask, token_type_ids=token_type_ids).to(device)# 計算損失并使用梯度下降法優化模型參數loss = criterion(out, labels)loss.backward()optimizer.step()scheduler.step()optimizer.zero_grad()# 輸出各項數據的情況,便于觀察if i % 10 == 0:out = out.argmax(dim=1)accuracy = (out == labels).sum().item() / len(labels)lr = optimizer.state_dict()['param_groups'][0]['lr']print(i, loss.item(),lr, accuracy)
train()

在上述的代碼中首先定義了優化器、損失函數、學習率調節器。其中優化器使用了HuggingFace提供的AdamW優化器,這是傳統的Adam優化器的改進版本,在自然語言處理任務中,該優化器往往取得了比Adam優化器更加好的成績,并且計算效率高。學習率調節器使用了HuggingFace提供的線性學習率調節器,它能夠在訓練過程中讓學習率緩慢下降,而不是始終使用一致的學習率,因為在訓練的后期階段往往需要更小的學習率來微調參數有利于損失函數下降到最低點。這里的損失函數采用了分類任務中常用的CrossEntropyLoss交叉熵損失函數。
然后將下游任務模型切換到訓練模式即可開始訓練。最后每當優化10次模型參數時,就計算一次當前模型預測結果的正確率,并輸出模型的損失函數、學習率,最終訓練完畢的結果如下所示:
在這里插入圖片描述
由上圖可見在訓練到大約200個steps時,模型已經能夠達到85%左右的正確率,損失函數也如同預期一樣隨著訓練過程不斷下降,學習率亦如此。

模型測試

對于已經訓練好的模型進行測試,以便驗證訓練的有效性,其測試代碼如下:

def test():# 定義測試數據加載器loader_test = torch.utils.data.DataLoader(dataset = Dataset('test'),batch_size = 32,collate_fn = collate_fn,shuffle = True,drop_last = True)# 將下游任務模型切換到運行模式model.eval()correct = 0total = 0for i, (input_ids, attention_mask, token_type_ids, labels) in enumerate(loader_test):# 計算5個批次即可,不需要全部遍歷input_ids = input_ids.to(device)attention_mask = attention_mask.to(device)token_type_ids = token_type_ids.to(device)  labels = labels.to(device)    if i == 5:breakprint(i)# 計算with torch.no_grad():out = model(input_ids=input_ids,attention_mask=attention_mask,token_type_ids=token_type_ids).to(device)# 統計正確率out = out.argmax(dim=1)correct += (out==labels).sum().item()total += len(labels)print(correct/total)test()

在上述的代碼中首先定義了測試數據集及其加載器,同時取出5個批次的數據讓模型進行預測,最后將統計的正確率輸出,運行結果為:

0
1
2
3
4
0.88125

最終模型取得了88.125%的正確率,這個正確率雖然不是很高,但是驗證了下游任務模型即使在不訓練basebone的情況下也可以達到一定的成績。

省流版-全部代碼

在這里插入圖片描述

總結

本文通過一個情感分類的例子說明了使用BERT預訓練模型抽取文本特征數據的方法,使用BERT作為backbone,相對于傳統的RNN而言其計算量會稍稍大一些,但是BERT抽取的文本特征將更加完整,更容易被下游任務模型識別總結出數據之間的規律。所以在不對BERT預訓練模型進行訓練,而是簡單應用于下游任務時也可以表現一個比較好的結果。
在這里插入圖片描述

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

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

相關文章

cobol基本動詞

cobol基本動詞 基本動詞用于過程部中的數據處理。每個語句總是以cobol動詞開頭。 input(輸入)/output(輸出) 輸入輸出動詞用于從用戶獲取數據。并顯示cobol程序的輸出。 accept 用于從操作系統或者用戶獲取數據,例如日…

langchain 部署組件-LangServe

原文:🦜?🏓 LangServe | 🦜?🔗 Langchain LangServe 🚩 We will be releasing a hosted version of LangServe for one-click deployments of LangChain applications. Sign up here to get on the wa…

OpenLayers入門,OpenLayers6的WebGLPointsLayer圖層樣式和運算符詳解,四種symbolType類型案例

專欄目錄: OpenLayers入門教程匯總目錄 前言 本章講解使用OpenLayers6的WebGL圖層顯示大量點情況下,列舉出所有WebGLPointsLayer圖層所支持的所有樣式運算符大全。 補充說明 本篇主要介紹OpenLayers6.x版本的webgl圖層,OpenLayers7.x和OpenLayers8.x主要更新內容就是webgl…

GB28181學習(十七)——基于jrtplib實現tcp被動和主動發流

前言 GB/T28181-2022實時流的傳輸方式介紹:https://blog.csdn.net/www_dong/article/details/134255185 基于jrtplib實現tcp被動和主動收流介紹:https://blog.csdn.net/www_dong/article/details/134451387 本文主要介紹下級平臺或設備發流功能&#…

生活如果真能像隊列一樣的話

生活如果真能像隊列一樣,那該多好啊。 —————————————————————————————————————————— 背包,隊列 可以先看他們的API:都含有一個無參構造函數,添加單個元素的方法,測試集合…

php項目從寶塔面板切換轉到phpstudy小皮面板

寶塔面板轉phpstudy面板 版本 寶塔面板8.0.1 phpstudy面板8.1.1.3 步驟 1、寶塔面板,找到項目文件夾,打包、下載到本地、解壓 2、本地windows系統安裝phpstudy面板,選擇盡可能一樣的配置 比如寶塔php7.4.33,可能phpstudy面板只有php7.4.3,也行 大環境一定要一致,比如…

力扣算法練習BM46—最小的K個數

題目 給定一個長度為 n 的可能有重復值的數組,找出其中不去重的最小的 k 個數。例如數組元素是4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4(任意順序皆可)。 數據范圍:0≤k,n≤10000,數組中每個數的大小0≤val≤1000 要…

linux signal 機制

ref: Linux操作系統學習筆記(十六)進程間通信之信號 | Ty-Chens Home https://www.cnblogs.com/renxinyuan/p/3867593.html 當執行kill -9 PID時系統發生了什么 -

Codeforces Round 910 (Div. 2) D. Absolute Beauty

D. Absolute Beauty 有兩個長度為 n n n 的整數數組 a 1 , a 2 , … , a n a_1,a_2,\ldots,a_n a1?,a2?,…,an? 和 b 1 , b 2 , … , b n b_1,b_2,\ldots,b_n b1?,b2?,…,bn? 。他將數組 b b b 的美麗值定義為 ∑ i 1 n ∣ a i ? b i ∣ . \sum_{i1}^{n} |a_i - b…

基于材料生成算法優化概率神經網絡PNN的分類預測 - 附代碼

基于材料生成算法優化概率神經網絡PNN的分類預測 - 附代碼 文章目錄 基于材料生成算法優化概率神經網絡PNN的分類預測 - 附代碼1.PNN網絡概述2.變壓器故障診街系統相關背景2.1 模型建立 3.基于材料生成優化的PNN網絡5.測試結果6.參考文獻7.Matlab代碼 摘要:針對PNN神…

JDK命令使用總結

目錄 javacjava javac 將源碼(*.java)編譯成字節碼(*.class) javac HelloWorld.javajava 運行字節碼(*.class) 不能加后綴名 java HelloWorld直接運行單文件源碼(*.java) Java11以上才支持 java HelloWorld.java

ROSNS3(一)

https://github.com/malintha/rosns3 第一步:clone和構建rosns3客戶端 第二步:運行 最詳細的ubuntu 安裝 docker教程 - 知乎 1. unable to find source space /home/muta/src 解決方法: 將副將將碰到的bug,解決方法_#include &…

【C++ Primer Plus學習記錄】遞增運算符(++)和遞減運算符(--)

遞增運算符()和遞減運算符(--):前綴版本位于操作數前面,如x;后綴版本位于操作數后面,如x。兩個版本對操作數的影響是一樣的,但是影響的時間不同。這就像吃飯前買單和吃飯…

Python從零開始快速搭建一個語音對話機器人

文章目錄 01-初心緣由02-準備工作03-語音機器人的搭建思路04-語音生成音頻文件05-音頻文件轉文字STT06-與圖靈機器人對話07-文字轉語音08-語音對話機器人的完整代碼09-結束語10-有問必答關于Python技術儲備一、Python所有方向的學習路線二、Python基礎學習視頻三、精品Python學…

SSH連接遠程服務器報錯:WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED 解決方法

一.錯誤描述 報錯信息里提示了路徑信息/root/.ssh/known_hosts:20 二.解決方案 方法一 輸入以下指令: ssh-keygen -R XXX(需要連接遠程服務器的ip) 按照我的例子ip:10.165.7.136,會返回以下信息: 重新嘗試連接: 輸…

C++學習 --set

目錄 1, 什么是set 2, 創建set 2-1, 標準數據類型 2-2, 自定義數據類型 2-3, 其他創建方式 3, 操作set 3-1, 賦值 3-2, 添加元素(insert) 3-2-1&…

MySQL的樂觀鎖和悲觀鎖

1、樂觀鎖: 樂觀鎖在操作數據的時候,是保持一種樂觀的狀態,認為別的線程是不會同時修改數據的,所以是不會上鎖的,但是在更新的時候,會判斷一下在這個期間內是否有別的線程修改過數據。 主要的流程&#x…

規劃類3d全景線上云展館幫助企業輕松拓展海外市場

科技3D線上云展館作為一種基于VR虛擬現實和互聯網技術的新一代展覽平臺。可以在線上虛擬空間中模擬真實的展館,讓觀眾無需親自到場,即可獲得沉浸式的參觀體驗。通過這個展館,您可以充分、全面、立體展示您的產品、服務以及各種創意作品&#…

python運算符重載之成員關系和屬性運算

1 python運算符重載之成員關系和屬性運算 1.1 重載成員關系運算符 1.1.1 contains,iter,getitem python使用成員關系運算符in時, 按優先級調用方法:contains>iter>getitem; class MyIters:def __init__(self,value):self.datavalu…