Seq2Sep机器训练
Seq2Sep机器训练
1 import numpy as np 2 import torch 3 import random 4 import torch.nn as nn 5 6 # 构建语料库,每行包含中文、英文(解码器输入)和翻译成英文后的目标输出 3 个句子 7 sentences = [ 8 # sos:start of sentence, 模型翻译的起始位置。 9 # eos:end of sentence,模型翻译的结束位置。 10 11 # 原始文本使用 空格 划分为token 12 13 # 原始文本、 解码输入、 解码输出 14 ['黄老师 喜欢 人工智能', '<sos> TeacherMao likes AI', 'TeacherMao likes AI <eos>'], 15 ['我 爱 学习 世界', '<sos> I love studying world', 'I love studying world <eos>'], 16 ['深度学习 改变 世界', '<sos> DL changed the world', 'DL changed the world <eos>'], 17 ['自然 语言 处理 很 强大', '<sos> NLP is so powerful', 'NLP is so powerful <eos>'], 18 ['神经网络 非常 复杂', '<sos> Neural-Nets are complex', 'Neural-Nets are complex <eos>'] 19 ] 20 21 # 遍历每一个句子并将单词添加到词汇表中 22 word_list_cn, word_list_en = [], [] 23 for s in sentences: 24 word_list_cn.extend(s[0].split()) 25 word_list_en.extend(s[1].split()) 26 word_list_en.extend(s[2].split()) 27 28 # 去重,得到没有重复单词的词汇表 29 word_list_cn = list(set(word_list_cn)) # 词典 包含所有的单词,唯一一次就够 30 word_list_en = list(set(word_list_en)) 31 32 # 构建单词到索引的映射(embeeding、rnn、lstm) 33 # 构建词汇表 34 word2idx_cn = {w: i for i, w in enumerate(word_list_cn)} 35 word2idx_en = {w: i for i, w in enumerate(word_list_en)} 36 37 # 构建索引到单词的映射 38 idx2word_cn = {i: w for i, w in enumerate(word_list_cn)} 39 idx2word_en = {i: w for i, w in enumerate(word_list_en)} 40 41 # 计算词汇表的大小 42 voc_size_cn = len(word_list_cn) 43 voc_size_en = len(word_list_en) 44 45 # 定义一个函数,随机选择一个句子和词汇表生成输入、输出和目标数据 46 def make_data(sentences): 47 # 随机选择一个句子进行训练 48 random_sentence = random.choice(sentences) 49 # 将输入句子中的单词转换为对应的索引 50 encoder_input = np.array([[word2idx_cn[n] for n in random_sentence[0].split()]]) 51 # 将输出句子中的单词转换为对应的索引 52 decoder_input = np.array([[word2idx_en[n] for n in random_sentence[1].split()]]) 53 # 将目标句子中的单词转换为对应的索引 54 target = np.array([[word2idx_en[n] for n in random_sentence[2].split()]]) 55 # 将输入、输出和目标批次转换为 LongTensor 56 encoder_input = torch.LongTensor(encoder_input) 57 decoder_input = torch.LongTensor(decoder_input) 58 target = torch.LongTensor(target) 59 return encoder_input, decoder_input, target 60 61 62 # 使用 make_data 函数生成输入、输出和目标张量 63 encoder_input, decoder_input, target = make_data(sentences) 64 for s in sentences: # 获取原始句子 65 if all([word2idx_cn[w] in encoder_input[0] for w in s[0].split()]): 66 original_sentence = s 67 68 print(" 原始句子:", original_sentence) # 打印原始句子 69 print(" 编码器输入张量的形状:", encoder_input.shape) # 打印输入张量形状 70 print(" 解码器输入张量的形状:", decoder_input.shape) # 打印输出张量形状 71 print(" 目标张量的形状:", target.shape) # 打印目标张量形状 72 print(" 编码器输入张量:", encoder_input) # 打印输入张量 73 print(" 解码器输入张量:", decoder_input) # 打印输出张量 74 print(" 目标张量:", target) # 打印目标张量 75 76 77 # 定义编码器类,继承自 nn.Module 78 class Encoder(nn.Module): 79 # 将输入的序列编码成一个包含其全部语义信息的上下文向量 80 def __init__(self, input_size, hidden_size): 81 super(Encoder, self).__init__() 82 self.hidden_size = hidden_size # 设置隐藏层大小 83 self.embedding = nn.Embedding(input_size, hidden_size) # 创建词嵌入层 input_size 词表大小 84 self.rnn = nn.RNN(hidden_size, hidden_size, batch_first=True) # 创建 RNN 层 85 86 def forward(self, inputs, hidden): # 前向传播函数 87 embedded = self.embedding(inputs) # 将输入转换为嵌入向量 88 output, hidden = self.rnn(embedded, hidden) # 将嵌入向量输入 RNN 层并获取输出 89 return output, hidden 90 91 92 class Decoder(nn.Module): 93 def __init__(self, hidden_size, output_size): 94 super(Decoder, self).__init__() 95 self.hidden_size = hidden_size 96 self.embedding = nn.Embedding(output_size, hidden_size) 97 self.rnn = nn.RNN(hidden_size, hidden_size, batch_first=True) 98 99 # 全链接层,维度转换 100 self.out = nn.Linear(hidden_size, output_size) # 全连接层, 目标词汇表的大小 101 102 def forward(self, inputs, hidden): 103 embedded = self.embedding(inputs) 104 output, hidden = self.rnn(embedded, hidden) 105 output = self.out(output) 106 return output, hidden 107 108 109 n_hidden = 128 # 设置隐藏层数量 110 # 创建编码器和解码器 111 encoder = Encoder(voc_size_cn, n_hidden) 112 decoder = Decoder(n_hidden, voc_size_en) 113 print(' 编码器结构:', encoder) # 打印编码器的结构 114 print(' 解码器结构:', decoder) # 打印解码器的结构 115 116 117 class Seq2Seq(nn.Module): 118 def __init__(self, encoder, decoder): 119 super(Seq2Seq, self).__init__() 120 # 初始化编码器和解码器 121 self.encoder = encoder 122 self.decoder = decoder 123 124 def forward(self, enc_input, hidden, dec_input): # 定义前向传播函数 125 # enc_input 中文输入 126 # hidden 初始化状态 127 encoder_output, encoder_hidden = self.encoder(enc_input, hidden) 128 129 # encoder_hidden 最终隐藏状态 130 decoder_hidden = encoder_hidden 131 132 # 英文输入序列 133 decoder_output, _ = self.decoder(dec_input, decoder_hidden) 134 return decoder_output 135 136 137 model = Seq2Seq(encoder, decoder) 138 print('模型结构:', model) 139 140 141 # 定义训练函数 142 def train_seq2seq(model, criterion, optimizer, epochs): 143 for epoch in range(epochs): # epoch 144 # 文本 -》 id 145 encoder_input, decoder_input, target = make_data(sentences) 146 147 # 初始化编码器的初始隐藏状态 148 hidden = torch.zeros(1, encoder_input.size(0), n_hidden) 149 150 optimizer.zero_grad() # 梯度清零 151 output = model(encoder_input, hidden, decoder_input) 152 loss = criterion(output.view(-1, voc_size_en), target.view(-1)) # 分类 153 154 if (epoch + 1) % 100 == 0: # 打印损失 155 print(f"Epoch: {epoch + 1:04d} cost = {loss:.6f}") 156 loss.backward() # 反向传播 157 optimizer.step() # 更新参数 158 159 160 # 训练模型 161 epochs = 500 # 训练轮次 162 criterion = nn.CrossEntropyLoss() # 损失函数 163 optimizer = torch.optim.Adam(model.parameters(), lr=0.001) # 优化器 164 train_seq2seq(model, criterion, optimizer, epochs) # 调用函数训练模型 165 166 167 # 定义测试函数 168 def test_seq2seq(model, source_sentence): 169 # 将输入的句子转换为索引 170 encoder_input = np.array([[word2idx_cn[n] for n in source_sentence.split()]]) 171 172 # 构建输出的句子的索引,以 '<sos>' 开始,后面跟 '<eos>',长度与输入句子相同 173 decoder_input = np.array([word2idx_en['<sos>']] + [word2idx_en['<eos>']] * (len(encoder_input[0]) - 1)) 174 175 # 转换为 LongTensor 类型 176 encoder_input = torch.LongTensor(encoder_input) 177 decoder_input = torch.LongTensor(decoder_input).unsqueeze(0) 178 179 hidden = torch.zeros(1, encoder_input.size(0), n_hidden) 180 predict = model(encoder_input, hidden, decoder_input) 181 predict = predict.data.max(2, keepdim=True)[1] # 概率最大的单词 182 183 # 打印输入的句子和预测的句子 184 print(source_sentence, '->', [idx2word_en[n.item()] for n in predict.squeeze()]) 185 186 187 # 测试模型 188 test_seq2seq(model, '黄老师 喜欢 人工智能') # 没有解码器输入

浙公网安备 33010602011771号