国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Python 基于pytorch從頭寫GPT模型;實(shí)現(xiàn)gpt實(shí)戰(zhàn)

這篇具有很好參考價(jià)值的文章主要介紹了Python 基于pytorch從頭寫GPT模型;實(shí)現(xiàn)gpt實(shí)戰(zhàn)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

1.GPT簡(jiǎn)介

????????GPT(Generative Pre-trained Transformer)模型是一種基于Transformer架構(gòu)的生成式預(yù)訓(xùn)練模型,由OpenAI開(kāi)發(fā)。它采用了無(wú)監(jiān)督學(xué)習(xí)的方式進(jìn)行預(yù)訓(xùn)練,然后通過(guò)微調(diào)適應(yīng)特定的任務(wù)。GPT模型的結(jié)構(gòu)由多層Transformer解碼器組成,每個(gè)解碼器由多頭自注意力機(jī)制和前饋神經(jīng)網(wǎng)絡(luò)組成。自注意力機(jī)制能夠?qū)斎氲男蛄羞M(jìn)行編碼,并捕捉序列中的上文關(guān)系,而前饋神經(jīng)網(wǎng)絡(luò)則負(fù)責(zé)對(duì)編碼后的向量進(jìn)行進(jìn)一步的非線性轉(zhuǎn)換。通過(guò)堆疊多個(gè)解碼器,GPT模型能夠?qū)W習(xí)到更加豐富的語(yǔ)義表示。

????????在預(yù)訓(xùn)練階段,GPT模型采用了大規(guī)模的無(wú)標(biāo)簽文本數(shù)據(jù),并根據(jù)上文來(lái)預(yù)測(cè)下一個(gè)詞。這個(gè)預(yù)測(cè)任務(wù)使模型能夠?qū)W習(xí)到語(yǔ)言的統(tǒng)計(jì)規(guī)律和語(yǔ)義信息。預(yù)訓(xùn)練采用了Transformer的自回歸結(jié)構(gòu),即每個(gè)位置的詞只能依賴于前面的詞。這種方式使得模型具有了生成文本的能力。

2018年6月 GPT-1:約5GB文本,1.17億參數(shù)量
2019年2月 GPT-2:約40GB文本,15億參數(shù)量
2020年5月 GPT-3:約45TB文本,1750億參數(shù)量

Python 基于pytorch從頭寫GPT模型;實(shí)現(xiàn)gpt實(shí)戰(zhàn),GPT,LLMs,NLP,深度學(xué)習(xí),人工智能,GPT,大模型,LLM

GPT又有哪些應(yīng)用呢?

1.1 文本生成:GPT可以通過(guò)學(xué)習(xí)大量文本數(shù)據(jù),從而生成新的文本。例如,可以用GPT來(lái)生成文章、故事、甚至是詩(shī)歌等。

1.2 對(duì)話系統(tǒng):GPT還可以用來(lái)構(gòu)建對(duì)話系統(tǒng),例如智能客服、聊天機(jī)器人等。用戶可以通過(guò)與GPT表達(dá)自己的意圖和需求,GPT可以自動(dòng)生成回復(fù)。

1.3 機(jī)器翻譯:GPT也可以用來(lái)進(jìn)行機(jī)器翻譯。通過(guò)學(xué)習(xí)不同語(yǔ)言的大量文本數(shù)據(jù),GPT可以將一種語(yǔ)言的文本轉(zhuǎn)換成另一種語(yǔ)言的文本。

1.4 情感分析:GPT可以用來(lái)進(jìn)行情感分析,例如對(duì)一段文本進(jìn)行情感分類,判斷其是正面、負(fù)面還是中性的。

1.5 問(wèn)答系統(tǒng):GPT還可以用來(lái)構(gòu)建問(wèn)答系統(tǒng),例如知識(shí)問(wèn)答、智能客服等。用戶可以通過(guò)向GPT提出問(wèn)題,GPT可以自動(dòng)生成回答。

2.GPT代碼實(shí)戰(zhàn)

2.1定義縮放點(diǎn)積注意力類

import numpy as np # 導(dǎo)入 numpy 庫(kù)
import torch # 導(dǎo)入 torch 庫(kù)
import torch.nn as nn # 導(dǎo)入 torch.nn 庫(kù)
d_k = 64 # K(=Q) 維度
d_v = 64 # V 維度
# 定義縮放點(diǎn)積注意力類
class ScaledDotProductAttention(nn.Module):
    def __init__(self):
        super(ScaledDotProductAttention, self).__init__()        
    def forward(self, Q, K, V, attn_mask):
        #------------------------- 維度信息 --------------------------------        
        # Q K V [batch_size, n_heads, len_q/k/v, dim_q=k/v] (dim_q=dim_k)
        # attn_mask [batch_size, n_heads, len_q, len_k]
        #----------------------------------------------------------------
        # 計(jì)算注意力分?jǐn)?shù)(原始權(quán)重)[batch_size,n_heads,len_q,len_k]
        scores = torch.matmul(Q, K.transpose(-1, -2)) / np.sqrt(d_k) 
        #------------------------- 維度信息 --------------------------------        
        # scores [batch_size, n_heads, len_q, len_k]
        #-----------------------------------------------------------------        
        # 使用注意力掩碼,將 attn_mask 中值為 1 的位置的權(quán)重替換為極小值
        #------------------------- 維度信息 -------------------------------- 
        # attn_mask [batch_size, n_heads, len_q, len_k], 形狀和 scores 相同
        #-----------------------------------------------------------------    
        scores.masked_fill_(attn_mask, -1e9) 
        # 對(duì)注意力分?jǐn)?shù)進(jìn)行 softmax 歸一化
        weights = nn.Softmax(dim=-1)(scores) 
        #------------------------- 維度信息 -------------------------------- 
        # weights [batch_size, n_heads, len_q, len_k], 形狀和 scores 相同
        #-----------------------------------------------------------------         
        # 計(jì)算上下文向量(也就是注意力的輸出), 是上下文信息的緊湊表示
        context = torch.matmul(weights, V) 
        #------------------------- 維度信息 -------------------------------- 
        # context [batch_size, n_heads, len_q, dim_v]
        #-----------------------------------------------------------------    
        return context, weights # 返回上下文向量和注意力分?jǐn)?shù)

