【NLP】Bi-LSTM 进行机器翻译

目标:利用 CMN 微型中英文翻译数据集,进行 中文 -> 英文 翻译
在这里插入图片描述

读取数据

import numpy as np
import pandas as pd

# 处理 cmn 数据集,将每行数据分割成中文和英文,每一行的格式: '英文\t中文\t其他'
# 转换为:[['英文', '中文'], ['英文', '中文'], ...]
def get_dataset():
    lines = read_txt('./cmn/cmn.txt')
    dataset = []
    for line in lines:
        line = line.strip().split('\t')
        dataset.append(line[:2])
    return dataset

ret_ls = get_dataset()

制作数据集

tokenizer 统计词频

# 将数据集合并到 string_zh_all 和 string_en_all ,方便后面统计词频
string_zh_all = ''
string_en_ls = []
for i in range(len(ret_ls)):
    string_zh_all += ret_ls[i][1]
    string_en_ls.append(ret_ls[i][0])
# 从 keras 导入 Tokenizer
from keras.preprocessing.text import Tokenizer

# 导入结巴分词
import jieba
# 对中文数据集进行分词
string_zh_all_cut = jieba.lcut(string_zh_all)
print(len(string_zh_all_cut))
string_zh_all_cut[:10]
# 用tokenizer 对中文数据集进行统计
tokenizer_zh = Tokenizer(num_words=15000)
tokenizer_zh.fit_on_texts(string_zh_all_cut)
# 查看中文数据集中的词频
tokenizer_zh.word_counts
# 查看中文数据集中的词频排序
print(len(tokenizer_zh.word_index))
tokenizer_zh.word_index

{‘。’: 1,
‘我’: 2,
‘的’: 3,
‘了’: 4,
‘你’: 5,
‘?’: 6,
‘他’: 7,
‘在’: 8,
‘是’: 9,
‘汤姆’: 10,

‘猜’: 997,
‘較’: 998,
‘考试’: 999,
‘男生’: 1000,
…}

# 用 tokenizer 对英文数据集进行统计 ( 单词级别 )
tokenizer_en = Tokenizer(num_words=7000,split=' ')
tokenizer_en.fit_on_texts(string_en_ls)
# 查看英文数据集中的词频
tokenizer_en.word_counts
# 查看英文数据集中的词频排序
print(len(tokenizer_en.word_index))
tokenizer_en.word_index

{‘the’: 1,
‘i’: 2,
‘to’: 3,
‘you’: 4,
‘a’: 5,
‘is’: 6,
‘tom’: 7,

‘useful’: 997,
‘supposed’: 998,
‘noise’: 999,
‘enter’: 1000,
…}

制作数据集

data_en_ls = []
data_zh_ls = []
for i in range(len(ret_ls)):
    seq_en = ret_ls[i][0]
    seq_zh = ret_ls[i][1]
    # 用 tokenizer 把英文句子转化成序列
    seq_en_token = tokenizer_en.texts_to_sequences([seq_en])
    # 先用结巴分词 lcut 分词,然后用 tokenizer 把中文句子转化成序列
    seq_zh_lcut =  jieba.lcut(seq_zh)
    seq_zh_token = tokenizer_zh.texts_to_sequences([seq_zh_lcut])
    # 把英文序列和中文序列分别放到 data_en_ls 和 data_zh_ls 中
    data_en_ls.append(seq_en_token[0])
    data_zh_ls.append(seq_zh_token[0])
len(data_en_ls),len(data_zh_ls)
# 只保留 20 个词以内的句子
data_en_ls_20 = []
data_zh_ls_20 = []

for i in range(len(ret_ls)):
    # 只保留 20 个词以内的句子
    # 只有在中文和英文同时满足条件的句子才会被保留
    len_zh = len(data_zh_ls[i])
    len_en = len(data_en_ls[i])
    if len_zh <= 20 and len_en <= 20:
        data_en_ls_20.append(data_en_ls[i])
        data_zh_ls_20.append(data_zh_ls[i])
