- 多模態(tài)大模型:算法、應(yīng)用與微調(diào)
- 劉兆峰
- 2113字
- 2024-09-11 17:37:22
1.1.2 編碼器-解碼器結(jié)構(gòu)
我們繼續(xù)深入探索Seq2Seq結(jié)構(gòu),如圖1-3所示,模型的最外層一般是由一個(gè)編碼器和一個(gè)解碼器組成的。編碼器依次對(duì)輸入序列中的每個(gè)元素進(jìn)行處理,然后將獲取的信息壓縮成一個(gè)上下文向量,之后將上下文向量發(fā)送給解碼器,解碼器根據(jù)輸入序列和上下文向量依次生成輸出序列。編碼器和解碼器在早期一般采用RNN模塊,后來(lái)變成了LSTM(長(zhǎng)短期記憶網(wǎng)絡(luò))或GRU(門控循環(huán)單元)模塊,不過(guò)不管內(nèi)部模塊是什么,其主要特點(diǎn)就是可以提取時(shí)序特征信息。

圖1-3 Seq2Seq結(jié)構(gòu)的模型一般由一個(gè)編碼器和一個(gè)解碼器組成
接下來(lái)我們用PyTorch實(shí)現(xiàn)一個(gè)簡(jiǎn)單的Seq2Seq結(jié)構(gòu)模型,并用于1.1.4節(jié)的實(shí)戰(zhàn)案例。本次實(shí)現(xiàn)主要分為以下幾步:首先實(shí)現(xiàn)Seq2Seq結(jié)構(gòu)模型的編碼器和解碼器部分;然后在解碼器中加入注意力機(jī)制;之后定義該任務(wù)的損失函數(shù);最后進(jìn)行訓(xùn)練和評(píng)估。
1.編碼器
在編碼器中,一般會(huì)先使用嵌入層(Embedding Layer)將輸入序列中的每一個(gè)詞元轉(zhuǎn)換為特征向量,嵌入層的參數(shù)是一個(gè)vocab_size×embed_size的矩陣,其中vocab_size表示詞表的大小,embed_size表示特征向量的維度。如果有多個(gè)編碼器,則詞向量的轉(zhuǎn)換僅發(fā)生在第一個(gè)編碼器的處理過(guò)程中。在底層的編碼器中輸入的是詞向量列表,而在其他編碼器中,輸入的是上一層編碼器的輸出。所有編碼器都有相同的輸入來(lái)源,這些輸入通常是一個(gè)大小為512的向量列表。列表的大小是可以通過(guò)設(shè)置超參數(shù)來(lái)調(diào)整的,通常設(shè)置為訓(xùn)練數(shù)據(jù)集中最長(zhǎng)句子的長(zhǎng)度。
python
class EncoderRNN(nn.Module):
def __init__(self, input_size, hidden_size, dropout_p=0.1):
super(EncoderRNN, self).__init__()
self.hidden_size=hidden_size
self.embedding=nn.Embedding(input_size, hidden_size)
self.rnn=nn.RNN(hidden_size, hidden_size, batch_first=True)
self.dropout=nn.Dropout(dropout_p)
def forward(self, x):
x=self.embedding(x)
x=self.dropout(x)
output, hidden=self.rnn(x)
return output, hidden
這段代碼定義了一個(gè)名為EncoderRNN的類,用于將輸入的序列數(shù)據(jù)編碼成一個(gè)向量,稱為隱藏狀態(tài)向量。
在該類的初始化方法中,有如下3個(gè)主要的成員變量。
?self.hidden_size代表了隱藏狀態(tài)的維度。
?self.embedding是一個(gè)嵌入層,用于將輸入序列的每個(gè)元素映射成對(duì)應(yīng)的稠密向量表示。
?self.rnn是一個(gè)循環(huán)神經(jīng)網(wǎng)絡(luò)層,其輸入和輸出的維度都是hidden_size,并且采用batch_first=True的方式進(jìn)行設(shè)置。
在前向傳播過(guò)程中,首先,將輸入序列進(jìn)行嵌入操作并使用dropout進(jìn)行隨機(jī)失活處理,得到嵌入后的序列。然后,將嵌入后的序列輸入到RNN層中進(jìn)行編碼操作。最后,返回編碼后的輸出序列以及最終的隱藏(hidden)狀態(tài)作為輸出。
下面我們實(shí)例化一個(gè)編碼器對(duì)象,然后使用玩具數(shù)據(jù)查看輸入向量、輸出向量和隱藏狀態(tài)的維度。
python
encoder=EncoderRNN(input_size=10, hidden_size=5) #詞表大小為10,隱藏狀態(tài)維度為5
input_vector=th.tensor([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])
output, hidden=encoder(input_vector)
print("輸入向量的維度:", input_vector.size()) #輸入向量的維度: torch.Size([1, 10])
print("輸出向量的維度:", output.size()) #輸出向量的維度: torch.Size([1, 10, 5])
print("最終隱藏狀態(tài)的維度:", hidden.size()) #最終隱藏狀態(tài)的維度: torch.Size([1, 1, 5])
2.解碼器
如果Seq2Seq結(jié)構(gòu)的編碼器中有多個(gè)RNN層,則在解碼器中僅使用編碼器最后一層的輸出,該輸出內(nèi)容也被稱為上下文向量,因?yàn)樗鼘?duì)整個(gè)輸入序列的上下文進(jìn)行編碼。解碼器將使用此上下文向量進(jìn)行初始化,這其中隱含了一個(gè)限定條件,就是解碼器的隱藏狀態(tài)維度和編碼器的隱藏狀態(tài)維度必須相同。解碼器最終的輸出應(yīng)該是詞元的概率分布,因此在解碼器的最后一層使用全連接層進(jìn)行變換。
解碼器在對(duì)目標(biāo)序列的單詞進(jìn)行嵌入之前,需要將整個(gè)序列右移一位,然后在序列的開(kāi)頭增加一個(gè)標(biāo)志位SOS_token來(lái)表示開(kāi)始解碼。例如,當(dāng)目標(biāo)序列是“Hello World!”時(shí),實(shí)際輸入的應(yīng)該是[SOS_token, Hello, World, !]。具體的解碼過(guò)程其實(shí)是:輸入SOS_token,然后解碼器輸出Hello,將SOS_token和Hello拼接起來(lái)輸入解碼器,然后輸出World,以此類推,直到解碼器輸出結(jié)束詞元EOS_token為止。
解碼器在前向傳播生成結(jié)果時(shí),采用了強(qiáng)制學(xué)習(xí)的方法。此方法是指在訓(xùn)練中使用真實(shí)的目標(biāo)輸出作為下一個(gè)輸入,而不是使用解碼器猜測(cè)的輸出作為下一個(gè)輸入。例如,在前面這個(gè)例子中,當(dāng)我們輸入SOS_token時(shí),期望模型輸出Hello,但是如果它實(shí)際輸出了Hi,那我們會(huì)將其先存下來(lái),然后在下一輪輸入的時(shí)候,將SOS_token和正確答案Hello拼接起來(lái)輸入解碼器。使用強(qiáng)制學(xué)習(xí)的方法可以加快網(wǎng)絡(luò)的收斂速度,但當(dāng)應(yīng)用訓(xùn)練好的網(wǎng)絡(luò)時(shí),可能會(huì)出現(xiàn)不穩(wěn)定的情況。
python
class DecoderRNN(nn.Module):
def __init__(self, hidden_size, output_size):
super(DecoderRNN, self).__init__()
self.embedding=nn.Embedding(output_size, hidden_size)
self.rnn=nn.RNN(hidden_size, hidden_size, batch_first=True)
self.out=nn.Linear(hidden_size, output_size)
def forward(self, encoder_outputs, encoder_hidden, target_tensor=None):
batch_size=encoder_outputs.size(0)
decoder_input=th.empty(batch_size, 1, dtype=th.long).fill_(SOS_token) # Start of Sentence詞元,表示開(kāi)始生成一個(gè)句子
decoder_hidden=encoder_hidden
decoder_outputs=[]
for i in range(MAX_LENGTH):
decoder_output, decoder_hidden =self.forward_step(decoder_input, decoder_hidden)
decoder_outputs.append(decoder_output)
if target_tensor is not None: # 強(qiáng)制學(xué)習(xí)
decoder_input=target_tensor[:, i].unsqueeze(1)
else:
_, topi=decoder_output.topk(1)
decoder_input=topi.squeeze(-1).detach()
decoder_outputs=th.cat(decoder_outputs, dim=1)
decoder_outputs=F.log_softmax(decoder_outputs, dim=-1)
return decoder_outputs, decoder_hidden, None
def forward_step(self, x, hidden):
x=self.embedding(x)
x=F.relu(x)
x, hidden=self.rnn(x, hidden)
output=self.out(x)
return output, hidden
這段代碼定義了一個(gè)名為DecoderRNN的類,用于根據(jù)編碼器的輸出和隱藏狀態(tài)逐步生成目標(biāo)序列。
在該類的初始化方法中,有三個(gè)主要的成員變量。
其中self.embedding和self.rnn前面已經(jīng)介紹過(guò),不再贅述。self.out是一個(gè)線性層,用于將RNN的輸出映射到目標(biāo)序列的維度。
在前向傳播過(guò)程中,首先根據(jù)編碼器的輸出和隱藏狀態(tài)初始化解碼器的第一個(gè)輸入,然后進(jìn)入一個(gè)循環(huán),循環(huán)次數(shù)為最大序列長(zhǎng)度(MAX_LENGTH)。在每一次循環(huán)中,調(diào)用forward_step方法來(lái)逐步生成目標(biāo)序列。強(qiáng)制學(xué)習(xí)方法會(huì)將目標(biāo)序列作為下一步的輸入。循環(huán)過(guò)程中的每一個(gè)輸出都被存儲(chǔ)在decoder_outputs列表中。
最后,在前向傳播的末尾,將存儲(chǔ)的所有輸出進(jìn)行拼接,然后經(jīng)過(guò)log_softmax函數(shù)進(jìn)行標(biāo)準(zhǔn)化,得到最終的decoder_outputs。同時(shí),返回最終的隱藏狀態(tài)(decoder_hidden)以及“None”以保持在訓(xùn)練循環(huán)中的一致性。
forward_step方法用于執(zhí)行每一步的解碼過(guò)程。它首先對(duì)輸入序列進(jìn)行嵌入操作,然后通過(guò)ReLU激活函數(shù)激活,接著經(jīng)過(guò)RNN層進(jìn)行解碼計(jì)算,再通過(guò)線性層映射到目標(biāo)序列的維度。最后,返回解碼結(jié)果和隱藏狀態(tài)。
下面我們實(shí)例化一個(gè)解碼器對(duì)象,然后使用玩具數(shù)據(jù)看一下最終輸出向量的維度。
python
decoder=DecoderRNN(hidden_size=5, output_size=10)
target_vector=th.tensor([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])
encoder_outputs, encoder_hidden=encoder(input_vector)
output, hidden, _=decoder(encoder_outputs, encoder_hidden, input_vector)
print("輸出向量的維度:", output.size()) #輸出向量的維度:[1, 10, 10]
最終輸出向量的第一個(gè)維度表示批量大小,第二個(gè)維度表示最大輸出長(zhǎng)度,即MAX_LENGTH,第三個(gè)維度表示詞表大小。
- 機(jī)器視覺(jué)與人工智能應(yīng)用開(kāi)發(fā)技術(shù)
- AI辦公高手速成:工具與提效技巧大全
- 移動(dòng)平臺(tái)深度神經(jīng)網(wǎng)絡(luò)實(shí)戰(zhàn):原理、架構(gòu)與優(yōu)化
- 巧用ChatGPT進(jìn)行數(shù)據(jù)分析與挖掘
- 從深度學(xué)習(xí)到圖神經(jīng)網(wǎng)絡(luò):模型與實(shí)踐
- 機(jī)器學(xué)習(xí)
- 人工智能視域下機(jī)器學(xué)習(xí)在教育研究中的應(yīng)用
- 人工智能及其應(yīng)用
- 信息流推薦算法
- 機(jī)器學(xué)習(xí)實(shí)踐指南:案例應(yīng)用解析
- 規(guī)則時(shí)代:虛擬現(xiàn)實(shí)、人工智能和區(qū)塊鏈構(gòu)建的游戲化未來(lái)
- AI加速器架構(gòu)設(shè)計(jì)與實(shí)現(xiàn)
- 圖分析與圖機(jī)器學(xué)習(xí):原理、算法與實(shí)踐
- 生成對(duì)抗網(wǎng)絡(luò)GAN:原理與實(shí)踐
- AI大模型企業(yè)落地指南