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

深度學(xué)習(xí)處理文本(NLP)

這篇具有很好參考價(jià)值的文章主要介紹了深度學(xué)習(xí)處理文本(NLP)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

引言

深度學(xué)習(xí)處理文本(NLP),Natural Language Processing,深度學(xué)習(xí),自然語言處理,人工智能,python

深度學(xué)習(xí)處理文本主要涉及到自然語言處理(NLP)領(lǐng)域。隨著深度學(xué)習(xí)技術(shù)的發(fā)展,NLP領(lǐng)域已經(jīng)取得了很大的進(jìn)展。以下是深度學(xué)習(xí)在處理文本中的一些主要應(yīng)用和技術(shù):

  1. 詞嵌入(Word Embeddings): 詞嵌入是將詞匯表中的單詞映射到稠密的向量,常用的方法有Word2Vec, GloVe和FastText。這些向量捕獲單詞之間的語義相似性。
  2. 循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN): RNN是一種處理序列數(shù)據(jù)(如文本)的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)。它通過保存前一時(shí)間步的狀態(tài)來捕獲序列中的時(shí)間依賴關(guān)系。
  3. 長短時(shí)記憶網(wǎng)絡(luò)(LSTM)和門控循環(huán)單元(GRU): 由于RNNs的短期記憶問題,LSTM和GRU被引入以捕獲長距離的依賴關(guān)系。
  4. Transformer 結(jié)構(gòu): 引入了自注意力機(jī)制的Transformer結(jié)構(gòu),如BERT, GPT, T5等模型,已經(jīng)在多個(gè)NLP任務(wù)上取得了當(dāng)前的最佳表現(xiàn)。
  5. 序列到序列模型(Seq2Seq): 這種模型常用于機(jī)器翻譯、文本摘要等任務(wù),通常與LSTM或Transformer結(jié)構(gòu)一起使用。
  6. 卷積神經(jīng)網(wǎng)絡(luò)(CNN): 盡管CNN主要用于圖像處理,但它也可以用于捕獲文本中的局部模式。例如,用于情感分析和文本分類任務(wù)。
  7. 遷移學(xué)習(xí): 通過預(yù)先訓(xùn)練的模型(例如BERT),我們可以輕松地微調(diào)特定任務(wù),從而減少訓(xùn)練時(shí)間和數(shù)據(jù)需求。
  8. 注意力機(jī)制: 注意力機(jī)制使模型能夠關(guān)注輸入序列的特定部分,這在機(jī)器翻譯和文本摘要等任務(wù)中特別有用。

處理文本的常見應(yīng)用包括:文本分類、情感分析、命名實(shí)體識(shí)別、文本摘要、機(jī)器翻譯、問答系統(tǒng)等。

為了在深度學(xué)習(xí)模型中使用文本,通常首先需要進(jìn)行預(yù)處理,如分詞、詞干提取、去除停用詞、轉(zhuǎn)換為詞嵌入等。然后,這些預(yù)處理后的文本數(shù)據(jù)可以作為深度學(xué)習(xí)模型的輸入。

1. 反向傳播

1.1 實(shí)例流程實(shí)現(xiàn)

深度學(xué)習(xí)處理文本(NLP),Natural Language Processing,深度學(xué)習(xí),自然語言處理,人工智能,python
深度學(xué)習(xí)處理文本(NLP),Natural Language Processing,深度學(xué)習(xí),自然語言處理,人工智能,python

1.2 前向傳播

  • 從輸入層開始,傳遞數(shù)據(jù)通過每一層。
  • 在每一層,使用當(dāng)前的權(quán)重計(jì)算節(jié)點(diǎn)的輸出。
  • 這些輸出成為下一層的輸入。

1.3 計(jì)算損失

  • 一旦數(shù)據(jù)通過所有層并生成了輸出,就可以計(jì)算損失函數(shù)(如均方誤差)來衡量網(wǎng)絡(luò)預(yù)測的準(zhǔn)確性。

1.4 反向傳播誤差

  • 計(jì)算輸出層誤差,并將其反向傳播到前面的層。
  • 使用鏈?zhǔn)椒▌t計(jì)算每一層的誤差。

1.5 更新權(quán)重

  • 使用學(xué)習(xí)率和之前計(jì)算的梯度來調(diào)整每一層的權(quán)重。
  • 基本公式為: Δw=?η??J,其中 η 是學(xué)習(xí)率,?J 是損失函數(shù) J 關(guān)于權(quán)重 w 的梯度。

1.6 迭代

  • 重復(fù)以上步驟多次,直到損失收斂到一個(gè)最小值或滿足其他停止標(biāo)準(zhǔn)。

反向傳播的核心是通過鏈?zhǔn)椒▌t來計(jì)算損失函數(shù)相對(duì)于每個(gè)權(quán)重的偏導(dǎo)數(shù)。這些偏導(dǎo)數(shù)提供了權(quán)重應(yīng)該如何調(diào)整的方向以減少誤差。

為了實(shí)現(xiàn)反向傳播,通常使用優(yōu)化算法,如梯度下降或其變體(如隨機(jī)梯度下降、Adam、RMSprop等),來更新網(wǎng)絡(luò)中的權(quán)重。

1.7 BackPropagation & Adam 代碼實(shí)例

#coding:utf8

import torch
import torch.nn as nn
import numpy as np
import copy

"""
基于pytorch的網(wǎng)絡(luò)編寫
手動(dòng)實(shí)現(xiàn)梯度計(jì)算和反向傳播
加入激活函數(shù)
"""

class TorchModel(nn.Module):
    def __init__(self, hidden_size):
        super(TorchModel, self).__init__()
        self.layer = nn.Linear(hidden_size, hidden_size, bias=False)
        self.activation = torch.sigmoid
        self.loss = nn.functional.mse_loss  #loss采用均方差損失

    #當(dāng)輸入真實(shí)標(biāo)簽,返回loss值;無真實(shí)標(biāo)簽,返回預(yù)測值
    def forward(self, x, y=None):
        y_pred = self.layer(x)
        y_pred = self.activation(y_pred)
        if y is not None:
            return self.loss(y_pred, y)
        else:
            return y_pred


#自定義模型,接受一個(gè)參數(shù)矩陣作為入?yún)?/span>
class DiyModel:
    def __init__(self, weight):
        self.weight = weight

    def forward(self, x, y=None):
        x = np.dot(x, self.weight.T)
        y_pred = self.diy_sigmoid(x)
        if y is not None:
            return self.diy_mse_loss(y_pred, y)
        else:
            return y_pred

    #sigmoid
    def diy_sigmoid(self, x):
        return 1 / (1 + np.exp(-x))

    #手動(dòng)實(shí)現(xiàn)mse,均方差loss
    def diy_mse_loss(self, y_pred, y_true):
        return np.sum(np.square(y_pred - y_true)) / len(y_pred)

    #手動(dòng)實(shí)現(xiàn)梯度計(jì)算
    def calculate_grad(self, y_pred, y_true, x):
        #前向過程
        # wx = np.dot(self.weight, x)
        # sigmoid_wx = self.diy_sigmoid(wx)
        # loss = self.diy_mse_loss(sigmoid_wx, y_true)
        #反向過程
        # 均方差函數(shù) (y_pred - y_true) ^ 2 / n 的導(dǎo)數(shù) = 2 * (y_pred - y_true) / n , 結(jié)果為2維向量
        grad_mse = 2/len(x) * (y_pred - y_true)
        # sigmoid函數(shù) y = 1/(1+e^(-x)) 的導(dǎo)數(shù) = y * (1 - y), 結(jié)果為2維向量
        grad_sigmoid = y_pred * (1 - y_pred)
        # wx矩陣運(yùn)算,見ppt拆解, wx = [w11*x0 + w21*x1, w12*x0 + w22*x1]
        #導(dǎo)數(shù)鏈?zhǔn)较喑?/span>
        grad_w11 = grad_mse[0] * grad_sigmoid[0] * x[0]
        grad_w12 = grad_mse[1] * grad_sigmoid[1] * x[0]
        grad_w21 = grad_mse[0] * grad_sigmoid[0] * x[1]
        grad_w22 = grad_mse[1] * grad_sigmoid[1] * x[1]
        grad = np.array([[grad_w11, grad_w12],
                         [grad_w21, grad_w22]])
        #由于pytorch存儲(chǔ)做了轉(zhuǎn)置,輸出時(shí)也做轉(zhuǎn)置處理
        return grad.T

