RNN文本情感分类

1. 实验目的

通过动手进行模型构建深入理解RNN模型的原理和结构,学习RNN用于NLP任务,以及模型优化方法。

2. 实验平3. 实验内容

      1. 实验目的

通过动手进行模型构建深入理解RNN模型的原理和结构,学习RNN用于NLP任务,以及模型优化方法。

2. 实验平台

操作系统:Windows 2000/ XP/7/8/10/11 或者 Linux

深度学习框架:pytorch,tensorflow, keras等

3. 实验内容

    任务:属性级的文本情感分类任务。如句子为“这家餐厅很喜欢,味道很好,就是卫生不太行”,给定属性“味道”,情感类别为positive,给定属性“卫生”,情感类别为negative(负类,或类别标签为-1)。若无明显情感倾向,则为中性类别neutral(0)。

    方法:使用一个GRU(或LSTM)模型完成情感分类。模型定义为一个继承nn.Module的类,可以直接引用torch.nn中的GRU模块。如使用双向循环,需要设置bidirectional=True,注意此时隐藏状态维度应该是单向的2倍。属性的利用方式可以参考课件,也可以自行设计。

  • 输入层是文本的预训练词向量的序列。一个batch内的文本要进行padding,maxlen可以选择当前batch内的最大文本长度,或者自行设置一个合适的值。输出维度=hidden_size
  • 隐藏层由GRU单元构成,输入维度和输出维度=hidden_size。
  • 可以使用torch.nn.Dropout添加dropout,缓解模型过拟合
  • 输出层输入维度= hidden_size,使用softmax输出单元,输出维度=类别数。

    损失函数使用交叉熵,即criterion = nn.CrossEntropyLoss()

【数据集】SemEval2014 Restaurants数据集修改得到。句子文本:text,属性只需要读取aspectTerms中的属性项。例子中id=457的句子考虑属性dinner,id=1306的句子无属性,则该条样本忽略。Id=3086的句子考虑属性drinks和place,形成两条样本。

读取代码可参考:

import xml.etree.ElementTree as ET

tree = ET.parse('train.xml')

root = tree.getroot()

for sent in root.findall('sentence'):

    title = sent.find('text').text

    for child in sent:

        if child.tag == 'aspectTerms':

            for term in child:

                aspect, polarity = term.attrib['term'], term.attrib['polarity']

【词向量】实验2给出的某个100维预训练词向量

(1)请说明具体参数设置

(2)统计准确率(accuracy)、精确率(precision)、召回率(recall)、宏F1值。

实验

accuracy

precision

recall

F1

属性级分类

感兴趣的同学也可以尝试对比单层、多层、单向、多向网络的结果。

(3)对实验结果进行解释,为什么某种模型更好,分析可能的原因。

类似项目参考:

代码实践:基于LSTM网络的DEAP情感数据集情感分类_deapdataset-CSDN博客

https://blog.csdn.net/m0_63642362/article/details/124335408

一、实验环境

操作系统:Windows 10

深度学习框架:pytorch

二、实验内容及详细的完成情况

(1)读取数据

读取aspectTerms中的属性项,若无属性,忽略该样本。若有多个属性,则建立多个样本,将情感分级分别使用0(中立),1(positive),2(negative)表示。

  1. def load_data(file_path):  
  2.     dataset = []  
  3.     tree = ET.parse(file_path)  
  4.     root = tree.getroot()  
  5.     for sent in root.findall('sentence'):  
  6.         text = sent.find('text').text  
  7.         for child in sent:  
  8.             if child.tag == 'aspectTerms':  
  9.                 for term in child:  
  10.                     aspect, polarity = term.attrib['term'], term.attrib['polarity']  
  11.                     if polarity == 'positive':  
  12.                         sentiment = 1  
  13.                     elif polarity == 'negative':  
  14.                         sentiment = 2  
  15.                     else:  
  16.                         sentiment = 0  # Neutral  
  17.                     dataset.append((text, aspect, sentiment))  
  18.     return dataset  

(2)数据处理

1.将情感取向转变为tensor格式,以便后续模型训练处理。

2.将文本(test)按空格分成一个个token,再转为词向量(Glove)(每个token 100维),并将每条文本长度固定位100个token,多切少补,以便size统一,方便处理。最后将text转成的嵌入embeddings转成tensor。

  1. def preprocess_text(text, maxlen=100):  
  2.     tokens = text.split()  
  3.     embeddings = [torch.from_numpy(word_embeddings[token]) if token in word_embeddings else torch.zeros_like(torch.from_numpy((word_embeddings['the']))) for token in tokens]  
  4.     if len(embeddings) > maxlen:  
  5.         embeddings = embeddings[:maxlen]  
  6.     elif len(embeddings) < maxlen:  
  7.         embeddings.extend([torch.zeros_like(torch.from_numpy((word_embeddings['the'])))] * (maxlen - len(embeddings)))  
  8.     return torch.stack(embeddings)  

