0


【自然语言处理(NLP)】基于FNN网络的电影评论情感分析

【自然语言处理(NLP)】基于FNN网络的电影评论情感分析


在这里插入图片描述


作者简介:在校大学生一枚,华为云享专家,阿里云专家博主,腾云先锋(TDP)成员,云曦智划项目总负责人,全国高等学校计算机教学与产业实践资源建设专家委员会(TIPCC)志愿者,以及编程爱好者,期待和大家一起学习,一起进步~
.
博客主页:ぃ灵彧が的学习日志
.
本文专栏:人工智能
.
专栏寄语:若你决定灿烂,山无遮,海无拦
.
在这里插入图片描述

文章目录


前言

(一)、任务描述

传统的文本分类模型一般根据文本的内容人工地构造特征,而人工构建特征存在考虑片面、浪费人力等现象。

本实践使用基于前馈神经网络(FNN)的电影评论情感分析模型,将电影评论文本中的情感极性向量化,通过前馈神经网络的学习训练来挖掘表示文本深层的特征,避免了特征构建的问题,并能发现那些不容易被人发现的特征,从而产生更好的效果。

在这里插入图片描述


(二)、环境配置

本实践代码运行的环境配置如下:Python版本为3.7,PaddlePaddle版本为2.0.0,操作平台为AI Studio。大部分深度学习项目都要经过以下几个过程:数据准备、模型配置、模型训练、模型评估。

import paddle
import numpy as np
import matplotlib.pyplot as plt
print(paddle.__version__)# cpu/gpu环境选择,在 paddle.set_device() 输入对应运行设备。# device = paddle.set_device('gpu')

一、IMDB数据准备

IMDB数据集是一个对电影评论标注为正向评论与负向评论的数据集,共有25000条文本数据作为训练集,25000条文本数据作为测试集。
该数据集的官方地址为:

http://ai.stanford.edu/~amaas/data/sentiment/

print('loading dataset...')
train_dataset = paddle.text.datasets.Imdb(mode='train')
test_dataset = paddle.text.datasets.Imdb(mode='test')print('loading finished')

部分输出如下图1所示:

在这里插入图片描述

train_dataset.docs[0]

部分输出如下图2所示:

在这里插入图片描述

构建了训练集与测试集后,可以通过 word_idx 获取数据集的词表。在飞桨框架2.0版本中,推荐使用padding的方式来对同一个batch中长度不一的数据进行补齐,所以在字典中,我们还会添加一个特殊的词,用来在后续对batch中较短的句子进行填充。

word_dict = train_dataset.word_idx

# add a pad token to the dict for later padding the sequence
word_dict['<pad>']=len(word_dict)for k inlist(word_dict)[:10]:print("{}:{}".format(k.decode('ASCII'), word_dict[k]))print("...")for k inlist(word_dict)[-5:]:print("{}:{}".format(k ifisinstance(k,str)else k.decode('ASCII'), word_dict[k]))print("totally {} words".format(len(word_dict)))

输出结果如下图3所示:

在这里插入图片描述


(一)、参数设置

在这里我们设置一下词表大小,

embedding

的大小,

batch_size

等等

vocab_size =len(word_dict)+1
emb_size =256
seq_len =200
batch_size =32
epochs =2
pad_id = word_dict['<pad>']

classes =['negative','positive']defids_to_str(ids):
    words =[]for k in ids:
        w =list(word_dict)[k]
        words.append(w ifisinstance(w,str)else w.decode('ASCII'))return" ".join(words)

在这里,取出一条数据打印出来看看,可以用 docs 获取数据的list,用 labels 获取数据的label值,打印出来对数据有一个初步的印象。

# 取出来第一条数据看看样子。
sent = train_dataset.docs[0]
label = train_dataset.labels[1]print('sentence list id is:', sent)print('sentence label id is:', label)print('--------------------------')print('sentence list is: ', ids_to_str(sent))print('sentence label is: ', classes[label])

输出结果如图4所示:

在这里插入图片描述


(二)、用padding的方式对齐数据

文本数据中,每一句话的长度都是不一样的,为了方便后续的神经网络的计算,常见的处理方式是把数据集中的数据都统一成同样长度的数据。这包括:对于较长的数据进行截断处理,对于较短的数据用特殊的词进行填充。接下来的代码会对数据集中的数据进行这样的处理。

defcreate_padded_dataset(dataset):
    padded_sents =[]
    labels =[]for batch_id, data inenumerate(dataset):
        sent, label = data[0], data[1]
        padded_sent = np.concatenate([sent[:seq_len],[pad_id]*(seq_len -len(sent))]).astype('int32')
        padded_sents.append(padded_sent)
        labels.append(label)return np.array(padded_sents), np.array(labels)

train_sents, train_labels = create_padded_dataset(train_dataset)
test_sents, test_labels = create_padded_dataset(test_dataset)print(train_sents.shape)print(train_labels.shape)print(test_sents.shape)print(test_labels.shape)for sent in train_sents[:3]:print(ids_to_str(sent))

(三)、用Dataset 与 DataLoader 加载

将前面准备好的训练集与测试集用Dataset 与 DataLoader封装后,完成数据的加载。

classIMDBDataset(paddle.io.Dataset):def__init__(self, sents, labels):
        self.sents = sents
        self.labels = labels
    
    def__getitem__(self, index):
        data = self.sents[index]
        label = self.labels[index]return data, label

    def__len__(self):returnlen(self.sents)
    
train_dataset = IMDBDataset(train_sents, train_labels)
test_dataset = IMDBDataset(test_sents, test_labels)

