系列文章
【如何訓(xùn)練一個(gè)中英翻譯模型】LSTM機(jī)器翻譯seq2seq字符編碼(一)
【如何訓(xùn)練一個(gè)中英翻譯模型】LSTM機(jī)器翻譯模型訓(xùn)練與保存(二)
【如何訓(xùn)練一個(gè)中英翻譯模型】LSTM機(jī)器翻譯模型部署(三)
【如何訓(xùn)練一個(gè)中英翻譯模型】LSTM機(jī)器翻譯模型部署之onnx(python)(四)
訓(xùn)練一個(gè)翻譯模型,我們需要一份數(shù)據(jù)集,以cmn.txt數(shù)據(jù)集為例:
取前兩行數(shù)據(jù)來(lái)看看,如下:
Wait! 等等!
Hello! 你好。
對(duì)于中譯英,我們希望讓網(wǎng)絡(luò)輸入:“Wait!”,輸出:“等等!”,輸入:“Hello!”,輸出:“你好?!?br> 那么問(wèn)題來(lái)了,這樣的數(shù)據(jù)要如何輸入網(wǎng)絡(luò)進(jìn)行訓(xùn)練呢?
顯然需要進(jìn)行編碼,大白話說(shuō)就是用“0101…”這樣的數(shù)據(jù)來(lái)表示這些文字(為了方便表達(dá),后面稱為字符)。
先假設(shè),我們的訓(xùn)練數(shù)據(jù)只取第一行,那就是只有“Wait! 等等!”,那么,我們開(kāi)始對(duì)它進(jìn)行編碼,讀取cmn.txt文件,并取第一行數(shù)據(jù)中英文分別保存在target_texts ,input_texts,,然后將所有的字符取出來(lái),中英文字符并分別保存在target_characters ,input_characters
input_texts = [] # 保存英文數(shù)據(jù)集
target_texts = [] # 保存中文數(shù)據(jù)集
input_characters = set() # 保存英文字符,比如a,b,c
target_characters = set() # 保存中文字符,比如,你,我,她
with open(data_path, 'r', encoding='utf-8') as f:
lines = f.read().split('\n')# 一行一行讀取數(shù)據(jù)
for line in lines[: min(num_samples, len(lines) - 1)]: # 遍歷每一行數(shù)據(jù)集(用min來(lái)防止越出)
input_text, target_text = line.split('\t') # 分割中英文
# We use "tab" as the "start sequence" character
# for the targets, and "\n" as "end sequence" character.
target_text = '\t' + target_text + '\n'
input_texts.append(input_text)
target_texts.append(target_text)
for char in input_text: # 提取字符
if char not in input_characters:
input_characters.add(char)
for char in target_text:
if char not in target_characters:
target_characters.add(char)
input_characters = sorted(list(input_characters)) # 排序一下
target_characters = sorted(list(target_characters))
num_encoder_tokens = len(input_characters) # 英文字符數(shù)量
num_decoder_tokens = len(target_characters) # 中文文字?jǐn)?shù)量
max_encoder_seq_length = max([len(txt) for txt in input_texts]) # 輸入的最長(zhǎng)句子長(zhǎng)度
max_decoder_seq_length = max([len(txt) for txt in target_texts])# 輸出的最長(zhǎng)句子長(zhǎng)度
print('Number of samples:', len(input_texts))
print('Number of unique input tokens:', num_encoder_tokens)
print('Number of unique output tokens:', num_decoder_tokens)
print('Max sequence length for inputs:', max_encoder_seq_length)
print('Max sequence length for outputs:', max_decoder_seq_length)
可以得到這樣的數(shù)據(jù):
#原始數(shù)據(jù):Wait! 等等!
input_texts = ['Wait!']
target_texts = ['\t等等!\n']
input_characters = ['!', 'W', 'a', 'i', 't']
target_characters = ['\t', '\n', '等', '!']
然后我們就可以開(kāi)始編碼啦。
先對(duì)input_characters 于target_characters 進(jìn)行編號(hào),也就是
['!', 'W', 'a', 'i', 't']
0 1 2 3 4
['\t', '\n', '等', '!']
0 1 2 3
代碼如下:
input_token_index = dict([(char, i) for i, char in enumerate(input_characters)])
target_token_index = dict([(char, i) for i, char in enumerate(target_characters)])
編號(hào)完之后就是:
input_token_index =
{
'!': 0,
'W': 1,
'a': 2,
'i': 3,
't': 4
}
target_token_index =
{
'\t': 0,
'\n': 1,
'等': 2,
'!': 3
}
有了input_token_index 與target_token_index ,我們就可以開(kāi)始對(duì)輸入輸出進(jìn)行編碼,先來(lái)看輸入。
假設(shè)我們的輸入只有一個(gè)字符W,那么根據(jù)input_token_index 對(duì)W進(jìn)行編碼就如下:
可看到W用向量01000表示了,只有W的那個(gè)位置被標(biāo)為1,其余標(biāo)為0
依次類推對(duì)Wait!進(jìn)行編碼,結(jié)果如下:
對(duì)中文進(jìn)行編碼也是一樣的操作:
因此輸入輸出分別可以用encoder_input_data與decoder_input_data這兩個(gè)矩陣來(lái)表示了,這兩個(gè)矩陣?yán)锩娴闹凳且欢?1
['!', 'W', 'a', 'i', 't']
encoder_input_data
[[[0. 1. 0. 0. 0.] W
[0. 0. 1. 0. 0.] a
[0. 0. 0. 1. 0.] i
[0. 0. 0. 0. 1.] t
[1. 0. 0. 0. 0.]]] !
target_texts通過(guò)編碼得到
['\t', '\n', '等', '!']
decoder_input_data
[[[1. 0. 0. 0.] \t
[0. 0. 1. 0.] 等
[0. 0. 1. 0.] 等
[0. 0. 0. 1.] !
[0. 1. 0. 0.]]] \n
為了進(jìn)一步說(shuō)明,我們這時(shí)候?qū)⒂?xùn)練集改為2,也就是num_samples = 2,那么
input_texts = ['Wait!', 'Hello!']
target_texts = ['\t等等!\n', '\t你好。\n']
input_characters = ['!', 'H', 'W', 'a', 'e', 'i', 'l', 'o', 't']
target_characters = ['\t', '\n', '。', '你', '好', '等', '!']
分別對(duì)輸入輸出的內(nèi)容進(jìn)行編碼,可得到:
encoder_input_data =
[[[0. 0. 1. 0. 0. 0. 0. 0. 0.] # 第一句 Wait!
[0. 0. 0. 1. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 1. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 1.]
[1. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0.]]
[[0. 1. 0. 0. 0. 0. 0. 0. 0.] # 第二句 Hello
[0. 0. 0. 0. 1. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 1. 0. 0.]
[0. 0. 0. 0. 0. 0. 1. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 1. 0.]
[1. 0. 0. 0. 0. 0. 0. 0. 0.]]]
decoder_input_data =
[[[1. 0. 0. 0. 0. 0. 0.] # 第一句 \t等等!\n
[0. 0. 0. 0. 0. 1. 0.]
[0. 0. 0. 0. 0. 1. 0.]
[0. 0. 0. 0. 0. 0. 1.]
[0. 1. 0. 0. 0. 0. 0.]]
[[1. 0. 0. 0. 0. 0. 0.] # 第二句 \t你好。\n
[0. 0. 0. 1. 0. 0. 0.]
[0. 0. 0. 0. 1. 0. 0.]
[0. 0. 1. 0. 0. 0. 0.]
[0. 1. 0. 0. 0. 0. 0.]]]
到這里,我們就清楚了這些文字用向量是怎么表示的,有了向量我們可以進(jìn)行計(jì)算,也就是可以搭建一個(gè)網(wǎng)絡(luò)來(lái)訓(xùn)練這些數(shù)據(jù)了,這個(gè)網(wǎng)絡(luò)的輸入是一堆0 1矩陣,輸出也是一堆0 1矩陣,輸入矩陣在輸入字符那里索引得出這個(gè)矩陣是什么句子,而輸出矩陣在輸出字符那里索引得出這個(gè)句子代表什么句子,因此我們就可以來(lái)訓(xùn)練一個(gè)翻譯模型了。
總結(jié)下來(lái):翻譯模型實(shí)際上就是輸入一個(gè)0 1矩陣,輸出另外一個(gè)0 1矩陣。
句子->輸入矩陣->運(yùn)算->輸出矩陣->句子
下面是相應(yīng)的代碼:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-607785.html
# mapping token to index, easily to vectors
# 處理方便進(jìn)行編碼為向量
# {
# 'a': 0,
# 'b': 1,
# 'c': 2,
# ...
# 'z': 25
# }
input_token_index = dict([(char, i) for i, char in enumerate(input_characters)])
target_token_index = dict([(char, i) for i, char in enumerate(target_characters)])
# np.zeros(shape, dtype, order)
# shape is an tuple, in here 3D
encoder_input_data = np.zeros( # (12000, 32, 73) (數(shù)據(jù)集長(zhǎng)度、句子長(zhǎng)度、字符數(shù)量)
(len(input_texts), max_encoder_seq_length, num_encoder_tokens),
dtype='float32')
decoder_input_data = np.zeros( # (12000, 22, 2751)
(len(input_texts), max_decoder_seq_length, num_decoder_tokens),
dtype='float32')
decoder_target_data = np.zeros( # (12000, 22, 2751)
(len(input_texts), max_decoder_seq_length, num_decoder_tokens),
dtype='float32')
# 遍歷輸入文本(input_texts)和目標(biāo)文本(target_texts)中的每個(gè)字符,
# 并將它們轉(zhuǎn)換為數(shù)值張量以供深度學(xué)習(xí)模型使用。
#編碼如下
#我,你,他,這,國(guó),是,家,人,中
#1 0 0 0 1 1 0 1 1,我是中國(guó)人
#1 0 1 0 0 1 1 1 0,他是我家人
# input_texts contain all english sentences
# output_texts contain all chinese sentences
# zip('ABC','xyz') ==> Ax By Cz, looks like that
# the aim is: vectorilize text, 3D
# zip(input_texts, target_texts)成對(duì)取出輸入輸出,比如input_text = 你好,target_text = you good
for i, (input_text, target_text) in enumerate(zip(input_texts, target_texts)):
for t, char in enumerate(input_text):
# 3D vector only z-index has char its value equals 1.0
encoder_input_data[i, t, input_token_index[char]] = 1.
for t, char in enumerate(target_text):
# decoder_target_data is ahead of decoder_input_data by one timestep
decoder_input_data[i, t, target_token_index[char]] = 1.
if t > 0:
# decoder_target_data will be ahead by one timestep
# and will not include the start character.
# igone t=0 and start t=1, means
decoder_target_data[i, t - 1, target_token_index[char]] = 1.
在進(jìn)行模型推理的時(shí)候,你同樣需要相同的一份input_token_index 與target_token_index ,那么就需要將input_characters與target_characters保存下來(lái),在推理之前,將你輸入的內(nèi)容進(jìn)行編碼,因?yàn)橹挥型环菸恢镁幋a,你的網(wǎng)絡(luò)才能認(rèn)識(shí),要不然全亂套了,下面是將input_characters與target_characters保存為txt與讀取的方法:文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-607785.html
# 將 input_characters保存為 input_words.txt 文件
with open('input_words.txt', 'w', newline='') as f:
for char in input_characters:
if char == '\t':
f.write('\\t\n')
elif char == '\n':
f.write('\\n\n')
else:
f.write(char + '\n')
# 將 target_characters保存為 target_words.txt 文件
with open('target_words.txt', 'w', newline='') as f:
for char in target_characters:
if char == '\t':
f.write('\\t\n')
elif char == '\n':
f.write('\\n\n')
else:
f.write(char + '\n')
# 從 input_words.txt 文件中讀取字符串
with open('input_words.txt', 'r') as f:
input_words = f.readlines()
input_characters = [line.rstrip('\n') for line in input_words]
# 從 target_words.txt 文件中讀取字符串
with open('target_words.txt', 'r', newline='') as f:
target_words = [line.strip() for line in f.readlines()]
target_characters = [char.replace('\\t', '\t').replace('\\n', '\n') for char in target_words]
#字符處理,以方便進(jìn)行編碼
input_token_index = dict([(char, i) for i, char in enumerate(input_characters)])
target_token_index = dict([(char, i) for i, char in enumerate(target_characters)])
到了這里,關(guān)于【如何訓(xùn)練一個(gè)中英翻譯模型】LSTM機(jī)器翻譯seq2seq字符編碼(一)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!