keras+seq2seq实现翻译

这周主要学习seq2seq模型,先敲代码感受一下,之后会总结学习过程中学习到的理论知识。
1.获取数据

from keras.models import Model
from keras.layers import Input,LSTM,Dense,TimeDistributed
import numpy as np
import keras.backend as K
import re
def clean_text(text):#可以根据下面的characters再回来调整要替换的特殊字符,保证字母纯洁
    
    text = re.sub(r'\n', ' ', text) #前一个参数由后一个参数取代,在text中
    text = re.sub(r'[{}@_*>()\\#%+=\[\]]','', text)
    text = re.sub('\xa0','', text)
    text = re.sub( '\u2009','', text)
    text = re.sub('\u202f','', text)
    text = re.sub('\u2009','', text)
    return text
#1.获取数据
data_path='fra.txt'
num_samples=10000
def get_dataset(data_path,num_samples):#数据地址,利用地址内的多少数据进行网络训练
    input_texts=[]
    target_texts=[]
    input_characters = set()#含有的英文字母
    target_characters = set()#含有的法文字母
    with open(data_path,'r',encoding='utf-8') as f:
        lines=f.read().split('\n')#读取所有行,作为列表元素存入lines
    for line in lines[:min(num_samples,len(lines))]:#取所有样本或者固定数量样本数
        input_text,target_text,_=line.split('\t')#用\t划分出英文,法文和无用数据
        target_text='\t'+target_text+'\n'#target以\t作为第一输入,后面的输入由前面的预测作为输入
        target_text=clean_text(target_text)
        input_textt=clean_text(input_text)
        input_texts.append(input_text)
        target_texts.append(target_text)
        #取出每一个英法字母,作为集合,将输入的每个单词的字母以onehot形式输入
        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)
    return input_texts,target_texts,input_characters,target_characters 

2.调整数据格式

#2.设置数据输入格式
batch_size=64
epochs=100
latent_dim=256#LSTM网络的神经元个数
input_texts,target_texts,input_characters,target_characters = get_dataset(data_path, num_samples)
max_input_length=max(len(txt) for txt in input_texts)
max_out_length=max(len(txt) for txt in target_texts)
input_characters = sorted(list(input_characters))
target_characters = sorted(list(target_characters))
num_encoder_tokens = len(input_characters)
num_decoder_tokens = len(target_characters)
print('一共有多少训练样本:', len(input_texts))
print('多少个英文字母:', num_encoder_tokens)
print('多少个法文字母:',num_decoder_tokens)
print('最大英文序列:', max_input_length)
print('最大法文序列:', max_out_length)
print(input_characters,target_characters)
#建立字母到数字的映射
input_token_index={char:i for i,char in enumerate(input_characters)}
target_token_index={char:i for i,char in enumerate(target_characters)}
#print(input_token_index)
#设置输入输出数据维度格式
encoder_input_data=np.zeros((len(input_texts),max_input_length,num_encoder_tokens),dtype='float32')#(10000,16,71)
decoder_input_data=np.zeros((len(input_texts),max_out_length,num_decoder_tokens),dtype='float32')#(10000,59,92)
decoder_target_data=np.zeros((len(input_texts),max_out_length,num_decoder_tokens),dtype='float32')#(10000,59,92)
#将数据放入固定格式中
for i ,(input_text,target_text) in enumerate(zip(input_texts,target_texts)):#遍历每一个单词
    for t,char in enumerate(input_text):#遍历每一个字母
        encoder_input_data[i,t,input_token_index[char]]=1.
    encoder_input_data[i,t+1:,input_token_index[' ']]=1.#后面补空格
    for t,char in enumerate(target_text):
        decoder_input_data[i,t,target_token_index[char]]=1.#num_decoder_tokens
        if t>0:
            decoder_target_data[i,t-1,target_token_index[char]]=1.## decoder_target_data不num_decoder_tokens
    decoder_input_data[i,t+1:,input_token_index[' ']]=1.
    decoder_target_data[i, t:, target_token_index[' ']] = 1.

3.构建网络并训练