train_loader = paddle.io.DataLoader(train_dataset, return_list=True,
                                    shuffle=True, batch_size=batch_size, drop_last=True)
test_loader = paddle.io.DataLoader(test_dataset, return_list=True,
                                    shuffle=True, batch_size=batch_size, drop_last=True)

二、模型配置

本示例中,我们将会使用一个不考虑词的顺序的BOW的网络,在查找到每个词对应的embedding后,简单的取平均,作为一个句子的表示。然后用

Linear

进行线性变换。为了防止过拟合,我们还使用了

Dropout

classMyNet(paddle.nn.Layer):def__init__(self):super(MyNet, self).__init__()
        self.emb = paddle.nn.Embedding(vocab_size, emb_size)
        self.fc = paddle.nn.Linear(in_features=emb_size, out_features=2)
        self.dropout = paddle.nn.Dropout(0.5)defforward(self, x):
        x = self.emb(x)
        x = paddle.mean(x, axis=1)
        x = self.dropout(x)
        x = self.fc(x)return x

三、模型训练

代码1:

defdraw_process(title,color,iters,data,label):
    plt.title(title, fontsize=24)
    plt.xlabel("iter", fontsize=20)
    plt.ylabel(label, fontsize=20)
    plt.plot(iters, data,color=color,label=label) 
    plt.legend()
    plt.grid()
    plt.show()

代码2

deftrain(model):
    model.train()
    opt = paddle.optimizer.Adam(learning_rate=0.001, parameters=model.parameters())
    steps =0
    Iters, total_loss, total_acc =[],[],[]for epoch inrange(epochs):for batch_id, data inenumerate(train_loader):
            steps +=1
            sent = data[0]
            label = data[1]
            
            logits = model(sent)
            loss = paddle.nn.functional.cross_entropy(logits, label)
            acc = paddle.metric.accuracy(logits, label)if batch_id %500==0:
                Iters.append(steps)
                total_loss.append(loss.numpy()[0])
                total_acc.append(acc.numpy()[0])print("epoch: {}, batch_id: {}, loss is: {}".format(epoch, batch_id, loss.numpy()))
            
            loss.backward()
            opt.step()
            opt.clear_grad()# evaluate model after one epoch
        model.eval()
        accuracies =[]
        losses =[]for batch_id, data inenumerate(test_loader):
            
            sent = data[0]
            label = data[1]

            logits = model(sent)
            loss = paddle.nn.functional.cross_entropy(logits, label)
            acc = paddle.metric.accuracy(logits, label)
            
            accuracies.append(acc.numpy())
            losses.append(loss.numpy())
        
        avg_acc, avg_loss = np.mean(accuracies), np.mean(losses)print("[validation] accuracy: {}, loss: {}".format(avg_acc, avg_loss))
        
        model.train()
    
        paddle.save(model.state_dict(),str(epoch)+"_model_final.pdparams")
    
    draw_process("trainning loss","red",Iters,total_loss,"trainning loss")
    draw_process("trainning acc","green",Iters,total_acc,"trainning acc")
        
model = MyNet()
train(model)

输出结果如下图5、6所示:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


四、模型评估

'''
模型评估
'''
model_state_dict = paddle.load('model_final.pdparams')
model = MyNet()
model.set_state_dict(model_state_dict) 
model.eval()
accuracies =[]
losses =[]for batch_id, data inenumerate(test_loader):
    
    sent = data[0]
    label = data[1]

    logits = model(sent)
    loss = paddle.nn.functional.cross_entropy(logits, label)
    acc = paddle.metric.accuracy(logits, label)
    
    accuracies.append(acc.numpy())
    losses.append(loss.numpy())

avg_acc, avg_loss = np.mean(accuracies), np.mean(losses)print("[validation] accuracy: {}, loss: {}".format(avg_acc, avg_loss))

输出结果如下图7所示:

在这里插入图片描述


五、模型预测

defids_to_str(ids):
    words =[]for k in ids:
        w =list(word_dict)[k]
        words.append(w ifisinstance(w,str)else w.decode('ASCII'))return" ".join(words)

label_map ={0:"negative",1:"positive"}

model_state_dict = paddle.load('model_final.pdparams')
model = MyNet()
model.set_state_dict(model_state_dict) 
model.eval()for batch_id, data inenumerate(test_loader):
    
    sent = data[0]
    results = model(sent)

    predictions =[]for probs in results:# 映射分类label
        idx = np.argmax(probs)
        labels = label_map[idx]
        predictions.append(labels)for i,pre inenumerate(predictions):print(' 数据: {} \n 情感: {}'.format(ids_to_str(sent[0]), pre))breakbreak

输出结果如下图8所示:

在这里插入图片描述


总结

本系列文章内容为根据清华社出版的《自然语言处理实践》所作的相关笔记和感悟,其中代码均为基于百度飞桨开发,若有任何侵权和不妥之处,请私信于我,定积极配合处理,看到必回!!!

最后,引用本次活动的一句话,来作为文章的结语~( ̄▽ ̄~)~:

学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。

ps:更多精彩内容还请进入本文专栏:人工智能,进行查看,欢迎大家支持与指教啊~( ̄▽ ̄~)~

在这里插入图片描述


本文转载自: https://blog.csdn.net/m0_54754302/article/details/127458532
版权归原作者 ぃ灵彧が 所有, 如有侵权,请联系我们删除。

“【自然语言处理(NLP)】基于FNN网络的电影评论情感分析”的评论:

还没有评论