Pytorch实战_Seq2seq模型
1. Sequence-to-Sequence 簡介
大多數常見的 sequence-to-sequence (seq2seq) model 為 encoder-decoder model,主要由兩個部分組成,分別是 Encoder 和 Decoder,而這兩個部分大多數是由 recurrent neural network (RNN) 實現。
Encoder 是將一連串的輸入,如文字、影片、聲音訊號等,編碼為單個向量,這個向量可以想像為整個輸入的抽象表示,包含了整個輸入的資訊。
Decoder 是將 Encoder 輸出的向量進行逐步解碼,一次輸出一個結果,直到將最終的目標全部輸出為止,每次輸出會影響下一個輸出,一般會在開始輸入 < BOS > 來表示開始解碼,會在結尾出輸出 < EOS > 來表示解碼結束。
2. 任務介紹
- 英文翻譯為中文
- 輸入: 一句英文 (e.g. tom is a student .)
- 輸出: 中文翻譯 (e.g. 湯姆 是 個 學生 。)
3. 實現過程
首先要做的是下載資料,主要是用來下載本次任務需要的數據集
!gdown --id '1r4px0i-NcrnXy1-tkBsIwvYwbWnxAhcg' --output data.tar.gz !tar -zxvf data.tar.gz !mkdir ckpt !ls之后導入需要用到的包(如果nltk包沒有下載的話,可使用第一段代碼進行下載)
!pip3 install --user nltk import torch import torch.nn as nn import torch.optim as optim import torch.nn.functional as F import torch.utils.data as data import torch.utils.data.sampler as sampler import torchvision from torchvision import datasets, transformsimport numpy as np import sys import os import random import jsondevice = torch.device("cuda" if torch.cuda.is_available() else "cpu") # 判斷是用 CPU 還是 GPU 執行運算需要注意的是,不同的句子往往有著不同的長度,這無疑給訓練帶來了不小的麻煩(因為 RNN 的輸入維度要進行相應的改變)。為了解決這個麻煩,我們使用 <pad> 長度較短的句子進行填充。因此這里定義一個長度轉換的類
import numpy as npclass LabelTransform(object):def __init__(self, size, pad):self.size = sizeself.pad = paddef __call__(self, label):label = np.pad(label, (0, (self.size - label.shape[0])), mode='constant', constant_values=self.pad)return label下一步就是數據的準備了,我們定義一個Dataset。
-
Data (出自manythings 的 cmn-eng):
- 訓練資料:18000句
- 驗證資料: 500句
- 測試資料: 2636句
-
資料預處理:
- 英文:
- 用 subword-nmt 套件將word轉為subword
- 建立字典:取出標簽中出現頻率高于預定閾值的subword
- 中文:
- 用 jieba 將中文句子進行斷句
- 建立字典:取出標簽中出現頻率高于預定閾值的詞
- 特殊字元: < PAD >, < BOS >, < EOS >, < UNK >
- < PAD > :無意義,將句子拓展到相同長度
- < BOS > :Begin of sentence, 開始字元
- < EOS > :End of sentence, 結尾字元
- < UNK > :單字沒有出現在字典里的字
- 將字典里出現的 subword (詞) 用一個整數表示,分為英文和中文的字典,方便之后轉化為 one-hot vector
- 英文:
接下來就是構建自己的模型
Encoder
- seq2seq模型的編碼器為RNN。對于每個輸入,Encoder 會輸出一個向量和一個隱藏層狀態(hidden state),并將隱藏層狀態用于下一個輸入,換句話說,Encoder 會逐步讀入輸入序列。
- 參數:
- en_vocab_size 是英文字典的大小,也就是英文的 subword 的個數
- emb_dim 是 embedding 的維度,主要將 one-hot vector 的單詞向量壓縮到指定的維度,可以使用預先訓練好的 word embedding,如 Glove 和 word2vector
- hid_dim 是 RNN 輸出和隱藏狀態的維度
- n_layers 是 RNN 要疊多少層
- dropout 是決定有多少的機率將某某個節點變為 0,主要是為了防止 overfitting ,一般來說是在訓練集使用,測試集不使用
- Encoder 的輸入和輸出:
- 輸入:
- 英文的整數序列 e.g. 1, 28, 29, 205, 2
- 輸出:
- outputs: 最上層 RNN 全部的輸出,可以用 Attention 再進行處理
- hidden: 每層最后的隱藏狀態,將傳輸到后面的 Decoder 進行解碼
- 輸入:
Decoder
-
Decoder 是另一個 RNN,在最簡單的 seq2seq decoder 中,僅使用 Encoder 對每一層最后的隱藏狀態來進行解碼,而這最好的的隱藏狀態有些被稱為 “content vector”,因為可以想象它對整個前文序列進行了編碼, 此 “content vector” 用作 Decoder 的初始隱藏狀態, 而 Encoder 的輸出通常用于 Attention Mechanism 產生相應的 Attention。
-
參數
- en_vocab_size 是英文字典的大小,也就是英文的 subword 的個數
- emb_dim 是 embedding 的維度,主要將 one-hot vector 的單詞向量壓縮到指定的維度,可以使用預先訓練好的 word embedding,如 Glove 和 word2vector
- hid_dim 是 RNN 輸出和隱藏狀態的維度
- output_dim 是最終輸出的維度,一般來說是將 hid_dim 轉到 one-hot vector 的單詞向量
- n_layers 是 RNN 要疊多少層
- dropout 是決定有多少的機率將某某個節點變為 0,主要是為了防止 overfitting ,一般來說是在訓練集使用,測試集不使用
- isatt 是來決定是否使用 Attention Mechanism
-
Decoder 的輸入和輸出:
- 輸入:
- 前一次解碼出來的單詞的整數表示
- 輸出:
- hidden: 根據輸入和前一次的隱藏轉態,現在的隱藏轉態的更新的結果
- output: 每個字有多少概率是這次解碼的結果
- 輸入:
Attention
-
當輸入過長時,或是單獨靠 “content vector” 無法獲取整個輸入的意思時,用 Attention Mechanism 來提供 Decoder 更多的資訊
-
主要是根據現在 Decoder hidden state ,去計算在 Encoder outputs 中,那些與其有較高的關系,根據關系的數值來決定傳給 Decoder 哪些額外的資訊
-
常見 Attention 的操作是用 Neural Network / Dot Product 來計算 Decoder hidden state 和 Encoder outputs 之間的關系,再對所有算出來的數值做 softmax ,最后根據過完 softmax 的值對 Encoder outputs 做 weight sum
-
李宏毅老師的課程在此處并沒有給出具體的代碼,需要大家自己補充。大家可以參考這篇文章 Seq2Seq (Attention) 的 PyTorch 實現 或者B站的視頻 PyTorch35——基于注意力機制的Seq2Seq的PyTorch實現示例。
Seq2seq模型
- 由 Encoder 和 Decoder 組成
- 接收輸入并傳給 Encoder
- 將 Encoder 的輸出傳給 Decoder
- 不斷地將 Decoder 的輸出傳回 Decoder ,進行解碼
- 當解碼完成,將 Decoder 的輸出傳回
總結
以上是生活随笔為你收集整理的Pytorch实战_Seq2seq模型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hadoop Day06~MapRedu
- 下一篇: 利用百度定位