2.2定義多頭自注意力類

# 定義多頭自注意力類
d_embedding = 512  # Embedding 的維度
n_heads = 8  # Multi-Head Attention 中頭的個(gè)數(shù)
batch_size = 3 # 每一批的數(shù)據(jù)大小
class MultiHeadAttention(nn.Module):
    def __init__(self):
        super(MultiHeadAttention, self).__init__()
        self.W_Q = nn.Linear(d_embedding, d_k * n_heads) # Q的線性變換層
        self.W_K = nn.Linear(d_embedding, d_k * n_heads) # K的線性變換層
        self.W_V = nn.Linear(d_embedding, d_v * n_heads) # V的線性變換層
        self.linear = nn.Linear(n_heads * d_v, d_embedding)
        self.layer_norm = nn.LayerNorm(d_embedding)
    def forward(self, Q, K, V, attn_mask): 
        #------------------------- 維度信息 -------------------------------- 
        # Q K V [batch_size, len_q/k/v, embedding_dim] 
        #-----------------------------------------------------------------        
        residual, batch_size = Q, Q.size(0) # 保留殘差連接
        # 將輸入進(jìn)行線性變換和重塑,以便后續(xù)處理
        q_s = self.W_Q(Q).view(batch_size, -1, n_heads, d_k).transpose(1,2)        
        k_s = self.W_K(K).view(batch_size, -1, n_heads, d_k).transpose(1,2)
        v_s = self.W_V(V).view(batch_size, -1, n_heads, d_v).transpose(1,2)
        #------------------------- 維度信息 -------------------------------- 
        # q_s k_s v_s: [batch_size, n_heads, len_q/k/v, d_q=k/v]
        #----------------------------------------------------------------- 
        # 將注意力掩碼復(fù)制到多頭 attn_mask: [batch_size, n_heads, len_q, len_k]
        attn_mask = attn_mask.unsqueeze(1).repeat(1, n_heads, 1, 1)
        #------------------------- 維度信息 -------------------------------- 
        # attn_mask [batch_size, n_heads, len_q, len_k]
        #----------------------------------------------------------------- 
        # 使用縮放點(diǎn)積注意力計(jì)算上下文和注意力權(quán)重
        context, weights = ScaledDotProductAttention()(q_s, k_s, v_s, attn_mask)
        #------------------------- 維度信息 -------------------------------- 
        # context [batch_size, n_heads, len_q, dim_v]
        # weights [batch_size, n_heads, len_q, len_k]
        #----------------------------------------------------------------- 
        # 通過(guò)調(diào)整維度將多個(gè)頭的上下文向量連接在一起
        context = context.transpose(1, 2).contiguous().view(batch_size, -1, n_heads * d_v) 
        #------------------------- 維度信息 -------------------------------- 
        # context [batch_size, len_q, n_heads * dim_v]
        #-----------------------------------------------------------------        
        # 用一個(gè)線性層把連接后的多頭自注意力結(jié)果轉(zhuǎn)換,原始地嵌入維度
        output = self.linear(context) 
        #------------------------- 維度信息 -------------------------------- 
        # output [batch_size, len_q, embedding_dim]
        #-----------------------------------------------------------------        
        # 與輸入 (Q) 進(jìn)行殘差鏈接,并進(jìn)行層歸一化后輸出
        output = self.layer_norm(output + residual)
        #------------------------- 維度信息 -------------------------------- 
        # output [batch_size, len_q, embedding_dim]
        #-----------------------------------------------------------------        
        return output, weights # 返回層歸一化的輸出和注意力權(quán)重

2.3定義逐位置前饋網(wǎng)絡(luò)類