#构建网络
encoder_inputs=Input(shape=(None,num_encoder_tokens))#None其实是单词的最大长度,以此为网络的输入序列数,num_encoder_tokens是每个输入的维度
encoder_outputs,state_h,state_c=LSTM(latent_dim,return_state=True)(encoder_inputs)
encoder_states=[state_h,state_c]
decoder_inputs=Input(shape=(None,num_decoder_tokens))#None其实是单词的最大长度,设为None是因为后面实际预测时是一个字母一个字母的预测
decoder_outputs,_,_=LSTM(latent_dim,return_sequences=True,return_state=True)(decoder_inputs,initial_state=encoder_states)
decoder_outputs=TimeDistributed(Dense(num_decoder_tokens,activation='softmax'))(decoder_outputs)
model=Model([encoder_inputs,decoder_inputs],decoder_outputs)
model.summary()
#开始训练
model.compile(optimizer='rmsprop',loss='categorical_crossentropy',metrics=['accuracy'])
model.fit([encoder_input_data,decoder_input_data],decoder_target_data,batch_size=batch_size,epochs=epochs,validation_split=0.2)
model.save('fra.h5')
K.clear_session()

4.开始实际预测

#开始实际预测使用
encoder_inputs=Input(shape=(None,num_encoder_tokens))
encoder_outputs,state_h,state_c=LSTM(latent_dim,return_state=True)(encoder_inputs)
encoder_states=[state_h,state_c]
encoder_model=Model(encoder_inputs,encoder_states)
encoder_model.load_weights('fra.h5',by_name=True)
encoder_model.summary()
decoder_inputs=Input(shape=(None,num_decoder_tokens))
decoder_state_input_h=Input(shape=(latent_dim,))#从encoder算出来的h
decoder_state_input_c=Input(shape=(latent_dim,))#从encoder算出来的c
decoder_states_inputs=[decoder_state_input_h,decoder_state_input_c]
decoder_outputs,state_h,state_c=LSTM(latent_dim,return_sequences=True,return_state=True)(decoder_inputs,initial_state=decoder_states_inputs)
decoder_states=[state_h,state_c]
decoder_outputs=TimeDistributed(Dense(num_decoder_tokens,activation='softmax'))(decoder_outputs)#每个输出连接一个Dense,算出此输出位置哪个字母的概率最大
decoder_model=Model([decoder_inputs]+decoder_states_inputs,[decoder_outputs]+decoder_states)
decoder_model.load_weights('fra.h5',by_name=True)
#将预测结果进行解码
num2char_input={i:char for i,char in enumerate(input_characters)}
num2char_target={i:char for i,char in enumerate(target_characters)}
def decoder_sequence(input_seq):
    states_value=encoder_model.predict(input_seq)#将要翻译的单词输入encoder进行预测输出
    target_seq=np.zeros((1,1,num_decoder_tokens))#输出的shape,
    target_seq[0,0,target_token_index['\t']]=1#decoder的第一个输入是'\t'(化成onehot形式)
    stop_condition=False
    decoder_sentence=''
    while not stop_condition:
        output_token,h,c=decoder_model.predict([target_seq]+states_value)#将'\t‘和encoder的输出作为decoder的输入,预测下一个字母的输出
        sample_tokend_index=np.argmax(output_token[0,-1,:])#取出字母概率最大的哪个位置的下标
        sample_char=num2char_target[sample_tokend_index]#取出那个字母
        decoder_sentence+=sample_char#将字母添加到输出字符串
        if (sample_char=='\n' or len(decoder_sentence)>=max_out_length):
            stop_condition=True
        states_value=[h,c]#decode对上一个字母预测后的预测输出
        target_seq=np.zeros((1,1,num_decoder_tokens))
        target_seq[0,0,sample_tokend_index]=1

    return decoder_sentence
for seq_index in range(60):
    input_seq=np.expand_dims(encoder_input_data[seq_index],axis=0)
    decoder_sentence=decoder_sequence(input_seq)
    print('-')
    print('Input sentence:', input_texts[seq_index])
    print('Decoded sentence:', decoder_sentence)

参考:https://blog.csdn.net/weixin_44791964/article/details/103988481

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是小z呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值