#梯度更新
def diy_sgd(grad, weight, learning_rate):
    return weight - learning_rate * grad

#adam梯度更新
def diy_adam(grad, weight):
    #參數(shù)應(yīng)當(dāng)放在外面,此處為保持后方代碼整潔簡單實(shí)現(xiàn)一步
    alpha = 1e-3  #學(xué)習(xí)率
    beta1 = 0.9   #超參數(shù)
    beta2 = 0.999 #超參數(shù)
    eps = 1e-8    #超參數(shù)
    t = 0         #初始化
    mt = 0        #初始化
    vt = 0        #初始化
    #開始計(jì)算
    t = t + 1
    gt = grad
    mt = beta1 * mt + (1 - beta1) * gt
    vt = beta2 * vt + (1 - beta2) * gt ** 2
    mth = mt / (1 - beta1 ** t)
    vth = vt / (1 - beta2 ** t)
    weight = weight - (alpha / (np.sqrt(vth) + eps)) * mth
    return weight

x = np.array([-0.5, 0.1])  #輸入
y = np.array([0.1, 0.2])  #預(yù)期輸出

#torch實(shí)驗(yàn)
torch_model = TorchModel(2)
torch_model_w = torch_model.state_dict()["layer.weight"]
print(torch_model_w, "初始化權(quán)重")
numpy_model_w = copy.deepcopy(torch_model_w.numpy())
#numpy array -> torch tensor, unsqueeze的目的是增加一個(gè)batchsize維度
torch_x = torch.from_numpy(x).float().unsqueeze(0)
torch_y = torch.from_numpy(y).float().unsqueeze(0)
#torch的前向計(jì)算過程,得到loss
torch_loss = torch_model(torch_x, torch_y)
print("torch模型計(jì)算loss:", torch_loss)
# #手動(dòng)實(shí)現(xiàn)loss計(jì)算
diy_model = DiyModel(numpy_model_w)
diy_loss = diy_model.forward(x, y)
print("diy模型計(jì)算loss:", diy_loss)

# #設(shè)定優(yōu)化器
learning_rate = 0.1
optimizer = torch.optim.SGD(torch_model.parameters(), lr=learning_rate)
# optimizer = torch.optim.Adam(torch_model.parameters())
optimizer.zero_grad()
#
# #pytorch的反向傳播操作
torch_loss.backward()
print(torch_model.layer.weight.grad, "torch 計(jì)算梯度")  #查看某層權(quán)重的梯度

# #手動(dòng)實(shí)現(xiàn)反向傳播
grad = diy_model.calculate_grad(diy_model.forward(x), y, x)
print(grad, "diy 計(jì)算梯度")
#
# #torch梯度更新
# optimizer.step()
# #查看更新后權(quán)重
# update_torch_model_w = torch_model.state_dict()["layer.weight"]
# print(update_torch_model_w, "torch更新后權(quán)重")
#
# #手動(dòng)梯度更新
# diy_update_w = diy_sgd(grad, numpy_model_w, learning_rate)
# diy_update_w = diy_adam(grad, numpy_model_w)
# print(diy_update_w, "diy更新權(quán)重")

2. 優(yōu)化器 – Adam

2.1 Adam解析

Adam (Adaptive Moment Estimation) 是一個(gè)廣泛使用的優(yōu)化算法,設(shè)計(jì)用于深度學(xué)習(xí)模型。它結(jié)合了兩種其他的優(yōu)化算法:Adagrad 和 RMSprop。

以下是 Adam 的特點(diǎn)和工作原理:

  1. 動(dòng)量:與傳統(tǒng)的動(dòng)量方法相似,Adam 使用移動(dòng)平均來獲得梯度的過去值。這幫助算法導(dǎo)航在相關(guān)的梯度下降方向,特別是在解決高度非凸的優(yōu)化問題時(shí)。
  2. 學(xué)習(xí)率自適應(yīng):與 RMSprop 和 Adagrad 一樣,Adam 根據(jù)過去的平方梯度調(diào)整每個(gè)參數(shù)的學(xué)習(xí)率。這有助于算法在學(xué)習(xí)的早期快速前進(jìn),而在接近最小值時(shí)減速。

具體算法:

  1. 初始化參數(shù)。
  2. 計(jì)算梯度
  3. 計(jì)算第一矩估計(jì) mt
  4. 計(jì)算第二矩估計(jì) vt
  5. 對(duì)mt和vt進(jìn)行偏置校正
  6. 更新權(quán)重

優(yōu)點(diǎn):
計(jì)算效率高。需要的內(nèi)存小。適用于大多數(shù)深度學(xué)習(xí)應(yīng)用。適用于非穩(wěn)定的目標(biāo)函數(shù)、大型問題、高噪聲或稀疏梯度。

缺點(diǎn):
Adam 可能需要更多的時(shí)間來收斂,尤其是在深度學(xué)習(xí)訓(xùn)練的后期。
對(duì)某些問題,它可能不如其他的算法(如 SGD 或 RMSprop)穩(wěn)定。

2.2 代碼實(shí)例

class AdamOptimizer:
    def __init__(self, learning_rate=0.001, beta1=0.9, beta2=0.999, epsilon=1e-8):
        self.learning_rate = learning_rate
        self.beta1 = beta1
        self.beta2 = beta2
        self.epsilon = epsilon
        
        # 初始化一階矩估計(jì)和二階矩估計(jì)
        self.m = 0
        self.v = 0
        self.t = 0

    def step(self, gradient):
        self.t += 1  # 增加時(shí)間步

        # 更新偏差修正的一階矩估計(jì)
        self.m = self.beta1 * self.m + (1 - self.beta1) * gradient

        # 更新偏差修正的二階矩估計(jì)
        self.v = self.beta2 * self.v + (1 - self.beta2) * gradient**2

        # 計(jì)算偏差修正的一階矩估計(jì)
        m_corr = self.m / (1 - self.beta1**self.t)

        # 計(jì)算偏差修正的二階矩估計(jì)
        v_corr = self.v / (1 - self.beta2**self.t)

        # 更新參數(shù)
        update = self.learning_rate * m_corr / (v_corr**0.5 + self.epsilon)

        return update

3. NLP任務(wù)

自然語言處理(NLP, Natural Language Processing)是計(jì)算機(jī)科學(xué)、人工智能和語言學(xué)交叉的一個(gè)領(lǐng)域,它使機(jī)器能夠讀懂、解釋、生成和相應(yīng)人類語言。隨著技術(shù)的進(jìn)步,NLP任務(wù)變得越來越先進(jìn),并在許多實(shí)際應(yīng)用中發(fā)揮了作用。

以下是一些主要的NLP任務(wù):

  1. 文本分類:將給定的文本歸類到預(yù)定義的類別中。例如,情感分析(判斷文本是正面的、負(fù)面的還是中立的)。
  2. 命名實(shí)體識(shí)別 (NER):從文本中識(shí)別出如人名、地名、機(jī)構(gòu)名等特定類別的實(shí)體。
  3. 詞性標(biāo)注:為文本中的每個(gè)詞分配一個(gè)詞性標(biāo)簽,如名詞、動(dòng)詞、形容詞等。
  4. 句法分析:構(gòu)建文本的句法結(jié)構(gòu),通常采用樹狀圖來表示。
  5. 語義角色標(biāo)注:確定句子中每個(gè)成分的語義角色,如施事、受事等。
  6. 語言模型:預(yù)測下一個(gè)詞或字符的出現(xiàn)概率。這在許多應(yīng)用中都很有用,如機(jī)器翻譯和語音識(shí)別。
  7. 機(jī)器翻譯:將文本從一種語言翻譯成另一種語言。
  8. 問答系統(tǒng):根據(jù)用戶的問題從文檔中提取或生成答案。
  9. 文本生成:基于給定的輸入生成新的文本。
    10.語音識(shí)別:將音頻轉(zhuǎn)換為文本。

