main
首先要定义
1.一个Encoder
2.一个AttentionDecoder
3.开始train
需要定义Encoder,Decoder结构,Encoder,AttentionDecoder需要vocab_size,hidden_size
TrainIter
声明一系列的参数,并读入数据。
迭代前声明好优化器,损失函数。
以batch_size大小读入数据,将tensor数据放入train中进行迭代。
def trainIter(encoder,decoder,n_iters):
criterion=nn.NLLLoss()
encoder_optimizer=optim.SGD(encoder.paremeters(),lr=0.001)
decoder_optimizer=optim.SGD(decoder.paremeters(),lr=0.001)
trainPair=[random.choice(pairs) for i in range(1,n_iters) ]
for i in range(1,n_iters):
trainpair=trainPair[iter-1]
input_tensor=pair2tensor(trainpair[0])
output_tensor=pair2tensor(trainpair[1])
loss=train(input_tensor,output_tensor,encoder,decoder,encoder_optimizer,decoder_optimizer,criterion)
Train
接收数据,将数据输入进模型中进行处理,计算loss。优化器进行工作。
实例化模型的时候我们传入的是__init__种需要的数据,使用模型的时候我们使用的是 forward中的数据。
def train(input_tensor, target_tensor, encoder, decoder, encoder_optimizer, decoder_optimizer, criterion, max_length=MAX_LENGTH):
encoder_hidden = encoder.initHidden()
encoder_optimizer.zero_grad()
decoder_optimizer.zero_grad()
input_length = input_tensor.size(0)
target_length = target_tensor.size(0)
encoder_outputs = torch.zeros(max_length, encoder.hidden_size, device=device)
loss = 0
for ei in range(input_length):
encoder_output, encoder_hidden = encoder(
input_tensor[ei], encoder_hidden)
encoder_outputs[ei] = encoder_output[0, 0]
decoder_input = torch.tensor([[SOS_token]], device=device)
decoder_hidden = encoder_hidden
use_teacher_forcing = True if random.random() < teacher_forcing_ratio else False
if use_teacher_forcing:
# Teacher forcing: Feed the target as the next input
for di in range(target_length):
decoder_output, decoder_hidden, decoder_attention = decoder(
decoder_input, decoder_hidden, encoder_outputs)
loss += criterion(decoder_output, target_tensor[di])
decoder_input = target_tensor[di] # Teacher forcing
else:
# Without teacher forcing: use its own predictions as the next input
for di in range(target_length):
decoder_output, decoder_hidden, decoder_attention = decoder(
decoder_input, decoder_hidden, encoder_outputs)
topv, topi = decoder_output.topk(1)
decoder_input = topi.squeeze().detach() # detach from history as input
loss += criterion(decoder_output, target_tensor[di])
if decoder_input.item() == EOS_token:
break
loss.backward()
encoder_optimizer.step()
decoder_optimizer.step()
return loss.item() / target_length
数据预处理
数据预处理要做的就是,读取数据(确定按行读取还是全文读取),在数据中获得我们想要的形式(分类问题获得数据以及标签,翻译问题形成pair),构建字典。
获得后续的字典的大小,以及相关的索引数据。
def propress(lang1,lang2):
input_lang,output_lang,pairs=readLines(lang1,lang2)
for pair in lines:
input=pair[0]
output=pair[1]
input_lang.addsentence(pair[0])
output_lang.addsentence(pair[1])
return input_lang,output_lang,pairs
def readLines(lang1,lang2):
lines=with open () .read().strip().split('\n')
input_lang=Lang(lang1)
output_lang=Lang(lang2)
pairs=[[normalizeString(l) for l in i.split('\t')]for i in lines]
return input_lang,output_lang,pairs
构建Tensor
确定我们传入模型的数据单位,以及我们的最小单位是词级还是字符级别。
def word2tensor(lang,sentence):
return [lang.word2index[word] for word in sentence.split(' ')]
def sentence2index(lang,sentence):
index=word2tensor(lang,sentence)
index.append(EOS_token)
return torch.tensor(index,dtype=torch.long,device=device)
def pair2tensor(pair):
input_tensor=sentence2index(input_lang,pair[0])
output_tensor=sentence2index(output_lang,pair[1])