# 定義逐位置前饋網(wǎng)絡(luò)類
class PoswiseFeedForwardNet(nn.Module):
    def __init__(self, d_ff=2048):
        super(PoswiseFeedForwardNet, self).__init__()
        # 定義一維卷積層 1,用于將輸入映射到更高維度
        self.conv1 = nn.Conv1d(in_channels=d_embedding, out_channels=d_ff, kernel_size=1)
        # 定義一維卷積層 2,用于將輸入映射回原始維度
        self.conv2 = nn.Conv1d(in_channels=d_ff, out_channels=d_embedding, kernel_size=1)
        # 定義層歸一化
        self.layer_norm = nn.LayerNorm(d_embedding)
    def forward(self, inputs): 
        #------------------------- 維度信息 -------------------------------- 
        # inputs [batch_size, len_q, embedding_dim]
        #----------------------------------------------------------------                       
        residual = inputs  # 保留殘差連接 
        # 在卷積層 1 后使用 ReLU 激活函數(shù) 
        output = nn.ReLU()(self.conv1(inputs.transpose(1, 2))) 
        #------------------------- 維度信息 -------------------------------- 
        # output [batch_size, d_ff, len_q]
        #----------------------------------------------------------------
        # 使用卷積層 2 進(jìn)行降維 
        output = self.conv2(output).transpose(1, 2) 
        #------------------------- 維度信息 -------------------------------- 
        # output [batch_size, len_q, embedding_dim]
        #----------------------------------------------------------------
        # 與輸入進(jìn)行殘差鏈接,并進(jìn)行層歸一化
        output = self.layer_norm(output + residual) 
        #------------------------- 維度信息 -------------------------------- 
        # output [batch_size, len_q, embedding_dim]
        #----------------------------------------------------------------
        return output # 返回加入殘差連接后層歸一化的結(jié)果

2.4生成正弦位置編碼表的函數(shù),用于在 Transformer 中引入位置信息?