現(xiàn)給定一個(gè)任務(wù)
任務(wù):字符串分類 – 判斷字符串中是否出現(xiàn)了指定字符
例:
指定字符:a
樣本: abcd 正樣本
bcde 負(fù)樣本

4. 神經(jīng)網(wǎng)絡(luò)處理文本

任務(wù)
當(dāng)前輸入:字符串 如:abcd
預(yù)期輸出:概率值 正樣本=1,負(fù)樣本=0,以0.5為分界
X = “abcd” Y = 1
X =“bcde” Y = 0

建模目標(biāo):找到一個(gè)映射f(x),使得f(“abcd”) = 1, f(“bcde”) = 0

4.1 step1 字符數(shù)值化

直觀方式,a -> 1, b -> 2, c -> 3 …. z -> 26 是否合理?
顯然不夠合理,因?yàn)檫@似乎告訴了網(wǎng)絡(luò)一些潛在的關(guān)系,如a+b=c,a+a=b。

每個(gè)字符轉(zhuǎn)化成同維度向量
a - > [0.32618175 0.20962898 0.43550067 0.07120884 0.58215387]
b - > [0.21841921 0.97431001 0.43676452 0.77925024 0.7307891 ]

z -> [0.72847746 0.72803551 0.43888069 0.09266955 0.65148562]

那么“abcd” - > 4 * 5 的矩陣
[[0.32618175 0.20962898 0.43550067 0.07120884 0.58215387]
[0.21841921 0.97431001 0.43676452 0.77925024 0.7307891 ]
[0.95035602 0.45280039 0.06675379 0.72238734 0.02466642]
[0.86751814 0.97157839 0.0127658 0.98910503 0.92606296]]
矩陣形狀 = 文本長度 * 向量長度

4.2 step 2 矩陣轉(zhuǎn)化為向量

求平均
[[0.32618175 0.20962898 0.43550067 0.07120884 0.58215387]
[0.21841921 0.97431001 0.43676452 0.77925024 0.7307891 ]
[0.95035602 0.45280039 0.06675379 0.72238734 0.02466642]
[0.86751814 0.97157839 0.0127658 0.98910503 0.92606296]]
->
[0.59061878 0.65207944 0.2379462 0.64048786 0.56591809]
由4 * 5 矩陣 -> 1* 5 向量 形狀 = 1*向量長度

4.3 step 3 向量到數(shù)值

采取最簡單的線性公式 y = w * x + b
w 維度為1*向量維度 b為實(shí)數(shù)
例:
w = [1, 1], b = -1, x = [1,2]

4.4 step 4 數(shù)值歸一化

sigmoid函數(shù)
x = 3 σ(x) = 0.9526
深度學(xué)習(xí)處理文本(NLP),Natural Language Processing,深度學(xué)習(xí),自然語言處理,人工智能,python
深度學(xué)習(xí)處理文本(NLP),Natural Language Processing,深度學(xué)習(xí),自然語言處理,人工智能,python

4.5 總結(jié)

整體映射
“abcd” ----每個(gè)字符轉(zhuǎn)化成向量----> 4 * 5矩陣
4 * 5矩陣 ----向量求平均----> 1 * 5向量
1 * 5向量 ----w*x + b線性公式 —> 實(shí)數(shù)
實(shí)數(shù) ----sigmoid歸一化函數(shù)—> 0-1之間實(shí)數(shù)

黃色部分需要通過訓(xùn)練優(yōu)化

5. Embedding層

5.1 解析

Embedding層在神經(jīng)網(wǎng)絡(luò)中用于將離散型數(shù)據(jù)(通常是文本數(shù)據(jù)的整數(shù)標(biāo)識(shí))轉(zhuǎn)換為持續(xù)型向量表示,也就是詞嵌入。這一層通常用于自然語言處理(NLP)任務(wù),例如文本分類、情感分析或機(jī)器翻譯等。

在嵌入層中,每個(gè)唯一的標(biāo)識(shí)(比如一個(gè)詞的整數(shù)ID)都會(huì)映射到一個(gè)固定大小的向量。這些向量通過模型的訓(xùn)練進(jìn)行優(yōu)化,以便更好地完成給定任務(wù)。

Embedding矩陣是可訓(xùn)練的參數(shù),一般會(huì)在模型構(gòu)建時(shí)隨機(jī)初始化
也可以使用預(yù)訓(xùn)練的詞向量來做初始化,此時(shí)也可以選擇不訓(xùn)練Embedding層中的參數(shù)

輸入的整數(shù)序列可以有重復(fù),但取值不能超過Embedding矩陣的列數(shù)

核心價(jià)值:將離散值轉(zhuǎn)化為向量
在nlp任務(wù)和各類特征工程中應(yīng)用廣泛

深度學(xué)習(xí)處理文本(NLP),Natural Language Processing,深度學(xué)習(xí),自然語言處理,人工智能,python

搭配詞表文件
對(duì)于中文通常使用字
對(duì)于英文使用token
多個(gè)語種和符號(hào)可以出現(xiàn)在同一份詞表中
目的:“abc" --詞表–> 0,1,2 --Embedding層–> 3*n的矩陣 --model–>

5.2 代碼實(shí)例

#coding:utf8
import torch
import torch.nn as nn

'''
embedding層的處理
'''

num_embeddings = 6  #通常對(duì)于nlp任務(wù),此參數(shù)為字符集字符總數(shù)
embedding_dim = 5   #每個(gè)字符向量化后的向量維度
embedding_layer = nn.Embedding(num_embeddings, embedding_dim)
print("隨機(jī)初始化權(quán)重")
print(embedding_layer.weight)
print("################")

#構(gòu)造字符表
vocab = {
    "a" : 0,
    "b" : 1,
    "c" : 2,
    "d" : 3,
    "e" : 4,
    "f" : 5,
}

def str_to_sequence(string, vocab):
    return [vocab[s] for s in string]

string1 = "abcde"
string2 = "ddccb"
string3 = "fedab"

sequence1 = str_to_sequence(string1, vocab)
sequence2 = str_to_sequence(string2, vocab)
sequence3 = str_to_sequence(string3, vocab)

x = torch.LongTensor([sequence1, sequence2, sequence3])
embedding_out = embedding_layer(x)
print(embedding_out)



字符轉(zhuǎn)換成向量
深度學(xué)習(xí)處理文本(NLP),Natural Language Processing,深度學(xué)習(xí),自然語言處理,人工智能,python

6. 網(wǎng)絡(luò)結(jié)構(gòu) – 全連接層

網(wǎng)絡(luò)結(jié)構(gòu)-全連接層
又稱線性層
計(jì)算公式:y = w * x + b
W和b是參與訓(xùn)練的參數(shù)
W的維度決定了隱含層輸出的維度,一般稱為隱單元個(gè)數(shù)(hidden size)
舉例:
輸入:x (維度1 x 3)
隱含層1:w(維度3 x 5)
隱含層2: w(維度5 x 2)
深度學(xué)習(xí)處理文本(NLP),Natural Language Processing,深度學(xué)習(xí),自然語言處理,人工智能,python

7. 網(wǎng)絡(luò)結(jié)構(gòu) – RNN

7.1 解析

循環(huán)神經(jīng)網(wǎng)絡(luò)(Recurrent Neural Networks, RNN)是一種用于處理序列數(shù)據(jù)的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)。與傳統(tǒng)的前饋神經(jīng)網(wǎng)絡(luò)不同,RNN具有記憶功能,能夠保存前一步或多步的信息。這使得RNN特別適合處理如時(shí)間序列數(shù)據(jù)、文本、語音等依賴于前文信息的任務(wù)。