# 从 keras_preprocessing 导入 pad_sequences
from keras_preprocessing.sequence import pad_sequences

# 把英文序列和中文序列都 pad 到 20 个词,转化成 numpy 数组
data_en_mat = pad_sequences(data_en_ls_20, maxlen=20, padding='post')
data_zh_mat = pad_sequences(data_zh_ls_20, maxlen=20, padding='post')
data_en_mat

array([[1435, 0, 0, …, 0, 0, 0],
[1435, 0, 0, …, 0, 0, 0],
[ 541, 0, 0, …, 0, 0, 0],
…,
[ 98, 230, 9, …, 0, 0, 0],
[ 11, 176, 716, …, 9, 150, 0],
[ 7, 67, 37, …, 128, 278, 73]])

data_zh_mat

array([[2710, 1, 0, …, 0, 0, 0],
[1087, 1, 0, …, 0, 0, 0],
[ 5, 102, 308, …, 0, 0, 0],
…,
[ 415, 8, 12, …, 0, 0, 0],
[ 2, 645, 3, …, 2333, 1, 0],
[ 10, 1994, 295, …, 0, 0, 0]])

划分训练集测试集

# 划分训练集测试集
from sklearn.model_selection import train_test_split
data_en_train, data_en_test, data_zh_train, data_zh_test = train_test_split(data_en_mat, data_zh_mat, test_size=0.3, random_state=42, shuffle=True)

训练模型

建立模型

# 建立 keras LSTM 模型
from keras.models import Sequential
from keras.layers import Dense, Embedding, LSTM, Dropout, Bidirectional
# LTSM Seq2Seq 模型,中文 -> 英文 翻译,3层 LSTM
model = Sequential()
model.add(Embedding(15000, 256, input_length=20))
model.add(Bidirectional(LSTM(256, return_sequences=True)))
model.add(Dropout(0.5))
model.add(Bidirectional(LSTM(256, return_sequences=True)))
model.add(Dropout(0.5))
model.add(Bidirectional(LSTM(256, return_sequences=True)))
model.add(Dropout(0.5))
model.add(Dense(7000, activation='softmax'))
model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.summary()

在这里插入图片描述

# 对英文标签数据进行 reshape ,因为模型的输出是 3 维的,而标签数据是 2 维的
data_en_train_reshape = data_en_train.reshape(data_en_train.shape[0], data_en_train.shape[1], 1)
data_en_test_reshape = data_en_test.reshape(data_en_test.shape[0], data_en_test.shape[1], 1)
# 训练,训练 10 个 epoch,用_train 作为训练数据,用_test 作为测试数据
# 中文 -> 英文 翻译,所以 zh 是输入,en 是输出
model.fit(data_zh_train, data_en_train_reshape, epochs=20, batch_size=128, validation_data=(data_zh_test, data_en_test_reshape))

# 保存模型
model.save('NLP_cmn_zh_en_v1_LSTM.h5')
# 保存中文和英文分词器
import pickle
with open('tokenizer_zh.pickle', 'wb') as handle:
    pickle.dump(tokenizer_zh, handle, protocol=pickle.HIGHEST_PROTOCOL)
with open('tokenizer_en.pickle', 'wb') as handle:
    pickle.dump(tokenizer_en, handle, protocol=pickle.HIGHEST_PROTOCOL)

测试模型

# 测试模型

test_string = '你是汤姆吗?'
test_string_lcut = jieba.lcut(test_string)
test_string_token = tokenizer_zh.texts_to_sequences([test_string_lcut])
test_string_mat = pad_sequences(test_string_token, maxlen=20, padding='post')

# 输入模型
pred = model.predict(test_string_mat)
# 取 argmax 
pred = np.argmax(pred, axis=2)
# 把数字转化成英文单词
pred = tokenizer_en.sequences_to_texts(pred)
pred

1/1 [==============================] - 0s 49ms/step
[‘are you tom’]

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值