当前位置:   article > 正文

Pytorch实现LSTM进行文本分类实例_pytorch lstm文本分类 rnn

pytorch lstm文本分类 rnn

首先简单实现构造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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

个人疑惑小结:
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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/118772
推荐阅读
相关标签
  

闽ICP备14008679号