在RNN中,神經(jīng)元不僅接收新的輸入,還維持一種狀態(tài)(通常用隱藏層表示),該狀態(tài)在網(wǎng)絡(luò)的每一步迭代中都會(huì)更新。簡單地說,RNN每次接收一個(gè)輸入并生成一個(gè)輸出,同時(shí)更新其內(nèi)部狀態(tài)。

RNN的一個(gè)典型應(yīng)用是自然語言處理(NLP),例如文本生成、文本分類和機(jī)器翻譯。然而,由于梯度消失或梯度爆炸問題,基礎(chǔ)的RNN結(jié)構(gòu)在處理長序列時(shí)可能會(huì)遇到困難。為了解決這些問題,更復(fù)雜的RNN變體如長短時(shí)記憶(LSTM)和門控循環(huán)單元(GRU)被開發(fā)出來。

循環(huán)神經(jīng)網(wǎng)絡(luò)(recurrent neural network)
主要思想:將整個(gè)序列劃分成多個(gè)時(shí)間步,將每一個(gè)時(shí)間步的信息依次輸入模型,同時(shí)將模型輸出的結(jié)果傳給下一個(gè)時(shí)間步
深度學(xué)習(xí)處理文本(NLP),Natural Language Processing,深度學(xué)習(xí),自然語言處理,人工智能,python

公式:
深度學(xué)習(xí)處理文本(NLP),Natural Language Processing,深度學(xué)習(xí),自然語言處理,人工智能,python

深度學(xué)習(xí)處理文本(NLP),Natural Language Processing,深度學(xué)習(xí),自然語言處理,人工智能,python

7.2 代碼實(shí)例

#coding:utf8

import torch
import torch.nn as nn
import numpy as np


"""
手動(dòng)實(shí)現(xiàn)簡單的神經(jīng)網(wǎng)絡(luò)
使用pytorch實(shí)現(xiàn)RNN
手動(dòng)實(shí)現(xiàn)RNN
對(duì)比
"""

class TorchRNN(nn.Module):
    def __init__(self, input_size, hidden_size):
        super(TorchRNN, self).__init__()
        self.layer = nn.RNN(input_size, hidden_size, bias=False, batch_first=True)

    def forward(self, x):
        return self.layer(x)

#自定義RNN模型
class DiyModel:
    def __init__(self, w_ih, w_hh, hidden_size):
        self.w_ih = w_ih
        self.w_hh = w_hh
        self.hidden_size = hidden_size

    def forward(self, x):
        ht = np.zeros((self.hidden_size))
        output = []
        for xt in x:
            ux = np.dot(self.w_ih, xt)
            wh = np.dot(self.w_hh, ht)
            ht_next = np.tanh(ux + wh)
            output.append(ht_next)
            ht = ht_next
        return np.array(output), ht


x = np.array([[1, 2, 3],
              [3, 4, 5],
              [5, 6, 7]])  #網(wǎng)絡(luò)輸入

#torch實(shí)驗(yàn)
hidden_size = 4
torch_model = TorchRNN(3, hidden_size)
# print(torch_model.state_dict())
w_ih = torch_model.state_dict()["layer.weight_ih_l0"]
w_hh = torch_model.state_dict()["layer.weight_hh_l0"]
print(w_ih, w_ih.shape)
print(w_hh, w_hh.shape)
#
torch_x = torch.FloatTensor([x])
output, h = torch_model.forward(torch_x)
print(h)
print(output.detach().numpy(), "torch模型預(yù)測結(jié)果")
print(h.detach().numpy(), "torch模型預(yù)測隱含層結(jié)果")
print("---------------")
diy_model = DiyModel(w_ih, w_hh, hidden_size)
output, h = diy_model.forward(x)
print(output, "diy模型預(yù)測結(jié)果")
print(h, "diy模型預(yù)測隱含層結(jié)果")

8. 網(wǎng)絡(luò)結(jié)構(gòu) – CNN

8.1 解析

以卷積操作為基礎(chǔ)的網(wǎng)絡(luò)結(jié)構(gòu),每個(gè)卷積核可以看成一個(gè)特征提取器
深度學(xué)習(xí)處理文本(NLP),Natural Language Processing,深度學(xué)習(xí),自然語言處理,人工智能,python

8.2 代碼實(shí)例

#coding:utf8

import torch
import torch.nn as nn
import numpy as np


"""
手動(dòng)實(shí)現(xiàn)簡單的神經(jīng)網(wǎng)絡(luò)
使用pytorch實(shí)現(xiàn)CNN
手動(dòng)實(shí)現(xiàn)CNN
對(duì)比
"""
#一個(gè)二維卷積
class TorchCNN(nn.Module):
    def __init__(self, in_channel, out_channel, kernel):
        super(TorchCNN, self).__init__()
        self.layer = nn.Conv2d(in_channel, out_channel, kernel, bias=False)

    def forward(self, x):
        return self.layer(x)

#自定義CNN模型
class DiyModel:
    def __init__(self, input_height, input_width, weights, kernel_size):
        self.height = input_height
        self.width = input_width
        self.weights = weights
        self.kernel_size = kernel_size

    def forward(self, x):
        output = []
        for kernel_weight in self.weights:
            kernel_weight = kernel_weight.squeeze().numpy() #shape : 2x2
            kernel_output = np.zeros((self.height - kernel_size + 1, self.width - kernel_size + 1))
            for i in range(self.height - kernel_size + 1):
                for j in range(self.width - kernel_size + 1):
                    window = x[i:i+kernel_size, j:j+kernel_size]
                    kernel_output[i, j] = np.sum(kernel_weight * window) # np.dot(a, b) != a * b
            output.append(kernel_output)
        return np.array(output)


x = np.array([[0.1, 0.2, 0.3, 0.4],
              [-3, -4, -5, -6],
              [5.1, 6.2, 7.3, 8.4],
              [-0.7, -0.8, -0.9, -1]])  #網(wǎng)絡(luò)輸入

#torch實(shí)驗(yàn)
in_channel = 1
out_channel = 3
kernel_size = 2
torch_model = TorchCNN(in_channel, out_channel, kernel_size)
print(torch_model.state_dict())
torch_w = torch_model.state_dict()["layer.weight"]
# print(torch_w.numpy().shape)
torch_x = torch.FloatTensor([[x]])
output = torch_model.forward(torch_x)
output = output.detach().numpy()
print(output, output.shape, "torch模型預(yù)測結(jié)果\n")
print("---------------")
diy_model = DiyModel(x.shape[0], x.shape[1], torch_w, kernel_size)
output = diy_model.forward(x)
print(output, "diy模型預(yù)測結(jié)果")

#######################

#一維卷積層,在nlp中更加常用
kernel_size = 3
input_dim = 5
hidden_size = 4
torch_cnn1d = nn.Conv1d(input_dim, hidden_size, kernel_size)
# for key, weight in torch_cnn1d.state_dict().items():
#     print(key, weight.shape)

def numpy_cnn1d(x, state_dict):
    weight = state_dict["weight"].numpy()
    bias = state_dict["bias"].numpy()
    sequence_output = []
    for i in range(0, x.shape[1] - kernel_size + 1):
        window = x[:, i:i+kernel_size]
        kernel_outputs = []
        for kernel in weight:
            kernel_outputs.append(np.sum(kernel * window))
        sequence_output.append(np.array(kernel_outputs) + bias)
    return np.array(sequence_output).T

# x = torch.from_numpy(np.random.random((length, input_dim)))
# x = x.transpose(1, 0)
# print(torch_cnn1d(torch.Tensor([x])))
# print(numpy_cnn1d(x, torch_cnn1d.state_dict()))

9. 網(wǎng)絡(luò)結(jié)構(gòu) – LSTM

9.1 解析

將RNN的隱單元復(fù)雜化一定程度規(guī)避了梯度消失和信息遺忘的問題
深度學(xué)習(xí)處理文本(NLP),Natural Language Processing,深度學(xué)習(xí),自然語言處理,人工智能,python

