使用Python實現深度學習模型:序列到序列模型(Seq2Seq)

华为云开发者联盟發表於2024-06-06

本文分享自華為雲社群《使用Python實現深度學習模型:序列到序列模型(Seq2Seq)》,作者: Echo_Wish。

序列到序列(Seq2Seq)模型是一種深度學習模型,廣泛應用於機器翻譯、文字生成和對話系統等自然語言處理任務。它的核心思想是將一個序列(如一句話)對映到另一個序列。本文將詳細介紹 Seq2Seq 模型的原理,並使用 Python 和 TensorFlow/Keras 實現一個簡單的 Seq2Seq 模型。

1. 什麼是序列到序列模型?

Seq2Seq 模型通常由兩個主要部分組成:編碼器(Encoder)和解碼器(Decoder)。編碼器將輸入序列編碼成一個固定長度的上下文向量(context vector),然後解碼器根據這個上下文向量生成目標序列。

1.1 編碼器(Encoder)

編碼器是一個迴圈神經網路(RNN),如 LSTM 或 GRU,用於處理輸入序列,並生成一個上下文向量。這個向量總結了輸入序列的全部資訊。

1.2 解碼器(Decoder)

解碼器也是一個 RNN,使用編碼器生成的上下文向量作為初始輸入,並逐步生成目標序列的每一個元素。

1.3 訓練過程

在訓練過程中,解碼器在每一步生成一個單詞,並使用該單詞作為下一步的輸入。這種方法被稱為教師強制(Teacher Forcing)。

2. 使用 Python 和 TensorFlow/Keras 實現 Seq2Seq 模型

我們將使用 TensorFlow/Keras 實現一個簡單的 Seq2Seq 模型,進行英法翻譯任務。

2.1 安裝 TensorFlow

首先,確保安裝了 TensorFlow:

pip install tensorflow

2.2 資料準備

我們使用一個簡單的英法翻譯資料集。每個句子對由英語句子和其對應的法語翻譯組成。

import numpy as np
import tensorflow as tf
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences

# 示例資料集
data = [
    ("Hello, how are you?", "Bonjour, comment ça va?"),
    ("I am fine.", "Je vais bien."),
    ("What is your name?", "Quel est ton nom?"),
    ("Nice to meet you.", "Ravi de vous rencontrer."),
    ("Thank you.", "Merci.")
]

# 準備輸入和目標句子
input_texts = [pair[0] for pair in data]
target_texts = ['\t' + pair[1] + '\n' for pair in data]

# 詞彙表大小
num_words = 10000

# 使用 Keras 的 Tokenizer 對輸入和目標文字進行分詞和編碼
input_tokenizer = Tokenizer(num_words=num_words)
input_tokenizer.fit_on_texts(input_texts)
input_sequences = input_tokenizer.texts_to_sequences(input_texts)
input_sequences = pad_sequences(input_sequences, padding='post')

target_tokenizer = Tokenizer(num_words=num_words, filters='')
target_tokenizer.fit_on_texts(target_texts)
target_sequences = target_tokenizer.texts_to_sequences(target_texts)
target_sequences = pad_sequences(target_sequences, padding='post')

# 輸入和目標序列的最大長度
max_encoder_seq_length = max(len(seq) for seq in input_sequences)
max_decoder_seq_length = max(len(seq) for seq in target_sequences)

# 建立輸入和目標資料的 one-hot 編碼
encoder_input_data = np.zeros((len(input_texts), max_encoder_seq_length, num_words), dtype='float32')
decoder_input_data = np.zeros((len(input_texts), max_decoder_seq_length, num_words), dtype='float32')
decoder_target_data = np.zeros((len(input_texts), max_decoder_seq_length, num_words), dtype='float32')

for i, (input_seq, target_seq) in enumerate(zip(input_sequences, target_sequences)):
    for t, word_index in enumerate(input_seq):
        encoder_input_data[i, t, word_index] = 1
    for t, word_index in enumerate(target_seq):
        decoder_input_data[i, t, word_index] = 1
        if t > 0:
            decoder_target_data[i, t-1, word_index] = 1

