Pytorch实现LSTM进行文本分类实例

首先简单实现构造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()
  • 3
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值