長短時(shí)記憶(Long Short-Term Memory, LSTM)網(wǎng)絡(luò)是一種特殊類型的循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN),旨在解決基礎(chǔ)RNN在處理長序列時(shí)可能出現(xiàn)的梯度消失或梯度爆炸問題。LSTM由Sepp Hochreiter和Jürgen Schmidhuber于1997年首次提出,并已被廣泛用于各種涉及序列數(shù)據(jù)的任務(wù),如自然語言處理、語音識(shí)別和時(shí)間序列預(yù)測。

LSTM的核心思想是引入了“記憶單元”(cell)和三個(gè)“門”(gate):輸入門、輸出門和遺忘門。這些門和記憶單元共同作用,以決定如何更新網(wǎng)絡(luò)的狀態(tài)。

  1. 輸入門:決定新輸入的哪些部分需要更新記憶狀態(tài)。
  2. 遺忘門:決定哪些舊信息需要被遺忘或保留。
  3. 輸出門:基于當(dāng)前的輸入和記憶單元,決定輸出什么信息。

這三個(gè)門的結(jié)構(gòu)使LSTM能夠在長序列中更有效地捕獲依賴關(guān)系。

9.2 代碼實(shí)例


import torch
import torch.nn as nn
import numpy as np

'''
用矩陣運(yùn)算的方式復(fù)現(xiàn)一些基礎(chǔ)的模型結(jié)構(gòu)
清楚模型的計(jì)算細(xì)節(jié),有助于加深對(duì)于模型的理解,以及模型轉(zhuǎn)換等工作
'''

#構(gòu)造一個(gè)輸入
length = 6
input_dim = 12
hidden_size = 7
x = np.random.random((length, input_dim))
# print(x)

#使用pytorch的lstm層
torch_lstm = nn.LSTM(input_dim, hidden_size, batch_first=True)
for key, weight in torch_lstm.state_dict().items():
    print(key, weight.shape)

def sigmoid(x):
    return 1/(1 + np.exp(-x))

#將pytorch的lstm網(wǎng)絡(luò)權(quán)重拿出來,用numpy通過矩陣運(yùn)算實(shí)現(xiàn)lstm的計(jì)算
def numpy_lstm(x, state_dict):
    weight_ih = state_dict["weight_ih_l0"].numpy()
    weight_hh = state_dict["weight_hh_l0"].numpy()
    bias_ih = state_dict["bias_ih_l0"].numpy()
    bias_hh = state_dict["bias_hh_l0"].numpy()
    #pytorch將四個(gè)門的權(quán)重拼接存儲(chǔ),我們將它拆開
    w_i_x, w_f_x, w_c_x, w_o_x = weight_ih[0:hidden_size, :], \
                                 weight_ih[hidden_size:hidden_size*2, :],\
                                 weight_ih[hidden_size*2:hidden_size*3, :],\
                                 weight_ih[hidden_size*3:hidden_size*4, :]
    w_i_h, w_f_h, w_c_h, w_o_h = weight_hh[0:hidden_size, :], \
                                 weight_hh[hidden_size:hidden_size * 2, :], \
                                 weight_hh[hidden_size * 2:hidden_size * 3, :], \
                                 weight_hh[hidden_size * 3:hidden_size * 4, :]
    b_i_x, b_f_x, b_c_x, b_o_x = bias_ih[0:hidden_size], \
                                 bias_ih[hidden_size:hidden_size * 2], \
                                 bias_ih[hidden_size * 2:hidden_size * 3], \
                                 bias_ih[hidden_size * 3:hidden_size * 4]
    b_i_h, b_f_h, b_c_h, b_o_h = bias_hh[0:hidden_size], \
                                 bias_hh[hidden_size:hidden_size * 2], \
                                 bias_hh[hidden_size * 2:hidden_size * 3], \
                                 bias_hh[hidden_size * 3:hidden_size * 4]
    w_i = np.concatenate([w_i_h, w_i_x], axis=1)
    w_f = np.concatenate([w_f_h, w_f_x], axis=1)
    w_c = np.concatenate([w_c_h, w_c_x], axis=1)
    w_o = np.concatenate([w_o_h, w_o_x], axis=1)
    b_f = b_f_h + b_f_x
    b_i = b_i_h + b_i_x
    b_c = b_c_h + b_c_x
    b_o = b_o_h + b_o_x
    c_t = np.zeros((1, hidden_size))
    h_t = np.zeros((1, hidden_size))
    sequence_output = []
    for x_t in x:
        x_t = x_t[np.newaxis, :]
        hx = np.concatenate([h_t, x_t], axis=1)
        # f_t = sigmoid(np.dot(x_t, w_f_x.T) + b_f_x + np.dot(h_t, w_f_h.T) + b_f_h)
        f_t = sigmoid(np.dot(hx, w_f.T) + b_f)
        # i_t = sigmoid(np.dot(x_t, w_i_x.T) + b_i_x + np.dot(h_t, w_i_h.T) + b_i_h)
        i_t = sigmoid(np.dot(hx, w_i.T) + b_i)
        # g = np.tanh(np.dot(x_t, w_c_x.T) + b_c_x + np.dot(h_t, w_c_h.T) + b_c_h)
        g = np.tanh(np.dot(hx, w_c.T) + b_c)
        c_t = f_t * c_t + i_t * g
        # o_t = sigmoid(np.dot(x_t, w_o_x.T) + b_o_x + np.dot(h_t, w_o_h.T) + b_o_h)
        o_t = sigmoid(np.dot(hx, w_o.T) + b_o)
        h_t = o_t * np.tanh(c_t)
        sequence_output.append(h_t)
    return np.array(sequence_output), (h_t, c_t)


# torch_sequence_output, (torch_h, torch_c) = torch_lstm(torch.Tensor([x]))
# numpy_sequence_output, (numpy_h, numpy_c) = numpy_lstm(x, torch_lstm.state_dict())
#
# print(torch_sequence_output)
# print(numpy_sequence_output)
# print("--------")
# print(torch_h)
# print(numpy_h)
# print("--------")
# print(torch_c)
# print(numpy_c)

#############################################################

#使用pytorch的GRU層
torch_gru = nn.GRU(input_dim, hidden_size, batch_first=True)
# for key, weight in torch_gru.state_dict().items():
#     print(key, weight.shape)


#將pytorch的GRU網(wǎng)絡(luò)權(quán)重拿出來,用numpy通過矩陣運(yùn)算實(shí)現(xiàn)GRU的計(jì)算
def numpy_gru(x, state_dict):
    weight_ih = state_dict["weight_ih_l0"].numpy()
    weight_hh = state_dict["weight_hh_l0"].numpy()
    bias_ih = state_dict["bias_ih_l0"].numpy()
    bias_hh = state_dict["bias_hh_l0"].numpy()
    #pytorch將3個(gè)門的權(quán)重拼接存儲(chǔ),我們將它拆開
    w_r_x, w_z_x, w_x = weight_ih[0:hidden_size, :], \
                        weight_ih[hidden_size:hidden_size * 2, :],\
                        weight_ih[hidden_size * 2:hidden_size * 3, :]
    w_r_h, w_z_h, w_h = weight_hh[0:hidden_size, :], \
                        weight_hh[hidden_size:hidden_size * 2, :], \
                        weight_hh[hidden_size * 2:hidden_size * 3, :]
    b_r_x, b_z_x, b_x = bias_ih[0:hidden_size], \
                        bias_ih[hidden_size:hidden_size * 2], \
                        bias_ih[hidden_size * 2:hidden_size * 3]
    b_r_h, b_z_h, b_h = bias_hh[0:hidden_size], \
                        bias_hh[hidden_size:hidden_size * 2], \
                        bias_hh[hidden_size * 2:hidden_size * 3]
    w_z = np.concatenate([w_z_h, w_z_x], axis=1)
    w_r = np.concatenate([w_r_h, w_r_x], axis=1)
    b_z = b_z_h + b_z_x
    b_r = b_r_h + b_r_x
    h_t = np.zeros((1, hidden_size))
    sequence_output = []
    for x_t in x:
        x_t = x_t[np.newaxis, :]
        hx = np.concatenate([h_t, x_t], axis=1)
        z_t = sigmoid(np.dot(hx, w_z.T) + b_z)
        r_t = sigmoid(np.dot(hx, w_r.T) + b_r)
        h = np.tanh(r_t * (np.dot(h_t, w_h.T) + b_h) + np.dot(x_t, w_x.T) + b_x)
        h_t = (1 - z_t) * h + z_t * h_t
        sequence_output.append(h_t)
    return np.array(sequence_output), h_t