(3)参数设置

input_size=100

hidden_size=128(hidden_size * 2 if bidirectional)双向循环,隐藏层数乘二

output_size=3  (总共三个输出类别:积极,中立,消极)

batch_size=32

optimizer = optim.Adam(model.parameters(), lr=0.001) #优化器

criterion = nn.CrossEntropyLoss()  # 交叉熵损失函数

num_epochs = 10

(4)GRU模型

使用GRU模型完成情感分类。使用单向循环和双向循环(设置bidirectional=True)

测试结果↓

单向循环:

双向循环:

通过对比可以看出,GRU模型是否设置双向循环,训练出来的结果其实差异不大,甚至单项的效果还稍微好一些。

通过查询资料,我得知,GRU模型的双向循环和单向循环在精度上有差异可能是由于几个原因造成的:

1.信息流动方向不同:双向循环通过两个方向的信息流动,理论上可以更全面地捕捉序列数据中的信息,但这也可能导致模型更复杂,训练难度增加。

2.参数数量增加:双向模型需要更多的参数来处理正向和反向的信息,如果训练数据不足或者模型复杂度过高,可能会导致过拟合或者训练困难。

3.训练过程不稳定:双向模型可能在训练过程中更容易出现梯度消失或者梯度爆炸的问题,需要更谨慎的参数初始化和调整学习率等超参数。

4.数据特性:某些数据集可能更适合单向模型,因为信息的重要性更多集中在正向或者反向流动中。

因此我猜测,可能是因为我只训练了10轮,可能出现了过拟合或者没有很好的训练模型导致的。

三、实验总结

(可以总结实验中出现的问题以及解决的思路,也可以列出没有解决的问题)

  1. 报错:RuntimeError: each element in list of batch should be of equal size

这个错误通常发生在数据加载过程中,提示批次中的元素大小不一致。这可能是由于在构建数据集对象时,某些句子的长度超过了指定的最大长度,而某些句子没有达到maxlen,导致在构建批次时出现不一致的情况。

于是采用统一为100token的方式来解决该问题。

2.模型训练过程中,需要所有数字,数组,矩阵等都是tensor格式,需要在导入数据时就对其(词向量,情感倾向)进行处理。

  • 22
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是使用RNN实现情感分类的代码示例: ``` import numpy as np import pandas as pd import tensorflow as tf from tensorflow.keras.preprocessing.text import Tokenizer from tensorflow.keras.preprocessing.sequence import pad_sequences from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Embedding, LSTM, SpatialDropout1D from sklearn.model_selection import train_test_split # 读取数据集 data = pd.read_csv('sentiment_analysis.csv') data = data[['text', 'sentiment']] data = data[data.sentiment != "Neutral"] data['text'] = data['text'].apply(lambda x: x.lower()) data['text'] = data['text'].apply((lambda x: re.sub('[^a-zA-z0-9\s]', '', x))) # 获取文本和标签 texts = data['text'].values labels = pd.get_dummies(data['sentiment']).values # 对文本进行分词,并将每个词转换为数字 tokenizer = Tokenizer(num_words=2000, split=' ') tokenizer.fit_on_texts(texts) X = tokenizer.texts_to_sequences(texts) X = pad_sequences(X) # 划分数据集 X_train, X_test, Y_train, Y_test = train_test_split(X, labels, test_size=0.33, random_state=42) # 构建RNN模型 embed_dim = 128 lstm_out = 196 model = Sequential() model.add(Embedding(2000, embed_dim, input_length=X.shape[1])) model.add(SpatialDropout1D(0.4)) model.add(LSTM(lstm_out, dropout=0.2, recurrent_dropout=0.2)) model.add(Dense(3, activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) # 训练模型 batch_size = 32 model.fit(X_train, Y_train, epochs=10, batch_size=batch_size, verbose=2) # 评估模型 score, acc = model.evaluate(X_test, Y_test, verbose=2, batch_size=batch_size) print("score: %.2f" % (score)) print("acc: %.2f" % (acc)) ``` 在这个示例中,我们首先读取数据集并对文本进行预处理。然后,我们使用Tokenizer将文本转换为数字,并使用pad_sequences将每个序列填充到相同的长度。然后,我们将数据集划分为训练集和测试集。 接下来,我们构建RNN模型。我们使用Embedding层将每个数字转换为向量,然后添加SpatialDropout1D层和LSTM层。最后,我们添加一个Dense层,并使用softmax激活函数对输出进行分类。我们使用categorical_crossentropy作为损失函数,使用adam优化器进行训练,并使用accuracy作为评估指标。 最后,我们训练模型并评估其性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值