2.3 構建 Seq2Seq 模型

from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, LSTM, Dense

# 編碼器
encoder_inputs = Input(shape=(None, num_words))
encoder_lstm = LSTM(256, return_state=True)
encoder_outputs, state_h, state_c = encoder_lstm(encoder_inputs)
encoder_states = [state_h, state_c]

# 解碼器
decoder_inputs = Input(shape=(None, num_words))
decoder_lstm = LSTM(256, return_sequences=True, return_state=True)
decoder_outputs, _, _ = decoder_lstm(decoder_inputs, initial_state=encoder_states)
decoder_dense = Dense(num_words, activation='softmax')
decoder_outputs = decoder_dense(decoder_outputs)

# 定義模型
model = Model([encoder_inputs, decoder_inputs], decoder_outputs)

# 編譯模型
model.compile(optimizer='rmsprop', loss='categorical_crossentropy')

# 訓練模型
model.fit([encoder_input_data, decoder_input_data], decoder_target_data, batch_size=64, epochs=100, validation_split=0.2)

2.4 推理模型

為了在預測時生成譯文,我們需要單獨定義編碼器和解碼器模型。

# 編碼器模型
encoder_model = Model(encoder_inputs, encoder_states)

# 解碼器模型
decoder_state_input_h = Input(shape=(256,))
decoder_state_input_c = Input(shape=(256,))
decoder_states_inputs = [decoder_state_input_h, decoder_state_input_c]

decoder_outputs, state_h, state_c = decoder_lstm(
    decoder_inputs, initial_state=decoder_states_inputs)
decoder_states = [state_h, state_c]
decoder_outputs = decoder_dense(decoder_outputs)

decoder_model = Model(
    [decoder_inputs] + decoder_states_inputs,
    [decoder_outputs] + decoder_states
)

2.5 定義翻譯函式

我們定義一個函式來使用訓練好的模型進行翻譯。

def decode_sequence(input_seq):
    # 編碼輸入序列得到狀態向量
    states_value = encoder_model.predict(input_seq)
    
    # 生成的序列初始化一個開始標記
    target_seq = np.zeros((1, 1, num_words))
    target_seq[0, 0, target_tokenizer.word_index['\t']] = 1.
    
    # 逐步生成譯文序列
    stop_condition = False
    decoded_sentence = ''
    while not stop_condition:
        output_tokens, h, c = decoder_model.predict([target_seq] + states_value)
        
        # 取機率最大的詞作為下一個詞
        sampled_token_index = np.argmax(output_tokens[0, -1, :])
        sampled_word = target_tokenizer.index_word[sampled_token_index]
        decoded_sentence += sampled_word
        
        # 如果達到結束標記或者最大序列長度,則停止
        if (sampled_word == '\n' or len(decoded_sentence) > max_decoder_seq_length):
            stop_condition = True
            
        # 更新目標序列
        target_seq = np.zeros((1, 1, num_words))
        target_seq[0, 0, sampled_token_index] = 1.
        
        # 更新狀態
        states_value = [h, c]
    
    return decoded_sentence

# 測試翻譯
for seq_index in range(10):
    input_seq = encoder_input_data[seq_index: seq_index + 1]
    decoded_sentence = decode_sequence(input_seq)
    print('-')
    print('Input sentence:', input_texts[seq_index])
    print('Decoded sentence:', decoded_sentence)

3. 總結

在本文中,我們介紹了序列到序列(Seq2Seq)模型的基本原理,並使用 Python 和 TensorFlow/Keras 實現了一個簡單的英法翻譯模型。希望這篇教程能幫助你理解 Seq2Seq 模型的工作原理和實現方法。隨著對 Seq2Seq 模型的理解加深,你可以嘗試實現更復雜的模型和任務,例如注意力機制和更大規模的資料集。

點選關注,第一時間瞭解華為雲新鮮技術~

相關文章