# torch_sequence_output, torch_h = torch_gru(torch.Tensor([x]))
# numpy_sequence_output, numpy_h = numpy_gru(x, torch_gru.state_dict())
#
# print(torch_sequence_output)
# print(numpy_sequence_output)
# print("--------")
# print(torch_h)
# print(numpy_h)


10. 網(wǎng)絡(luò)結(jié)構(gòu) – GRU

10.1 解析

LSTM的一種簡化變體
在不同任務(wù)上與LSTM效果各有優(yōu)劣
深度學(xué)習(xí)處理文本(NLP),Natural Language Processing,深度學(xué)習(xí),自然語言處理,人工智能,python

門控循環(huán)單元(Gated Recurrent Unit, GRU)是一種循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)的變體,由Kyunghyun Cho等人在2014年提出。GRU旨在解決標(biāo)準(zhǔn)RNN結(jié)構(gòu)在處理長序列時(shí)面臨的梯度消失問題,與長短時(shí)記憶(LSTM)網(wǎng)絡(luò)有相似的目的。

與LSTM相比,GRU有更簡單的結(jié)構(gòu),主要由兩個(gè)門組成:

  1. 更新門(Update Gate):決定哪些信息從前一狀態(tài)傳遞到當(dāng)前狀態(tài)。
  2. 重置門(Reset Gate):決定哪些過去的信息會(huì)與當(dāng)前的輸入一起用于更新當(dāng)前狀態(tài)。

因?yàn)镚RU有更少的門和參數(shù),所以它們通常更快地訓(xùn)練,尤其是在不需要捕獲極長依賴關(guān)系的數(shù)據(jù)集上。

10.2 代碼實(shí)例

import torch
import torch.nn as nn

# 定義模型結(jié)構(gòu)
class GRUModel(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim):
        super(GRUModel, self).__init__()
        self.gru = nn.GRU(input_dim, hidden_dim, batch_first=True)
        self.fc = nn.Linear(hidden_dim, output_dim)
        
    def forward(self, x):
        out, _ = self.gru(x)
        out = self.fc(out[:, -1, :])
        return out

# 參數(shù)設(shè)置
input_dim = 64  # 輸入的特征維度
hidden_dim = 50  # GRU層的隱藏狀態(tài)維度
output_dim = 1   # 輸出層的維度(用于二分類)

# 初始化模型、損失函數(shù)和優(yōu)化器
model = GRUModel(input_dim, hidden_dim, output_dim)
criterion = nn.BCEWithLogitsLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

# 假設(shè)我們有一個(gè)形狀為(batch_size, seq_len, input_dim)的輸入數(shù)據(jù)和相應(yīng)的標(biāo)簽
# 這里我們僅用隨機(jī)數(shù)據(jù)作為例子
batch_size = 32
seq_len = 10
x = torch.randn(batch_size, seq_len, input_dim)
y = torch.randint(0, 2, (batch_size, output_dim), dtype=torch.float32)

# 前向傳播
outputs = model(x)

# 計(jì)算損失
loss = criterion(outputs, y)

# 反向傳播和優(yōu)化
optimizer.zero_grad()
loss.backward()
optimizer.step()

11. 網(wǎng)絡(luò)結(jié)構(gòu) – TextCNN

11.1 解析

利用一維卷積對(duì)文本進(jìn)行編碼編碼后的文本矩陣通過pooling轉(zhuǎn)化為向量,用于分類
深度學(xué)習(xí)處理文本(NLP),Natural Language Processing,深度學(xué)習(xí),自然語言處理,人工智能,python

11.2 代碼實(shí)例

import torch
import torch.nn as nn
import torch.nn.functional as F

# 定義TextCNN模型
class TextCNN(nn.Module):
    def __init__(self, vocab_size, embed_dim, num_classes, kernel_sizes=[3, 4, 5], num_filters=100):
        super(TextCNN, self).__init__()
        
        # 嵌入層
        self.embedding = nn.Embedding(vocab_size, embed_dim)
        
        # 卷積層
        self.convs = nn.ModuleList([
            nn.Conv1d(in_channels=embed_dim, out_channels=num_filters, kernel_size=k)
            for k in kernel_sizes
        ])
        
        # 全連接層
        self.fc = nn.Linear(len(kernel_sizes) * num_filters, num_classes)

    def forward(self, x):
        # 輸入x形狀:[批量大小, 序列長度]
        
        # 嵌入
        x = self.embedding(x)  # 輸出形狀:[批量大小, 序列長度, 嵌入維度]
        
        # Conv1D期望輸入形狀:[批量大小, 嵌入維度, 序列長度]
        x = x.permute(0, 2, 1)
        
        # 卷積
        x = [F.relu(conv(x)) for conv in self.convs]
        
        # 池化
        x = [F.max_pool1d(c, c.size(-1)).squeeze(-1) for c in x]
        
        # 拼接
        x = torch.cat(x, 1)
        
        # 全連接層
        x = self.fc(x)
        
        return x

# 超參數(shù)
vocab_size = 5000  # 詞匯表大小
embed_dim = 300  # 嵌入維度
num_classes = 2  # 類別數(shù)
kernel_sizes = [3, 4, 5]  # 卷積核大小
num_filters = 100  # 卷積核數(shù)量

# 初始化模型
model = TextCNN(vocab_size, embed_dim, num_classes, kernel_sizes, num_filters)

# 示例輸入(在實(shí)際應(yīng)用中,這應(yīng)是預(yù)處理并編碼為整數(shù)的文本序列)
# 輸入形狀:[批量大小, 序列長度]
input_batch = torch.randint(0, vocab_size, (32, 50))

# 前向傳播
output = model(input_batch)

12. 池化層

12.1 解析

  • 降低了后續(xù)網(wǎng)絡(luò)層的輸入維度,縮減模型大小,提高計(jì)算速度
  • 提高了Feature Map 的魯棒性,防止過擬合
    深度學(xué)習(xí)處理文本(NLP),Natural Language Processing,深度學(xué)習(xí),自然語言處理,人工智能,python

12.2 代碼實(shí)例

#coding:utf8
import torch
import torch.nn as nn

'''
pooling層的處理
'''

#pooling操作默認(rèn)對(duì)于輸入張量的最后一維進(jìn)行
#入?yún)?,代表把五維池化為一維
layer = nn.AvgPool1d(5)
#隨機(jī)生成一個(gè)維度為3x4x5的張量
#可以想象成3條,文本長度為4,向量長度為5的樣本
x = torch.rand([3, 4, 5])
print(x)
print(x.shape)
#經(jīng)過pooling層
y = layer(x)
print(y)
print(y.shape)
#squeeze方法去掉值為1的維度
y = y.squeeze()
print(y)
print(y.shape)

13. Normalization

深度學(xué)習(xí)處理文本(NLP),Natural Language Processing,深度學(xué)習(xí),自然語言處理,人工智能,python

深度學(xué)習(xí)處理文本(NLP),Natural Language Processing,深度學(xué)習(xí),自然語言處理,人工智能,python

標(biāo)準(zhǔn)化是機(jī)器學(xué)習(xí)和統(tǒng)計(jì)中用于縮放特征的技術(shù),使它們具有可比性和可解釋性。常見的標(biāo)準(zhǔn)化方法有最小-最大標(biāo)準(zhǔn)化(Min-Max Normalization)和Z分?jǐn)?shù)標(biāo)準(zhǔn)化(Z-score Normalization,也叫標(biāo)準(zhǔn)化)。

