赞
踩
首先简单实现构造LSTM模型以及使用LSTM进行计算,代码如下
import torch import torch.nn as nn class rnn(nn.Module): def __init__(self,input_dim,output_dim,num_layer): super(rnn,self).__init__() self.layer1 = nn.LSTM(input_dim,output_dim,num_layer) def forward(self,input): output,hidden=self.layer1(input)#LSTM的输出包括隐藏层计算结果以及隐藏层状态,因此=左边必须是两个值 return output,hidden if __name__=="__main__": #实例化 encoder = rnn(input_dim = 10, output_dim = 5, num_layer = 2) #创建输入 input = torch.randn(20,15,10)#参数分别代表sequence_length,batch_size,word_embedding #计算 output,hidden=encoder(input) print(output.shape)#输出结果的维度为sequence_length,batch_size,output_dim(最后一层神经网络的输出层维度) print(hidden[0].shape)#输出结果的维度为num_layer,batch_size,output_dim
个人疑惑小结:
1)numlayer代表LSTM的堆叠层数,该值为2时,则将第一层LSTM的输出作为第二层LSTM 的输入继续计算
2)bidirectional是决定每一层LSTM是否是双向的,当LSTM为双向模型时,最终每个token的输出向量为正反向向量的拼接,例如设置的隐藏层维度为100维,经双向LSTM计算后,每个token的维度为200维。
3)LSTM会返回output和hidden两个值,其中output包含输入序列中每个字的输出向量,最后一个字的输出向量代表整句话的语义向量;hidden是一个元组,元组中的第一个元素代表每个字的隐藏层向量,第二个元素代表所需遗忘的元素,有一个问题就是output和hidden[0]的数据维度为什么不一致??
#---------分割线----------
后续解答:output是包含所有字的语义向量,其维度为[batch_size,seq_len,hidden_size],hidden[0]代表整句话的语义向量,其维度为[1,batch_size,hidden_size]。最近在看机器翻译的相关内容,突然理解到output中每个字的语义向量就是每个时间步的向量。
4)RNN的输出和LSTM类似,同样包含output和hidden两部分,output仍然代表每个字最终的输出向量,不同之处在于hidden不再是一个元组,只有一个元素代表最后一个字的输出向量。
在实例化LSTM时需要指定模型内部结构的固有的输入层维度,隐藏层维度等参数,而在运行模型时需要指定句子长度,batch_size等参数
在实际文本分类的应用过程中存在其他一些细节问题,接下来记录使用LSTM进行文本分类的代码
import torch import torch.nn as nn import numpy as np import torch.nn.functional as F from torch.nn import CrossEntropyLoss from torch.utils.data import TensorDataset,DataLoader,SequentialSampler class model(nn.Module): def __init__(self,input_dim,hidden_dim,num_layer,num_class,batch_first = True): super(model,self).__init__() self.layer1 = nn.LSTM(input_dim,hidden_dim,num_layer) self.layer2 = nn.Linear(hidden_dim,num_class) def forward(self,inputs): layer1_output,layer1_hidden = self.layer1(inputs) layer2_output = self.layer2(layer1_output) layer2_output = layer2_output[:,-1,:]#取出一个batch中每个句子最后一个单词的输出向量即该句子的语义量!!!!!!!,layer2_output的维度是[batch_size,sequence_length,embedding_dim],layer2_output[:,-1,:]-1表示第二个维度sequence_length的最后一个数据也就是一句话中最后一个字的语义向量。 return layer2_output #-------或者使用隐藏层向量作为线性层的输入------- layer1_output,layer1_hidden = self.layer1(inputs) layer2_output = self.layer2(layer1_hidden) return layer2_output def fill_sentence(embeddings,embedding_dim): ''' 由于句子长短不一致,本函数对句子中的字转换成向量以后进行补齐(用0填补) ''' fill_embeddings = [] length = [len(embedding) for embedding in embeddings] max_len = max(length) for embedding in embeddings: if len(embedding) < max_len: fill_zero = np.zeros((max_len-len(embedding),embedding_dim)) fill_embedding = np.append(embedding,fill_zero) fill_embedding = fill_embedding.reshape(-1,embedding_dim) fill_embeddings.append(fill_embedding) else: fill_embeddings.append(embedding) return np.array(fill_embeddings) def create_dataset(tesnsor_data,tensor_label): dataset = TensorDataset(tesnsor_data,tensor_label) return dataset def create_dataloader(dataset,sampler,batch_size): dataloader = DataLoader(dataset = dataset,sampler = sampler,batch_size = batch_size) return dataloader def create_tensors(embedding_dim): data = ['今天去看展览','今天加班','中午刚睡醒','明天休息'] labels = [0,1,0,0] embeddings = [] for line in data: embeddings.append(np.random.rand(len(line),embedding_dim))#此处随机生成字向量,可以换成加载glove等训练好的词向量 new_embeddings = fill_sentence(embeddings,embedding_dim) tensor_data = torch.tensor(new_embeddings,dtype = torch.float32) tensor_label = torch.tensor(np.array(labels),dtype = torch.int64) return tensor_data,tensor_label def train(lstm_model,dataloader): loss_fun = CrossEntropyLoss() for step,batch in enumerate(dataloader): inputs = batch[0] true_labels = batch[1] model_output = lstm_model(inputs) softmax_output = F.softmax(model_output,dim=-1) loss = loss_fun(model_output,true_labels)#交叉熵损失函数的输入model_output是模型预测各类别的概率,即softmax计算后的值。 loss.backward()#先写到这里,后续再补充!! print(loss) def run(): tensors_data,tensors_label = create_tensors(5) dataset = create_dataset(tensors_data,tensors_label) sampler = SequentialSampler(dataset) dataloader = create_dataloader(dataset = dataset,sampler = sampler,batch_size = 2) lstm_model = model(input_dim = 5,hidden_dim = 20,num_layer = 1,num_class = 2) train(lstm_model,dataloader) run()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。