# 生成正弦位置編碼表的函數(shù),用于在 Transformer 中引入位置信息
def get_sin_enc_table(n_position, embedding_dim):
    #------------------------- 維度信息 --------------------------------
    # n_position: 輸入序列的最大長(zhǎng)度
    # embedding_dim: 詞嵌入向量的維度
    #-----------------------------------------------------------------    
    # 根據(jù)位置和維度信息,初始化正弦位置編碼表
    sinusoid_table = np.zeros((n_position, embedding_dim))    
    # 遍歷所有位置和維度,計(jì)算角度值
    for pos_i in range(n_position):
        for hid_j in range(embedding_dim):
            angle = pos_i / np.power(10000, 2 * (hid_j // 2) / embedding_dim)
            sinusoid_table[pos_i, hid_j] = angle    
    # 計(jì)算正弦和余弦值
    sinusoid_table[:, 0::2] = np.sin(sinusoid_table[:, 0::2])  # dim 2i 偶數(shù)維
    sinusoid_table[:, 1::2] = np.cos(sinusoid_table[:, 1::2])  # dim 2i+1 奇數(shù)維    
    #------------------------- 維度信息 --------------------------------
    # sinusoid_table 的維度是 [n_position, embedding_dim]
    #----------------------------------------------------------------   
    return torch.FloatTensor(sinusoid_table)  # 返回正弦位置編碼表

2.5定義填充注意力掩碼函數(shù)?

# 定義填充注意力掩碼函數(shù)
def get_attn_pad_mask(seq_q, seq_k):
    #------------------------- 維度信息 --------------------------------
    # seq_q 的維度是 [batch_size, len_q]
    # seq_k 的維度是 [batch_size, len_k]
    #-----------------------------------------------------------------
    batch_size, len_q = seq_q.size()
    batch_size, len_k = seq_k.size()
    # 生成布爾類型張量
    pad_attn_mask = seq_k.data.eq(0).unsqueeze(1)  # <PAD>token 的編碼值為 0
    #------------------------- 維度信息 --------------------------------
    # pad_attn_mask 的維度是 [batch_size,1,len_k]
    #-----------------------------------------------------------------
    # 變形為與注意力分?jǐn)?shù)相同形狀的張量 
    pad_attn_mask = pad_attn_mask.expand(batch_size, len_q, len_k)
    #------------------------- 維度信息 --------------------------------
    # pad_attn_mask 的維度是 [batch_size,len_q,len_k]
    #-----------------------------------------------------------------
    return pad_attn_mask # 返回填充位置的注意力掩碼

2.6定義編碼器層類?

# 定義編碼器層類
class EncoderLayer(nn.Module):
    def __init__(self):
        super(EncoderLayer, self).__init__()        
        self.enc_self_attn = MultiHeadAttention() # 多頭自注意力層        
        self.pos_ffn = PoswiseFeedForwardNet() # 位置前饋神經(jīng)網(wǎng)絡(luò)層
    def forward(self, enc_inputs, enc_self_attn_mask):
        #------------------------- 維度信息 --------------------------------
        # enc_inputs 的維度是 [batch_size, seq_len, embedding_dim]
        # enc_self_attn_mask 的維度是 [batch_size, seq_len, seq_len]
        #-----------------------------------------------------------------
        # 將相同的 Q,K,V 輸入多頭自注意力層 , 返回的 attn_weights 增加了頭數(shù)  
        enc_outputs, attn_weights = self.enc_self_attn(enc_inputs, enc_inputs,
                                               enc_inputs, enc_self_attn_mask)
        #------------------------- 維度信息 --------------------------------
        # enc_outputs 的維度是 [batch_size, seq_len, embedding_dim] 
        # attn_weights 的維度是 [batch_size, n_heads, seq_len, seq_len]      
        # 將多頭自注意力 outputs 輸入位置前饋神經(jīng)網(wǎng)絡(luò)層
        enc_outputs = self.pos_ffn(enc_outputs) # 維度與 enc_inputs 相同
        #------------------------- 維度信息 --------------------------------
        # enc_outputs 的維度是 [batch_size, seq_len, embedding_dim] 
        #-----------------------------------------------------------------
        return enc_outputs, attn_weights # 返回編碼器輸出和每層編碼器注意力權(quán)重

2.7定義編碼器類

# 定義編碼器類
n_layers = 6  # 設(shè)置 Encoder 的層數(shù)
class Encoder(nn.Module):
    def __init__(self, corpus):
        super(Encoder, self).__init__()        
        self.src_emb = nn.Embedding(len(corpus.src_vocab), d_embedding) # 詞嵌入層
        self.pos_emb = nn.Embedding.from_pretrained( \
          get_sin_enc_table(corpus.src_len+1, d_embedding), freeze=True) # 位置嵌入層
        self.layers = nn.ModuleList(EncoderLayer() for _ in range(n_layers))# 編碼器層數(shù)
    def forward(self, enc_inputs):  
        #------------------------- 維度信息 --------------------------------
        # enc_inputs 的維度是 [batch_size, source_len]
        #-----------------------------------------------------------------
        # 創(chuàng)建一個(gè)從 1 到 source_len 的位置索引序列
        pos_indices = torch.arange(1, enc_inputs.size(1) + 1).unsqueeze(0).to(enc_inputs)
        #------------------------- 維度信息 --------------------------------
        # pos_indices 的維度是 [1, source_len]
        #-----------------------------------------------------------------             
        # 對(duì)輸入進(jìn)行詞嵌入和位置嵌入相加 [batch_size, source_len,embedding_dim]
        enc_outputs = self.src_emb(enc_inputs) + self.pos_emb(pos_indices)
        #------------------------- 維度信息 --------------------------------
        # enc_outputs 的維度是 [batch_size, seq_len, embedding_dim]
        #-----------------------------------------------------------------
        # 生成自注意力掩碼
        enc_self_attn_mask = get_attn_pad_mask(enc_inputs, enc_inputs) 
        #------------------------- 維度信息 --------------------------------
        # enc_self_attn_mask 的維度是 [batch_size, len_q, len_k]        
        #-----------------------------------------------------------------         
        enc_self_attn_weights = [] # 初始化 enc_self_attn_weights
        # 通過(guò)編碼器層 [batch_size, seq_len, embedding_dim]
        for layer in self.layers: 
            enc_outputs, enc_self_attn_weight = layer(enc_outputs, enc_self_attn_mask)
            enc_self_attn_weights.append(enc_self_attn_weight)
        #------------------------- 維度信息 --------------------------------
        # enc_outputs 的維度是 [batch_size, seq_len, embedding_dim] 維度與 enc_inputs 相同
        # enc_self_attn_weights 是一個(gè)列表,每個(gè)元素的維度是 [batch_size, n_heads, seq_len, seq_len]          
        #-----------------------------------------------------------------
        return enc_outputs, enc_self_attn_weights # 返回編碼器輸出和編碼器注意力權(quán)重

2.8生成后續(xù)注意力掩碼的函數(shù),用于在多頭自注意力計(jì)算中忽略未來(lái)信息

# 生成后續(xù)注意力掩碼的函數(shù),用于在多頭自注意力計(jì)算中忽略未來(lái)信息
def get_attn_subsequent_mask(seq):
    #------------------------- 維度信息 --------------------------------
    # seq 的維度是 [batch_size, seq_len(Q)=seq_len(K)]
    #-----------------------------------------------------------------
    # 獲取輸入序列的形狀
    attn_shape = [seq.size(0), seq.size(1), seq.size(1)]  
    #------------------------- 維度信息 --------------------------------
    # attn_shape 是一個(gè)一維張量 [batch_size, seq_len(Q), seq_len(K)]
    #-----------------------------------------------------------------
    # 使用 numpy 創(chuàng)建一個(gè)上三角矩陣(triu = triangle upper)
    subsequent_mask = np.triu(np.ones(attn_shape), k=1)
    #------------------------- 維度信息 --------------------------------
    # subsequent_mask 的維度是 [batch_size, seq_len(Q), seq_len(K)]
    #-----------------------------------------------------------------
    # 將 numpy 數(shù)組轉(zhuǎn)換為 PyTorch 張量,并將數(shù)據(jù)類型設(shè)置為 byte(布爾值)
    subsequent_mask = torch.from_numpy(subsequent_mask).byte()
    #------------------------- 維度信息 --------------------------------
    # 返回的 subsequent_mask 的維度是 [batch_size, seq_len(Q), seq_len(K)]
    #-----------------------------------------------------------------
    return subsequent_mask # 返回后續(xù)位置的注意力掩碼

2.9定義解碼器層類

# 定義解碼器層類
class DecoderLayer(nn.Module):
    def __init__(self):
        super(DecoderLayer, self).__init__()
        self.self_attn = MultiHeadAttention()  # 多頭自注意力層
        self.feed_forward = PoswiseFeedForwardNet()  # 逐位置前饋網(wǎng)絡(luò)層
        self.norm1 = nn.LayerNorm(d_embedding)  # 第一個(gè)層歸一化
        self.norm2 = nn.LayerNorm(d_embedding)  # 第二個(gè)層歸一化
    def forward(self, dec_inputs, attn_mask=None):
        # 使用多頭自注意力處理輸入
        attn_output, _ = self.self_attn(dec_inputs, dec_inputs, dec_inputs, attn_mask)
        # 將注意力輸出與輸入相加并進(jìn)行第一個(gè)層歸一化
        norm1_outputs = self.norm1(dec_inputs + attn_output)
        # 將歸一化后的輸出輸入到位置前饋神經(jīng)網(wǎng)絡(luò)
        ff_outputs = self.feed_forward(norm1_outputs)
        # 將前饋神經(jīng)網(wǎng)絡(luò)輸出與第一次歸一化后的輸出相加并進(jìn)行第二個(gè)層歸一化
        dec_outputs = self.norm2(norm1_outputs + ff_outputs)
        return dec_outputs # 返回解碼器層輸出

2.10定義解碼器類

#  定義解碼器類
n_layers = 6  # 設(shè)置 Decoder 的層數(shù)
class Decoder(nn.Module):
    def __init__(self, vocab_size, max_seq_len):
        super(Decoder, self).__init__()
        # 詞嵌入層(參數(shù)為詞典維度)
        self.src_emb = nn.Embedding(vocab_size, d_embedding)  
        # 位置編碼層(參數(shù)為序列長(zhǎng)度)
        self.pos_emb = nn.Embedding(max_seq_len, d_embedding)
        # 初始化 N 個(gè)解碼器層       
        self.layers = nn.ModuleList([DecoderLayer() for _ in range(n_layers)]) 
    def forward(self, dec_inputs):        
        # 創(chuàng)建位置信息
        positions = torch.arange(len(dec_inputs), device=dec_inputs.device).unsqueeze(-1)
        # 將詞嵌入與位置編碼相加
        inputs_embedding = self.src_emb(dec_inputs) + self.pos_emb(positions)
        # 生成自注意力掩碼
        attn_mask = get_attn_subsequent_mask(inputs_embedding).to(device)
        # 初始化解碼器輸入,這是第一層解碼器層的輸入 
        dec_outputs =  inputs_embedding 
        for layer in self.layers:
            # 將輸入數(shù)據(jù)傳遞給解碼器層,并返回解碼器層的輸出,作為下一層的輸入
            dec_outputs = layer(dec_outputs, attn_mask) 
        return dec_outputs # 返回解碼器輸出

2.11定義 GPT 模型?

# 定義 GPT 模型
class GPT(nn.Module):
    def __init__(self, vocab_size, max_seq_len):
        super(GPT, self).__init__()
        self.decoder = Decoder(vocab_size, max_seq_len) # 解碼器,用于學(xué)習(xí)文本生成能力
        self.projection = nn.Linear(d_embedding, vocab_size)  # 全連接層,輸出預(yù)測(cè)結(jié)果
    def forward(self, dec_inputs):        
        dec_outputs = self.decoder(dec_inputs) # 將輸入數(shù)據(jù)傳遞給解碼器
        logits = self.projection(dec_outputs) # 傳遞給全連接層以生成預(yù)測(cè)
        return logits # 返回預(yù)測(cè)結(jié)果

2.12構(gòu)建語(yǔ)料庫(kù)?

# 構(gòu)建語(yǔ)料庫(kù)
from collections import Counter
class LanguageCorpus:
    def __init__(self, sentences):
        self.sentences = sentences
        # 計(jì)算語(yǔ)言的最大句子長(zhǎng)度,并加 2 以容納特殊符號(hào) <sos> 和 <eos>
        self.seq_len = max([len(sentence.split()) for sentence in sentences]) + 2
        self.vocab = self.create_vocabulary() # 創(chuàng)建源語(yǔ)言和目標(biāo)語(yǔ)言的詞匯表
        self.idx2word = {v: k for k, v in self.vocab.items()} # 創(chuàng)建索引到單詞的映射
    def create_vocabulary(self):
        vocab = {'<pad>': 0, '<sos>': 1, '<eos>': 2}
        counter = Counter()
        # 統(tǒng)計(jì)語(yǔ)料庫(kù)的單詞頻率
        for sentence in self.sentences:
            words = sentence.split()
            counter.update(words)
        # 創(chuàng)建詞匯表,并為每個(gè)單詞分配一個(gè)唯一的索引
        for word in counter:
            if word not in vocab:
                vocab[word] = len(vocab)
        return vocab
    def make_batch(self, batch_size, test_batch=False):
        input_batch, output_batch = [], [] # 初始化批數(shù)據(jù)
        sentence_indices = torch.randperm(len(self.sentences))[:batch_size] # 隨機(jī)選擇句子索引
        for index in sentence_indices:
            sentence = self.sentences[index]
            # 將句子轉(zhuǎn)換為索引序列
            seq = [self.vocab['<sos>']] + [self.vocab[word] for word in sentence.split()] + [self.vocab['<eos>']]
            seq += [self.vocab['<pad>']] * (self.seq_len - len(seq)) # 對(duì)序列進(jìn)行填充
            # 將處理好的序列添加到批次中
            input_batch.append(seq[:-1])
            output_batch.append(seq[1:])
        return torch.LongTensor(input_batch), torch.LongTensor(output_batch)

2.13預(yù)料處理

with open("lang.txt", "r") as file: # 從文件中讀入語(yǔ)料
    sentences = [line.strip() for line in file.readlines()]
corpus = LanguageCorpus(sentences) # 創(chuàng)建語(yǔ)料庫(kù)
vocab_size = len(corpus.vocab) # 詞匯表大小
max_seq_len = corpus.seq_len # 最大句子長(zhǎng)度(用于設(shè)置位置編碼)
print(f" 語(yǔ)料庫(kù)詞匯表大小 : {vocab_size}") # 打印詞匯表大小
print(f" 最長(zhǎng)句子長(zhǎng)度 : {max_seq_len}") # 打印最大序列長(zhǎng)

2.14訓(xùn)練模型

import torch.optim as optim # 導(dǎo)入優(yōu)化器
device = "cuda" if torch.cuda.is_available() else "cpu" # 設(shè)置設(shè)備
model = GPT(vocab_size, max_seq_len).to(device) # 創(chuàng)建 GPT 模型實(shí)例
criterion = nn.CrossEntropyLoss() # 損失函數(shù)
optimizer = optim.Adam(model.parameters(), lr=0.0001) # 優(yōu)化器
epochs = 500 # 訓(xùn)練輪次
for epoch in range(epochs):  # 訓(xùn)練 epochs 輪
    optimizer.zero_grad() # 梯度清零
    inputs, targets = corpus.make_batch(batch_size) # 創(chuàng)建訓(xùn)練數(shù)據(jù)
    inputs, targets = inputs.to(device), targets.to(device)
    outputs = model(inputs) # 獲取模型輸出 
    loss = criterion(outputs.view(-1, vocab_size), targets.view(-1)) # 計(jì)算損失
    if (epoch + 1) % 100 == 0: # 打印損失
        print(f"Epoch: {epoch + 1:04d} cost = {loss:.6f}")
    loss.backward() # 反向傳播
    optimizer.step() # 更新參數(shù)

2.15測(cè)試文本生成?

# 測(cè)試文本生成
def generate_text(model, input_str, max_len=50):
    model.eval()  # 將模型設(shè)置為評(píng)估(測(cè)試)模式,關(guān)閉 dropout 和 batch normalization 等訓(xùn)練相關(guān)的層
    # 將輸入字符串中的每個(gè) token 轉(zhuǎn)換為其在詞匯表中的索引
    input_tokens = [corpus.vocab[token] for token in input_str]
    # 創(chuàng)建一個(gè)新列表,將輸入的 tokens 復(fù)制到輸出 tokens 中 , 目前只有輸入的詞
    output_tokens = input_tokens.copy()
    with torch.no_grad():  # 禁用梯度計(jì)算,以節(jié)省內(nèi)存并加速測(cè)試過(guò)程
        for _ in range(max_len):  # 生成最多 max_len 個(gè) tokens
            # 將輸出的 token 轉(zhuǎn)換為 PyTorch 張量,并增加一個(gè)代表批次的維度 [1, len(output_tokens)]
            inputs = torch.LongTensor(output_tokens).unsqueeze(0).to(device)
            outputs = model(inputs) # 輸出 logits 形狀為 [1, len(output_tokens), vocab_size]
            # 在最后一個(gè)維度上獲取 logits 中的最大值,并返回其索引(即下一個(gè) token)
            _, next_token = torch.max(outputs[:, -1, :], dim=-1)            
            next_token = next_token.item() # 將張量轉(zhuǎn)換為 Python 整數(shù)            
            if next_token == corpus.vocab["<eos>"]:
                break # 如果生成的 token 是 EOS(結(jié)束符),則停止生成過(guò)程           
            output_tokens.append(next_token) # 將生成的 tokens 添加到 output_tokens 列表
    # 將輸出 tokens 轉(zhuǎn)換回文本字符串
    output_str = " ".join([corpus.idx2word[token] for token in output_tokens])
    return output_str
input_str = ["Python"] # 輸入一個(gè)詞:Python
generated_text = generate_text(model, input_str) # 模型跟著這個(gè)詞生成后續(xù)文本
print(" 生成的文本 :", generated_text) # 打印預(yù)測(cè)文本

3.總結(jié)?

注意:GPT只有解碼器部分,但是我全都定義了,大家順便復(fù)習(xí)一下,然后仔細(xì)看一下解碼器的結(jié)構(gòu)。

?????????GPT模型的訓(xùn)練分為兩個(gè)階段:預(yù)訓(xùn)練和微調(diào)。在預(yù)訓(xùn)練階段,GPT模型利用大規(guī)模文本數(shù)據(jù)進(jìn)行自監(jiān)督學(xué)習(xí),通過(guò)掩蓋輸入文本的一部分內(nèi)容,讓模型預(yù)測(cè)被掩蓋的部分。這個(gè)預(yù)測(cè)任務(wù)被稱為“掩碼語(yǔ)言模型”(Masked Language Modeling)。

????????在微調(diào)階段,GPT模型通過(guò)在特定任務(wù)上進(jìn)行有監(jiān)督的微調(diào)來(lái)利用其在預(yù)訓(xùn)練階段學(xué)到的語(yǔ)言知識(shí)。通過(guò)在少量標(biāo)注數(shù)據(jù)上進(jìn)行微調(diào),GPT模型可以適應(yīng)特定的任務(wù),如文本生成、文本分類、機(jī)器翻譯等。

????????然而,GPT模型也存在一些挑戰(zhàn)和限制。例如,由于是基于自動(dòng)回歸的方式生成文本,它可能面臨生成不準(zhǔn)確、重復(fù)、和不連貫的問(wèn)題。此外,GPT模型對(duì)訓(xùn)練數(shù)據(jù)的質(zhì)量和多樣性敏感,可能會(huì)受到輸入偏見(jiàn)和不準(zhǔn)確信息的影響。

注意“l(fā)ang.txt”內(nèi)容如下:

Python is a popular programming language.
I love to code in Python.
Data science is a hot topic in the tech industry.
Machine learning and deep learning are important parts of data science.
I am learning how to build neural networks.
Neural networks are modeled after the structure of the human brain.
Artificial intelligence has many applications in various industries.
Natural language processing is a branch of AI that deals with language understanding.
The rise of big data has led to an increased demand for data scientists.
I enjoy analyzing and visualizing data using Python libraries like Pandas and Matplotlib.
Data cleaning is an important part of data analysis.
I am fascinated by the power of deep learning algorithms.
Self-driving cars are an example of the practical applications of AI.
The tech industry is constantly evolving and changing.
I believe that AI will have a major impact on the future of work.
I am excited to see how AI will continue to develop and change the world.
The ethical implications of AI are a topic of much debate and discussion.
As with any powerful technology, there is a responsibility to use AI ethically and responsibly.
I think that the benefits of AI outweigh the risks, if used wisely.
Programming is a valuable skill in the digital age.文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-817167.html

到了這里,關(guān)于Python 基于pytorch從頭寫GPT模型;實(shí)現(xiàn)gpt實(shí)戰(zhàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Python基于PyTorch實(shí)現(xiàn)卷積神經(jīng)網(wǎng)絡(luò)分類模型(CNN分類算法)項(xiàng)目實(shí)戰(zhàn)

    Python基于PyTorch實(shí)現(xiàn)卷積神經(jīng)網(wǎng)絡(luò)分類模型(CNN分類算法)項(xiàng)目實(shí)戰(zhàn)

    說(shuō)明:這是一個(gè)機(jī)器學(xué)習(xí)實(shí)戰(zhàn)項(xiàng)目(附帶 數(shù)據(jù)+代碼+文檔+視頻講解 ),如需 數(shù)據(jù)+代碼+文檔+視頻講解 可以直接到文章最后獲取。 卷積神經(jīng)網(wǎng)絡(luò),簡(jiǎn)稱為卷積網(wǎng)絡(luò),與普通神經(jīng)網(wǎng)絡(luò)的區(qū)別是它的卷積層內(nèi)的神經(jīng)元只覆蓋輸入特征局部范圍的單元,具有稀疏連接(sparse connec

    2024年02月15日
    瀏覽(26)
  • openai開(kāi)放gpt3.5-turbo模型api,使用python即可寫一個(gè)基于gpt的智能問(wèn)答機(jī)器人

    openai開(kāi)放gpt3.5-turbo模型api,使用python即可寫一個(gè)基于gpt的智能問(wèn)答機(jī)器人

    使用 pip 安裝openai庫(kù),注意 gpt3.5-turbo 模型需要 python=3.9 的版本支持,本文演示的python版本是 python==3.10.10 需要提前在 openai 官網(wǎng)上注冊(cè)好賬號(hào),然后打開(kāi) https://platform.openai.com/account/api-keys 就可以創(chuàng)建接口 keys 每個(gè)賬號(hào)注冊(cè)完成會(huì)有18美元在里面,每次調(diào)用api,就會(huì)花費(fèi)里面的

    2024年02月06日
    瀏覽(104)
  • 搭建部署屬于自己的基于gpt3.5的大語(yǔ)言模型(基于flask+html+css+js+mysql實(shí)現(xiàn))

    本項(xiàng)目是一個(gè)基于GPT-3.5模型的聊天機(jī)器人網(wǎng)站,旨在為用戶提供一個(gè)簡(jiǎn)便、直接的方式來(lái)體驗(yàn)和利用GPT-3.5模型的強(qiáng)大功能。項(xiàng)目以Flask為基礎(chǔ),構(gòu)建了一個(gè)完整的Web應(yīng)用程序,其中包含了多個(gè)前端頁(yè)面和后端API接口,能夠處理用戶輸入并與GPT-3.5模型進(jìn)行交互來(lái)生成響應(yīng)。 一

    2024年02月07日
    瀏覽(93)
  • 基于Transformer語(yǔ)言模型:GPT-2

    基于Transformer語(yǔ)言模型:GPT-2 ??Transformer是Google在2017年提出的一種新型模型架構(gòu)。它以自注意力機(jī)制取代傳統(tǒng)的RNN和CNN對(duì)序列數(shù)據(jù)的建模,它在機(jī)器翻譯、語(yǔ)言理解等任務(wù)上顯示出強(qiáng)大的表示能力,目前已經(jīng)成為自然語(yǔ)言處理領(lǐng)域的主流框架之一。主要特點(diǎn)有: 完全基于注意

    2024年02月07日
    瀏覽(20)
  • GPT實(shí)戰(zhàn)系列-如何用自己數(shù)據(jù)微調(diào)ChatGLM2模型訓(xùn)練

    廣告文案生成模型 輸入文字 :類型#裙 顏色#藍(lán)色 風(fēng)格#清新*圖案#蝴蝶結(jié) 輸出文案 :裙身處采用立體蝴蝶結(jié)裝飾輔以藍(lán)色條帶點(diǎn)綴,令衣身造型飽滿富有層次的同時(shí)為其注入一絲甜美氣息。將女孩清新嬌俏的一面襯托而出。 訓(xùn)練和測(cè)試數(shù)據(jù)組織: 數(shù)據(jù)可以從 下載鏈接,t

    2024年02月06日
    瀏覽(18)
  • MATLAB算法實(shí)戰(zhàn)應(yīng)用案例精講-【深度學(xué)習(xí)】預(yù)訓(xùn)練模型GPT&XLNet

    目錄 GPT 1. 介紹 1.1 GPT的動(dòng)機(jī) 2. 模型結(jié)構(gòu) 3. GPT訓(xùn)練過(guò)程 3.1 無(wú)監(jiān)督的預(yù)訓(xùn)練

    2024年02月15日
    瀏覽(21)
  • 基于Tensorflow來(lái)重現(xiàn)GPT v1模型

    基于Tensorflow來(lái)重現(xiàn)GPT v1模型

    OpenAI推出的ChatGPT模型讓我們看到了通用人工智能的發(fā)展?jié)摿?,我也找了GPT的相關(guān)論文來(lái)進(jìn)行研究。OpenAI在2017年的論文Improving Language Understanding by Generative Pre-Training提出了GPT的第一個(gè)版本,我也基于這個(gè)論文來(lái)用Tensorflow進(jìn)行了復(fù)現(xiàn)。 GPT是基于bookcorpus數(shù)據(jù)集來(lái)進(jìn)行預(yù)訓(xùn)練的。在

    2024年02月16日
    瀏覽(25)
  • 大語(yǔ)言模型的預(yù)訓(xùn)練[2]:GPT、GPT2、GPT3、GPT3.5、GPT4相關(guān)理論知識(shí)和模型實(shí)現(xiàn)、模型應(yīng)用以及各個(gè)版本之間的區(qū)別詳解

    大語(yǔ)言模型的預(yù)訓(xùn)練[2]:GPT、GPT2、GPT3、GPT3.5、GPT4相關(guān)理論知識(shí)和模型實(shí)現(xiàn)、模型應(yīng)用以及各個(gè)版本之間的區(qū)別詳解

    在自然語(yǔ)言處理問(wèn)題中,可從互聯(lián)網(wǎng)上下載大量無(wú)標(biāo)注數(shù)據(jù),而針對(duì)具體問(wèn)題的有標(biāo)注數(shù)據(jù)卻非常少,GPT 是一種半監(jiān)督學(xué)習(xí)方法,它致力于用大量無(wú)標(biāo)注數(shù)據(jù)讓模型學(xué)習(xí) “常識(shí)”,以緩解標(biāo)注信息不足的問(wèn)題。其具體方法是在針對(duì)有標(biāo)簽數(shù)據(jù)訓(xùn)練 Fine-tune 之前,用無(wú)標(biāo)簽數(shù)據(jù)

    2024年02月16日
    瀏覽(91)
  • ChatGPT:基于GPT-3.5架構(gòu)的強(qiáng)大語(yǔ)言模型

    ChatGPT:基于GPT-3.5架構(gòu)的強(qiáng)大語(yǔ)言模型

    這段時(shí)間,周圍朋友們討論最多的除了春招的激烈之外,就是ChatGPT了,大家被ChatGPT的智能和超強(qiáng)的學(xué)習(xí)能力所震驚,甚至擔(dān)心未來(lái)會(huì)被人工智能所取代。 這樣的擔(dān)心不無(wú)道理,我們程序員作為技術(shù)人員,需要對(duì)新技術(shù)保持敏銳的嗅覺(jué),以免被時(shí)代拋棄。但就我最近對(duì)ChatGP

    2024年02月07日
    瀏覽(18)
  • 基于大模型GPT,如何提煉出優(yōu)質(zhì)的Prompt

    基于大模型GPT,如何提煉出優(yōu)質(zhì)的Prompt

    在當(dāng)今信息爆炸的時(shí)代AIGC時(shí)代的發(fā)展,自然語(yǔ)言處理技術(shù)的快速發(fā)展給人們帶來(lái)了前所未有的機(jī)遇和挑戰(zhàn)。作為其中的重要組成部分,大模型語(yǔ)言模型在多個(gè)領(lǐng)域展現(xiàn)了強(qiáng)大的能力。然而,隨著模型的增長(zhǎng)和復(fù)雜性的提升,如何引導(dǎo)模型生成準(zhǔn)確、有價(jià)值的輸出成為了一個(gè)關(guān)

    2024年02月07日
    瀏覽(15)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包