標(biāo)準(zhǔn)化的好處

  1. 加速訓(xùn)練:標(biāo)準(zhǔn)化數(shù)據(jù)在訓(xùn)練過程中更快地收斂。
  2. 特征可比:使不同的特征具有可比性。
  3. 有助于某些算法:例如k-NN和SVM等依賴于數(shù)據(jù)點(diǎn)之間的距離,標(biāo)準(zhǔn)化在這些情況下是有幫助的。

14. Dropout層

14.1 解析

  • 作用:減少過擬合
  • 按照指定概率,隨機(jī)丟棄一些神經(jīng)元(將其化為零)
  • 其余元素乘以 1 / (1 – p)進(jìn)行放大

深度學(xué)習(xí)處理文本(NLP),Natural Language Processing,深度學(xué)習(xí),自然語言處理,人工智能,python文章來源地址http://www.zghlxwxcb.cn/news/detail-669947.html

  • 如何理解其作用
  • 強(qiáng)迫一個(gè)神經(jīng)單元,和隨機(jī)挑選出來的其他神經(jīng)單元共同工作,消除減弱了神經(jīng)元節(jié)點(diǎn)間的聯(lián)合適應(yīng)性,增強(qiáng)了泛化能力
  • 可以看做是一種模型平均,由于每次隨機(jī)忽略的隱層節(jié)點(diǎn)都不同,這樣就使每次訓(xùn)練的網(wǎng)絡(luò)都是不一樣的,每次訓(xùn)練都可以單做一個(gè)“新”的模型
  • 啟示:計(jì)算方式并不是越復(fù)雜就越好

14.2 代碼實(shí)例

#coding:utf8

import torch
import torch.nn as nn
import numpy as np


"""
基于pytorch的網(wǎng)絡(luò)編寫
測試dropout層
"""

import torch

x = torch.Tensor([1,2,3,4,5,6,7,8,9])
dp_layer = torch.nn.Dropout(0.5)
dp_x = dp_layer(x)
print(dp_x)


15. NLPDemo

#coding:utf8

import torch
import torch.nn as nn
import numpy as np
import random
import json
import matplotlib.pyplot as plt

"""

基于pytorch的網(wǎng)絡(luò)編寫
實(shí)現(xiàn)一個(gè)網(wǎng)絡(luò)完成一個(gè)簡單nlp任務(wù)
判斷文本中是否有某些特定字符出現(xiàn)

"""

class TorchModel(nn.Module):
    def __init__(self, vector_dim, sentence_length, vocab):
        super(TorchModel, self).__init__()
        self.embedding = nn.Embedding(len(vocab), vector_dim)  #embedding層
        self.pool = nn.AvgPool1d(sentence_length)   #池化層
        self.classify = nn.Linear(vector_dim, 1)     #線性層
        self.activation = torch.sigmoid     #sigmoid歸一化函數(shù)
        self.loss = nn.functional.mse_loss  #loss函數(shù)采用均方差損失

    #當(dāng)輸入真實(shí)標(biāo)簽,返回loss值;無真實(shí)標(biāo)簽,返回預(yù)測值
    def forward(self, x, y=None):
        x = self.embedding(x)                      #(batch_size, sen_len) -> (batch_size, sen_len, vector_dim)
        x = x.transpose(1, 2)                      # (batch_size, sen_len, vector_dim) -> (batch_size, vector_dim, sen_len)
        x = self.pool(x)                           #(batch_size, vector_dim, sen_len)->(batch_size, vector_dim, 1)
        x = x.squeeze()                            #(batch_size, vector_dim, 1) -> (batch_size, vector_dim)
        x = self.classify(x)                       #(batch_size, vector_dim) -> (batch_size, 1)
        y_pred = self.activation(x)                #(batch_size, 1) -> (batch_size, 1)
        if y is not None:
            return self.loss(y_pred, y)   #預(yù)測值和真實(shí)值計(jì)算損失
        else:
            return y_pred                 #輸出預(yù)測結(jié)果

#字符集隨便挑了一些字,實(shí)際上還可以擴(kuò)充
#為每個(gè)字生成一個(gè)標(biāo)號(hào)
#{"a":1, "b":2, "c":3...}
#abc -> [1,2,3]
def build_vocab():
    chars = "abcdefghijklmnopqrstuvwxyz"  #字符集
    vocab = {}
    for index, char in enumerate(chars):
        vocab[char] = index   #每個(gè)字對(duì)應(yīng)一個(gè)序號(hào)
    vocab['unk'] = len(vocab)
    return vocab

#隨機(jī)生成一個(gè)樣本
#從所有字中選取sentence_length個(gè)字
#反之為負(fù)樣本
def build_sample(vocab, sentence_length):
    #隨機(jī)從字表選取sentence_length個(gè)字,可能重復(fù)
    x = [random.choice(list(vocab.keys())) for _ in range(sentence_length)]
    #指定哪些字出現(xiàn)時(shí)為正樣本
    if set("abc") & set(x):
        y = 1
    #指定字都未出現(xiàn),則為負(fù)樣本
    else:
        y = 0
    x = [vocab.get(word, vocab['unk']) for word in x]   #將字轉(zhuǎn)換成序號(hào),為了做embedding
    return x, y

#建立數(shù)據(jù)集
#輸入需要的樣本數(shù)量。需要多少生成多少
def build_dataset(sample_length, vocab, sentence_length):
    dataset_x = []
    dataset_y = []
    for i in range(sample_length):
        x, y = build_sample(vocab, sentence_length)
        dataset_x.append(x)
        dataset_y.append([y])
    return torch.LongTensor(dataset_x), torch.FloatTensor(dataset_y)

#建立模型
def build_model(vocab, char_dim, sentence_length):
    model = TorchModel(char_dim, sentence_length, vocab)
    return model

#測試代碼
#用來測試每輪模型的準(zhǔn)確率
def evaluate(model, vocab, sample_length):
    model.eval()
    x, y = build_dataset(200, vocab, sample_length)   #建立200個(gè)用于測試的樣本
    print("本次預(yù)測集中共有%d個(gè)正樣本,%d個(gè)負(fù)樣本"%(sum(y), 200 - sum(y)))
    correct, wrong = 0, 0
    with torch.no_grad():
        y_pred = model(x)      #模型預(yù)測
        for y_p, y_t in zip(y_pred, y):  #與真實(shí)標(biāo)簽進(jìn)行對(duì)比
            if float(y_p) < 0.5 and int(y_t) == 0:
                correct += 1   #負(fù)樣本判斷正確
            elif float(y_p) >= 0.5 and int(y_t) == 1:
                correct += 1   #正樣本判斷正確
            else:
                wrong += 1
    print("正確預(yù)測個(gè)數(shù):%d, 正確率:%f"%(correct, correct/(correct+wrong)))
    return correct/(correct+wrong)


def main():
    #配置參數(shù)
    epoch_num = 20        #訓(xùn)練輪數(shù)
    batch_size = 20       #每次訓(xùn)練樣本個(gè)數(shù)
    train_sample = 500    #每輪訓(xùn)練總共訓(xùn)練的樣本總數(shù)
    char_dim = 20         #每個(gè)字的維度
    sentence_length = 6   #樣本文本長度
    learning_rate = 0.005 #學(xué)習(xí)率
    # 建立字表
    vocab = build_vocab()
    # 建立模型
    model = build_model(vocab, char_dim, sentence_length)
    # 選擇優(yōu)化器
    optim = torch.optim.Adam(model.parameters(), lr=learning_rate)
    log = []
    # 訓(xùn)練過程
    for epoch in range(epoch_num):
        model.train()
        watch_loss = []
        for batch in range(int(train_sample / batch_size)):
            x, y = build_dataset(batch_size, vocab, sentence_length) #構(gòu)造一組訓(xùn)練樣本
            optim.zero_grad()    #梯度歸零
            loss = model(x, y)   #計(jì)算loss
            loss.backward()      #計(jì)算梯度
            optim.step()         #更新權(quán)重
            watch_loss.append(loss.item())
        print("=========\n第%d輪平均loss:%f" % (epoch + 1, np.mean(watch_loss)))
        acc = evaluate(model, vocab, sentence_length)   #測試本輪模型結(jié)果
        log.append([acc, np.mean(watch_loss)])
    #畫圖
    plt.plot(range(len(log)), [l[0] for l in log], label="acc")  #畫acc曲線
    plt.plot(range(len(log)), [l[1] for l in log], label="loss")  #畫loss曲線
    plt.legend()
    plt.show()
    #保存模型
    torch.save(model.state_dict(), "model.pth")
    # 保存詞表
    writer = open("vocab.json", "w", encoding="utf8")
    writer.write(json.dumps(vocab, ensure_ascii=False, indent=2))
    writer.close()
    return

