TensorFlow练手项目一:使用循环神经网络(RNN)实现影评情感分类

本文介绍使用TensorFlow实现影评情感分类的RNN模型,涵盖数据预处理、模型构建、训练及验证过程,探讨了RNN在序列数据上的优势,并分享了项目GitHub链接。
摘要由CSDN通过智能技术生成

使用循环神经网络(RNN)实现影评情感分类

作为对循环神经网络的实践,我用循环神经网络做了个影评情感的分类,即判断影评的感情色彩是正面的,还是负面的。

选择使用RNN来做情感分类,主要是因为影评是一段文字,是序列的,而RNN对序列的支持比较好,能够“记忆”前文。虽然可以提取特征词向量,然后交给传统机器学习模型或全连接神经网络去做,也能取得很好的效果,但只从端对端的角度来看的话,RNN无疑是最合适的。

以下介绍实现过程。

转载请注明出处:https://blog.csdn.net/aaronjny/article/details/79561115

一、数据预处理

本文中使用的训练数据集为https://www.cs.cornell.edu/people/pabo/movie-review-data/上的sentence polarity dataset v1.0,包含正负面评论各5331条。可以点击进行下载。

数据下载下来之后需要进行解压,得到rt-polarity.negrt-polarity.pos文件,这两个文件是Windows-1252编码的,先将它转成unicode处理起来会更方便。

补充一下小知识,当我们打开一个文件,发现乱码,却又不知道该文件的编码是什么的时候,可以使用python
chardet类库进行判断,这里的Windows-1252就是使用该类库检测出来的。

在数据预处理部分,我们要完成如下处理过程:

1.转码

即将文件转为unicode编码,方便我们后续操作。读取文件,转换编码,重新写入到新文件即可。不存在技术难点。

2.生成词汇表

读取训练文件,提取出所有的单词,并统计各个单词出现的次数。为了避免低频词的干扰,同时减少模型参数,我们只保留部分高频词,比如这里我只保存出现次数前9999个,同时将低频词标识符<unkown>加入到词汇表中。

3.借助词汇表将影评转化为词向量

单词是没法直接输入给模型的,所以我们需要将词汇表中的每个单词对应于一个编号,将影评数据转化成词向量。方便后面生成词嵌入矩阵。

4.填充词向量并转化为np数组

因为不同评论的长度是不同的,我们要组成batch进行训练,就需要先将其长度统一。这里我选择以最长的影评为标准,对其他较短的影评的空白部分进行填充。然后将其转化成numpy的数组。

5.按比例划分数据集

按照机器学习的惯例,数据集应被划分为三份,即训练集、开发集和测试集。当然,有时也会只划分两份,即只包括训练集和开发集。

这里我划分成三份,训练集、开发集和测试集的占比为[0.8,0.1,0.1]。划分的方式为轮盘赌法,在numpy中可以使用cumsumsearchsorted来简洁地实现轮盘赌法。

6.打乱数据集,写入文件

为了取得更好的训练效果,将数据集随机打乱。为了保证在训练和模型调整的过程中训练集、开发集、测试集不发生改变,将三个数据集写入到文件中,使用的时候从文件中读取。

下面贴上数据预处理的代码,注释写的很细,就不多说了。

# -*- coding: utf-8 -*-
# @Time    : 18-3-14 下午2:28
# @Author  : AaronJny
# @Email   : Aaron__7@163.com
import sys

reload(sys)
sys.setdefaultencoding('utf8')
import collections
import settings
import utils
import numpy as np


def create_vocab():
    """
    创建词汇表,写入文件中
    :return:
    """
    # 存放出现的所有单词
    word_list = []
    # 从文件中读取数据,拆分单词
    with open(settings.NEG_TXT, 'r') as f:
        f_lines = f.readlines()
        for line in f_lines:
            words = line.strip().split()
            word_list.extend(words)
    with open(settings.POS_TXT, 'r') as f:
        f_lines = f.readlines()
        for line in f_lines:
            words = line.strip().split()
            word_list.extend(words)
    # 统计单词出现的次数
    counter = collections.Counter(word_list)

    sorted_words = sorted(counter.items(), key=lambda x: x[1], reverse=True)
    # 选取高频词
    word_list = [word[0] for word in sorted_words]

    word_list = ['<unkown>'] + word_list[:settings.VOCAB_SIZE - 1]
    # 将词汇表写入文件中
    with open(settings.VOCAB_PATH, 'w') as f:
        for word in word_list:
            f.write(word + '\n')


def create_vec(txt_path, vec_path):
    """
    根据词汇表生成词向量
    :param txt_path: 影评文件路径
    :param vec_path: 输出词向量路径
    :return:
    """
    # 获取单词到编号的映射
    word2id = utils.read_word_to_id_dict()
    # 将语句转化成向量
    vec = []
    with open(txt_path, 'r') as f:
        f_lines = f.readlines()
        for line in f_lines:
            tmp_vec = [str(utils.get_id_by_word(word, word2id)) for word in line.strip().split()]
            vec.append(tmp_vec)
    # 写入文件中
    with open(vec_path, 'w') as f:
        for tmp_vec in vec:
            f.write(' '.join(tmp_vec) + '\n')


def cut_train_dev_test():
    """
    使用轮盘赌法,划分训练集、开发集和测试集
    打乱,并写入不同文件中
    :return:
    """
    # 三个位置分别存放训练、开发、测试
    data = [[], [], []]
    labels = [[], [], []]
    # 累加概率 rate [0.8,0.1,0.1]  cumsum_rate [0.8,0.9,1.0]
    rate = np.array([settings.TRAIN_RATE, settings.DEV_RATE, settings.TEST_RATE])
    cumsum_rate = np.cumsum(rate)
    # 使用轮盘赌法划分数据集
    with open(settings.POS_VEC, 'r') as f:
        f_lines = f.readlines()
        for line 
  • 19
    点赞
  • 118
    收藏
    觉得还不错? 一键收藏
  • 29
    评论
评论 29
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值