基于pytorch的文本分类(使用Sentiment140数据集)

基于pytorch的文本分类(使用Sentiment140数据集)

1 独热编码和嵌入矩阵

在建立神经网络模型之前,要将单词转化为张量,常见的有独热编码(one-hot encoding)和嵌入矩阵两种形式,由于独热编码的编码机制的局限性(会使向量非常长,并且无法表达若干语义相近的单词之间的联系),因此这里使用嵌入矩阵。,调用格式如下:

embed = nn.Embedding(vocab_size,dimension_size)
#dimension_size为向量大小
#eg:
cat_mat_embed = nn.Embedding(5,2) #先创建嵌入
cat_tensor = tensor([1])  #再创建张量
cat_mat_embed.forward(cat_tensor) #将张量传入嵌入层的forward()

2 数据集获取及预处理

在网站上下载zip文件,使用里面的training.1600000.processed.noemoticon.csv

import pandas as pd
#读取数据
tweetsDF = pd.read_csv("training.1600000.processed.noemoticon.csv",engine = 'python', header = None)
#查看数据的前5行
tweetsDF.head(5)
#我们只需要最后一列的推文文本信息和第0列的类别标签信息(0代表负面情绪,2代表中立,4代表正面情绪)
#对第0列的标签进行计数,发现没有中立情绪
tweetsDF[0].value_counts()
4  800000
0  800000

#将类编码为从0开始的数字
tweetsDF['sentiment_cat'] = tweetsDF[0].astype('category')
tweetsDF['sentiment'] = tweetsDF['sentiment_cat'].cat.codes
tweetsDF.to_csv('train-processed.csv', hearder = None, index = None)

3 定义字段并建立单词表

使用torchtext处理原始csv(或JSON)文件,需要定义字段field

from torchtext import data
#定义字段
LABEL = data.LabelField()
TWEET = data.Field(tokenize = 'spacy', lower = True) #使用spacy标记工具
#如果标记太慢,可以去掉tokenize参数重新运行,这时会使用默认标记(即按空白符划分)

#生成列表,将字段映射到csv行列中
fields = [('score',None),('id',None),('date',None),('query',None),('name',None),
('tweet',TWEET),('category',None),('label',LABEL)]
twitterDataset = torchtext.data.TabularDataset(path='training-processed.csv',format
	='CSV',fields = fields, skip_header = False)
	
#划分训练、测试、和验证集
(train,test,valid) = twitterDataset.split(split_ratio = [0.8,0.1,0.1])

#建立单词表
vocab_size = 20000 #设置单词表最多包含训练集中的20000个单词
TWEET.build_vocab(train, max_size = vocab_size)

#创建数据加载器
train_iterator, valid_iterator, test_iterator = data.BucketIterator.splits(
	(train,valid,test), batch_size = 32,device = 'cuda')

4 创建模型

使用pytorch中的embedding和LSTM模块建立对推文分类的模型

import torch.nn as nn
class OurFirstLSTM(nn.module):
	def _init_(self,hidden_size,embedding_dim,vocab_size):
		super(OurFirstLSTM,self)._init_()
		self.embedding = nn.Embedding(vocab_size,embedding_dim)
		self.encoder = nn.LSTM(input_size = embedding_dim, hidden_size = 					hidden_size, num_layers = 1)
		self.predictor = nn.Linear(hidden_size,2)
		
	def forward(self,seq):
		output, (hidden,_) = self.encoder(self.embedding(seq))
		preds = self.predictor(hidden.squeeze(0))
		return preds
	
model = OurFirstLSTM(100,300,20002) 
#这里的vocab_size=20002是因为torchtext增加了两个特定的标记<unk>和<pad>,分别表示未知单词和填充
model.to(device)

5 更新训练循环

由于只有负面情绪和正面情绪两个类型的文本,即是一个二分类问题,二分类问题可以使用BCEWithLogitsLoss()损失函数,比交叉熵CrossEntropyLoss()可能更合适些

optimizer = optim.Adam(model.parameters(), lr = 2e-2)
criterion = nn.BCEWithLogitsLoss()

def train(epochs,models,optimizer,criterion,train_iterator,valid_iterator):
	for epoch in range(1,epochs+1):
		train_loss = 0.0
		valid_loss = 0.0
		model.train()
		for batch_idx, batch in enumerate(train_iterator):
			opt.zero_grad()
			predict = model(batch.tweet)
			loss = criterion(predict,batch.label)
			loss.backward()
			optimizer.step()
			training_loss += loss.data.item()*batch.tweet.size(0)
		training_loss /= len(train_iterator)
		
		model.eval()
		for batch_idx, batch in enumerate(valid_iterator):
			predict = model(batch.tweet)
			loss = criterion(predict,batch.label)
			valid_loss += loss.data.item()*batch.tweet.size(0)
		valid_loss /= len(valid_iterator)
		print('Epoch: {}, Training Loss: {:.2f}, Validation Loss: {:.2f}'.format(epoch, 				training_loss,valid_loss)) 

6 分类

这里定义一个函数完成二分类

def classify_tweet(tweet):
	categories = {0:'Negative',1:'Positive'}
	processed = TWEET.process([TWEET.preprocess(tweet)])
	return categories[model(processed).argmax().item()]
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值