#使用訓(xùn)練好的模型做預(yù)測
def predict(model_path, vocab_path, input_strings):
    char_dim = 20  # 每個(gè)字的維度
    sentence_length = 6  # 樣本文本長度
    vocab = json.load(open(vocab_path, "r", encoding="utf8")) #加載字符表
    model = build_model(vocab, char_dim, sentence_length)     #建立模型
    model.load_state_dict(torch.load(model_path))             #加載訓(xùn)練好的權(quán)重
    x = []
    for input_string in input_strings:
        x.append([vocab[char] for char in input_string])  #將輸入序列化
    model.eval()   #測試模式
    with torch.no_grad():  #不計(jì)算梯度
        result = model.forward(torch.LongTensor(x))  #模型預(yù)測
    for i, input_string in enumerate(input_strings):
        print("輸入:%s, 預(yù)測類別:%d, 概率值:%f" % (input_string, round(float(result[i])), result[i])) #打印結(jié)果



if __name__ == "__main__":
    main()
    test_strings = ["favfee", "wbsdfg", "rqwdeg", "nakwww"]
    predict("model.pth", "vocab.json", test_strings)

到了這里,關(guān)于深度學(xué)習(xí)處理文本(NLP)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(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)文章

  • NLP/Natural Language Processing

    自然語言處理( Natural Language Processing, NLP)是計(jì)算機(jī)科學(xué)領(lǐng)域與人工智能領(lǐng)域中的一個(gè)重要方向,也就是人們常說的「自然語言處理」,就是研究如何讓計(jì)算機(jī)讀懂人類語言,即將人的自然語言轉(zhuǎn)換為計(jì)算機(jī)可以閱讀的指令。 它研究能實(shí)現(xiàn)人與計(jì)算機(jī)之間用自然語言進(jìn)行有效通

    2024年02月03日
    瀏覽(35)
  • 【人工智能】NLP自然語言處理領(lǐng)域發(fā)展史 | The History of Development in Natural Language Processing (NLP) Field

    【人工智能】NLP自然語言處理領(lǐng)域發(fā)展史 | The History of Development in Natural Language Processing (NLP) Field

    自然語言處理(Natural Language Processing,NLP)是人工智能(AI)領(lǐng)域的重要分支,旨在讓計(jì)算機(jī)能夠理解、處理和生成自然語言,如英語、漢語等。本文將介紹NLP領(lǐng)域的發(fā)展歷史和里程碑事件。

    2024年02月07日
    瀏覽(32)
  • Essential Steps in Natural Language Processing (NLP)

    Essential Steps in Natural Language Processing (NLP)

    ??????歡迎來到我的博客,你將找到有關(guān)如何使用技術(shù)解決問題的文章,也會(huì)找到某個(gè)技術(shù)的學(xué)習(xí)路線。無論你是何種職業(yè),我都希望我的博客對(duì)你有所幫助。最后不要忘記訂閱我的博客以獲取最新文章,也歡迎在文章下方留下你的評(píng)論和反饋。我期待著與你分享知識(shí)、互

    2024年02月08日
    瀏覽(37)
  • Summary of What Is Natural Language Processing (NLP)?

    作者:禪與計(jì)算機(jī)程序設(shè)計(jì)藝術(shù) Natural language processing (NLP) is a subfield of artificial intelligence that involves the use of computational techniques to enable computers to understand and manipulate human languages as they are spoken or written. The field has become increasingly important due to advances in speech recognition technology, na

    2024年02月07日
    瀏覽(26)
  • Natural Language Processing (NLP) for Beginners: A Guid

    作者:禪與計(jì)算機(jī)程序設(shè)計(jì)藝術(shù) 自然語言處理(Natural Language Processing,NLP)作為當(dāng)今最熱門的AI領(lǐng)域之一,已經(jīng)吸引了眾多青年學(xué)者、工程師、科學(xué)家的關(guān)注。但是,對(duì)于剛接觸NLP的人來說,很多基礎(chǔ)知識(shí)都很難掌握,并且掌握起來也并不簡單。特別是當(dāng)遇到一些涉及到實(shí)際

    2024年02月08日
    瀏覽(67)
  • 深度學(xué)習(xí)的Natural Language Processing:從Word2Vec到BERT

    自然語言處理(Natural Language Processing,NLP)是人工智能(Artificial Intelligence,AI)領(lǐng)域的一個(gè)重要分支,其目標(biāo)是讓計(jì)算機(jī)理解、生成和翻譯人類語言。隨著大數(shù)據(jù)、云計(jì)算和深度學(xué)習(xí)等技術(shù)的發(fā)展,深度學(xué)習(xí)的NLP(Deep Learning for NLP)在處理自然語言文本和語音的能力得到了顯

    2024年02月03日
    瀏覽(42)
  • 數(shù)據(jù)分析 How Natural Language Processing (NLP) Tools Can Im

    作者:禪與計(jì)算機(jī)程序設(shè)計(jì)藝術(shù) 自然語言處理(Natural Language Processing,NLP)是計(jì)算機(jī)科學(xué)領(lǐng)域的一個(gè)重要方向,它主要研究如何從非結(jié)構(gòu)化文本中提取有效的信息,并對(duì)其進(jìn)行理解、分析和生成新穎的表達(dá)形式。在軟件開發(fā)領(lǐng)域,NLP可以幫助開發(fā)人員提升效率,改善產(chǎn)品質(zhì)量

    2024年02月03日
    瀏覽(19)
  • NLP的知識(shí)體系和技術(shù)原理 A Gentle Introduction to Natural Language Processing

    作者:禪與計(jì)算機(jī)程序設(shè)計(jì)藝術(shù) 自然語言處理(NLP)是人工智能領(lǐng)域的一個(gè)重要分支,它涉及到計(jì)算機(jī)如何理解、分析和生成人類的語言。在過去的十年里,NLP已成為研究熱點(diǎn),并取得了很大的成果。與此同時(shí),隨著技術(shù)的進(jìn)步和應(yīng)用場景的豐富,NLP也越來越受到了關(guān)注。近

    2024年02月07日
    瀏覽(15)
  • 自然語言處理技術(shù)(Natural Language Processing)知識(shí)點(diǎn)

    自然語言處理技術(shù)(Natural Language Processing)知識(shí)點(diǎn)

    對(duì)自然語言處理相關(guān)的知識(shí)點(diǎn)進(jìn)行總結(jié)。 自然語言處理(NLP)是一種人工智能技術(shù),用于處理和理解自然語言文本。NLP 的目標(biāo)是使計(jì)算機(jī)能夠像人類一樣理解、處理或生成自然語言,以便能夠完成各種任務(wù),例如文本分類、情感分析、機(jī)器翻譯、問答系統(tǒng)等。 NLP 的實(shí)現(xiàn)通常

    2024年04月25日
    瀏覽(19)
  • Coursera自然語言處理專項(xiàng)課程04:Natural Language Processing with Attention Models筆記 Week02

    Coursera自然語言處理專項(xiàng)課程04:Natural Language Processing with Attention Models筆記 Week02

    Course Certificate 本文是學(xué)習(xí)這門課 Natural Language Processing with Attention Models的學(xué)習(xí)筆記,如有侵權(quán),請(qǐng)聯(lián)系刪除。 Compare RNNs and other sequential models to the more modern Transformer architecture, then create a tool that generates text summaries. Learning Objectives Describe the three basic types of attention Name the two ty

    2024年04月08日
    瀏覽(24)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包