文本情感分析(二):基于word2vec和glove词向量的文本表示

上一篇博客用词袋模型,包括词频矩阵、Tf-Idf矩阵、LSA和n-gram构造文本特征,做了Kaggle上的电影评论情感分类题。

这篇博客还是关于文本特征工程的,用词嵌入的方法来构造文本特征,也就是用word2vec词向量和glove词向量进行文本表示,训练随机森林分类器。

一、训练word2vec词向量

Kaggle情感分析题给出了三个数据集,一个是带标签的训练集,共25000条评论,一个是测试集,无标签的,用来做预测并提交结果,这两个数据集是上一篇文章里我们用过的。

此外还有一个无标签的数据集,有50000条评论,不用太可惜了。我们可以想到,用无标签的数据可以训练word2vec词向量,进行词嵌入。与词袋模型相比,word2vec词向量能解决文本表示维度过高的问题,并且把单词之间的位置信息考虑进去了。或许,用word2vec词向量进行文本表示,能取得更好的预测结果。

下面我们先用gensim训练word2vec词向量。

首先导入所需要的库。

import os,re
import numpy as np
import pandas as pd

from bs4 import BeautifulSoup
from gensim.models import word2vec

接着读取有标签的训练数据和无标签的数据,把影评合并到一个列表中。

"""读取数据,包括有标签的和无标签的数据"""

# 定义读取数据的函数
def load_dataset(name, nrows=None):
    datasets = {
        ‘unlabeled_train‘: ‘unlabeledTrainData.tsv‘,
        ‘labeled_train‘: ‘labeledTrainData.tsv‘,
        ‘test‘: ‘testData.tsv‘
    }
    if name not in datasets:
        raise ValueError(name)
    data_file = os.path.join(‘..‘, ‘data‘, datasets[name])
    df = pd.read_csv(data_file, sep=‘\t‘, escapechar=‘\\‘, nrows=nrows)
    print(‘Number of reviews: {}‘.format(len(df)))
    return df

# 读取有标签和无标签的数据
df_labeled = load_dataset(‘labeled_train‘)
df_unlabeled = load_dataset(‘unlabeled_train‘)

sentences = []

for s in df_labeled[‘review‘]:
    sentences.append(s)

for s in df_unlabeled[‘review‘]:
    sentences.append(s)

print("一共加载了",len(sentences),"条评论。")
Number of reviews: 25000
Number of reviews: 50000
一共加载了 75000 条评论。

接着进行数据预处理,处理成gensim所需要的格式。这里非常关键,我还摸索了一阵,才知道什么输入格式是正确的。

其实输入格式是这样的,假设有两篇文本,那么处理成 [ [‘with‘, ‘all‘, ‘this‘, ‘stuff‘, ‘going‘,...], [‘movie‘, ‘but‘, ‘mj‘, ‘and‘, ‘most‘,...]]的格式,每篇文本是一个列表,列表元素为单个单词。这个很容易做到,因为英文不需要进行分词,用text.split()按照空格进行切分就行。

由于word2vec依赖于上下文,而上下文有可能就是停词,所以这里选择不去停用词。

"""数据预处理,去html标签、去非字母的字符"""

eng_stopwords = {}.fromkeys([ line.rstrip() for line in open(‘../stopwords.txt‘)])

# 可以选择是否去停用词,由于word2vec依赖于上下文,而上下文有可能就是停词。
# 因此对于word2vec,我们可以不用去停词。
def clean_text(text, remove_stopwords=False):
    text = BeautifulSoup(text,‘html.parser‘).get_text()
    text = re.sub(r‘[^a-zA-Z]‘, ‘ ‘, text)
    words = text.lower().split()
    if remove_stopwords:
        words = [w for w in words if w not in eng_stopwords]
    return words

sentences = [clean_text(s) for s in sentences]
# 这里可以说是最关键的,gensim需要的格式就是把每条评论弄成[‘with‘, ‘all‘, ‘this‘, ‘stuff‘, ‘going‘,...]的格式。
# 再次强调,这里最关键,格式不对则没法学习。

现在就可以输入进去训练词向量了。

"""打印日志信息"""

import logging
logging.basicConfig(format=‘%(asctime)s : %(levelname)s : %(message)s‘, level=logging.INFO)

""""设定词向量训练的参数,开始训练词向量"""

num_features = 300      # 词向量取300维
min_word_count = 40     # 词频小于40个单词就去掉
num_workers = 4         # 并行运行的线程数
context = 10            # 上下文滑动窗口的大小
model_ = 0              # 使用CBOW模型进行训练

model_name = ‘{}features_{}minwords_{}context.model‘.format(num_features, min_word_count, context)

print(‘Training model...‘)
model = word2vec.Word2Vec(sentences, workers=num_workers,             size=num_features, min_count = min_word_count,             window = context, sg=model_)

# 保存模型
model.save(os.path.join(‘..‘, ‘models‘, model_name))

检验一下模型训练的效果,查看和 man 这个单词最相关的词,可以看到,结果还不错。

model.wv.most_similar("man")
[(‘woman‘, 0.6039960384368896),
 (‘lady‘, 0.5690498948097229),
 (‘lad‘, 0.5434065461158752),
 (‘guy‘, 0.4913134276866913),
 (‘person‘, 0.4771265387535095),
 (‘monk‘, 0.47647857666015625),
 (‘widow‘, 0.47423964738845825),
 (‘millionaire‘, 0.4719209671020508),
 (‘soldier‘, 0.4717007279396057),
 (‘men‘, 0.46545034646987915)]

二、用word2vec和glove词向量进行文本表示

好,下面分别用word2vec和glove词向量做电影评论的文本表示,再次训练随机森林分类器,看哪种词向量的效果更好。

首先导入所需要的库。

import os
import re
import numpy as np
import pandas as pd
from bs4 import BeautifulSoup

from nltk.corpus import stopwords

from gensim.models.word2vec import Word2Vec

from sklearn.ensemble import RandomForestClassifier
from sklearn import metrics 

读取训练集数据。

"""读取训练集数据"""

def load_dataset(name, nrows=None):
    datasets = {
        ‘unlabeled_train‘: ‘unlabeledTrainData.tsv‘,
        ‘labeled_train‘: ‘labeledTrainData.tsv‘,
        ‘test‘: ‘testData.tsv‘
    }
    if name not in datasets:
        raise ValueError(name)
    data_file = os.path.join(‘..‘, ‘data‘, datasets[name])
    df = pd.read_csv(data_file, sep=‘\t‘, escapechar=‘\\‘, nrows=nrows)
    print(‘Number of reviews: {}‘.format(len(df)))
    return df

df = load_dataset(‘labeled_train‘)

读取训练好的word2vec词向量,和预训练的glove词向量(需要先下载glove词向量),备用。

"""读取训练好的word2vec模型"""

model_name = ‘300features_40minwords_10context.model‘
word2vec_embedding = Word2Vec.load(os.path.join(‘..‘, ‘models‘, model_name))

"""读取glove词向量"""

glove_embedding = {}
f = open(‘../glove.6B/glove.6B.300d.txt‘, encoding=‘utf-8‘)
for line in f:
    values = line.split()
    word = values[0]
    coefs = np.asarray(values[1:], dtype=‘float32‘)
    glove_embedding[word] = coefs
f.close()

将训练集中的每条电影评论用向量表示,首先要得到每条评论中每个单词的词向量,然后把所有单词的词向量做平均,当作是句子或文本的向量表示。

于是得到电影评论的word2vec表示和golve表示。

"""数据预处理,得到单词的词向量,并得到句子的向量"""

#编码方式有一点粗暴,简单说来就是把这句话中的词的词向量做平均

eng_stopwords = set(stopwords.words(‘english‘))

# 清洗文本数据
def clean_text(text, remove_stopwords=False):
    text = BeautifulSoup(text, ‘html.parser‘).get_text()
    text = re.sub(r‘[^a-zA-Z]‘, ‘ ‘, text)
    words = text.lower().split()
    if remove_stopwords:
        words = [w for w in words if w not in eng_stopwords]
    return words

# 取word2vec词向量,或者glove词向量
def to_review_vector(review,model=‘word2vec‘):
    words = clean_text(review, remove_stopwords=True)
    if model == ‘word2vec‘:
        array = np.asarray([word2vec_embedding[w] for w in words if w in word2vec_embedding],dtype=‘float32‘)
    elif model == ‘glove‘:
        array = np.asarray([glove_embedding[w] for w in words if w in glove_embedding],dtype=‘float32‘)
    else:
        raise ValueError(‘请输入:word2vec或glove‘)
    return array.mean(axis=0)

"""word2vec表示的样本"""
train_data_word2vec = [to_review_vector(text,‘word2vec‘) for text in df[‘review‘]]

"""用glove表示的样本"""
train_data_glove = [to_review_vector(text,‘glove‘) for text in df[‘review‘]]

用word2vec表示的样本训练随机森林模型,并用包外估计作为泛化误差的评估指标。

从结果可以看到,包外估计为0.83568,之前用词频矩阵训练的模型包外估计为0.84232,所以比之前用词袋模型训练的效果差一点。

def model_eval(train_data):

    print("1、混淆矩阵为:\n")
    print(metrics.confusion_matrix(df.sentiment, forest.predict(train_data)))

    print("\n2、准确率、召回率和F1值为:\n")
    print(metrics.classification_report(df.sentiment,forest.predict(train_data)))

    print("\n3、包外估计为:\n")
    print(forest.oob_score_)

    print("\n4、AUC Score为:\n")
    y_predprob = forest.predict_proba(train_data)[:,1]
    print(metrics.roc_auc_score(df.sentiment, y_predprob))

"""用word2vec词向量表示训练模型和评估模型"""

forest = RandomForestClassifier(oob_score=True,n_estimators = 200, random_state=42)
forest = forest.fit(train_data_word2vec, df.sentiment)
print("\n====================评估以word2vec为文本表示训练的模型==================\n")
model_eval(train_data_word2vec)

再用glove词向量表示的训练集进行模型训练。很不幸,包外估计为0.78556,泛化性能比较差。

"""用glove词向量表示训练模型和评估模型"""

forest = RandomForestClassifier(oob_score=True,n_estimators = 200, random_state=42)
forest = forest.fit(train_data_glove, df.sentiment)
print("\n====================评估以glove为文本表示训练的模型==================\n")
model_eval(train_data_glove)

重新用word2vec词向量表示的样本训练分类器,进行预测,并保存预测结果。

"""重新用word2vec向量表示的样本训练模型"""
forest = RandomForestClassifier(oob_score=True,n_estimators = 200, random_state=42)
forest = forest.fit(train_data_word2vec, df.sentiment)

del df
del train_data_word2vec
del train_data_glove

"""进行预测,并保存预测结果"""
df = load_dataset(‘test‘)

test_data_word2vec = [to_review_vector(text,‘word2vec‘) for text in df[‘review‘]]

result = forest.predict(test_data_word2vec)
output = pd.DataFrame({‘id‘:df.id, ‘sentiment‘:result})
# 保存
output.to_csv(os.path.join(‘..‘, ‘data‘, ‘word2vec_model.csv‘), index=False)

三、后记

之前就用gensim训练过中文词向量,一段时间不用,连输入格式都忘记了,这次正好巩固一下。

从上面的结果可以看到,至少在这个任务中,word2vec的表现比glove要优秀。

原文地址:https://www.cnblogs.com/Luv-GEM/p/10890010.html

时间: 2024-10-10 08:14:14

文本情感分析(二):基于word2vec和glove词向量的文本表示的相关文章

主题模型及其在文本情感分析中的应用

随着Web2.0技术的出现和发展,互联网上(包括门户网站.电子商务网站.社交网站.音/视频分享网站.论坛.博客.微博等)产生了海量的.由用户发表的对于诸如人物.事件.产品等目标实体的评论信息.例如,下面这两个短文本评论:(1)“比较了多个智能手机后选择了8150,性价比还可以.另外,就是考虑到它是3.7的屏幕,大小比较合适,否则携带很不方便.”(京东商城用户,2011.11.25):(2)“我以前在杭州做二手房地产,用温州炒房客的话说:全世界房价降了,杭州的房价永远不会降,因为他们有一道坚不可摧

LSTM 文本情感分析/序列分类 Keras

LSTM 文本情感分析/序列分类 Keras 请参考 http://spaces.ac.cn/archives/3414/ neg.xls是这样的 pos.xls是这样的neg=pd.read_excel('neg.xls',header=None,index=None) pos=pd.read_excel('pos.xls',header=None,index=None) #读取训练语料完毕 pos['mark']=1 neg['mark']=0 #给训练语料贴上标签 pn=pd.concat

动手学深度学习--文本情感分析之RNN

?本分类是?然语?处理的?个常?任务,它把?段不定?的?本序列变换为?本的类别.它的?个?问题:使??本情感分类来分析?本作者的情绪.这个问题也叫情感分析,并有着?泛的应?.例如,我们可以分析?户对产品的评论并统计?户的满意度,或者分析?户对市场?情的情绪并?以预测接下来的?情. 这里将应?预训练的词向量和含多个隐藏层的双向循环神经?络,来判断?段不定?的?本序列中包含的是正?还是负?的情绪. 1.导入包和模块 1 import collections 2 import os 3 import

文本分类实战(一)—— word2vec预训练词向量

1 大纲概述 文本分类这个系列将会有十篇左右,包括基于word2vec预训练的文本分类,与及基于最新的预训练模型(ELMo,BERT等)的文本分类.总共有以下系列: word2vec预训练词向量 textCNN 模型 charCNN 模型 Bi-LSTM 模型 Bi-LSTM + Attention 模型 RCNN 模型 Adversarial LSTM 模型 Transformer 模型 ELMo 预训练模型 BERT 预训练模型 所有代码均在textClassifier仓库中, 觉得有帮助,

基于word2vec的文档向量模型的应用

基于word2vec的文档向量模型的应用 word2vec的原理以及训练过程具体细节就不介绍了,推荐两篇文档:<word2vec parameter learning explained>.和<word2vec中的数学>. 在<word2vec中的数学>中谈到了训练语言模型的一些方法:比如n-gram和神经网络.在使用神经网络训练语言模型时得到的"副产物",就是word2vec词向量.基于神经网络训练语言模型有2种方案:cbow和skip-gram,

重磅︱R+NLP:text2vec包简介(GloVe词向量、LDA主题模型、各类距离计算等)

词向量的表示主流的有两种方式,一种当然是耳熟能详的google的word2vec,还有一类就是GloVe.那么前面一类有三个开源的包,后面这一类我倒是看到得不多,恰好是在我关注了许久的一个包里面有,它就是text2vec啦.该包提供了一个强大API接口,能够很好地处理文本信息. 本包是由C++写的,流处理器可以让内存得到更好的利用,一些地方是用RcppParallel包进行并行化加乘,同时兼容各个系统的服务器.如果没有并行的地方,大家也可以自己用foreach包来自己加速. ----------

word2vec 构建中文词向量

词向量作为文本的基本结构--词的模型,以其优越的性能,受到自然语言处理领域研究人员的青睐.良好的词向量可以达到语义相近的词在词向量空间里聚集在一起,这对后续的文本分类,文本聚类等等操作提供了便利,本文将详细介绍如何使用word2vec构建中文词向量. 一.中文语料库 本文采用的是搜狗实验室的搜狗新闻语料库,数据链接 http://www.sogou.com/labs/resource/cs.php 下载下来的文件名为: news_sohusite_xml.full.tar.gz 二.数据预处理

文本情感分析(一):基于词袋模型(VSM、LSA、n-gram)的文本表示

现在自然语言处理用深度学习做的比较多,我还没试过用传统的监督学习方法做分类器,比如SVM.Xgboost.随机森林,来训练模型.因此,用Kaggle上经典的电影评论情感分析题,来学习如何用传统机器学习方法解决分类问题. 通过这个情感分析的题目,我会整理做特征工程.参数调优和模型融合的方法,这一系列会有四篇文章.这篇文章整理文本特征工程的内容. 文本的特征工程主要包括数据清洗.特征构造.降维和特征选择等. 首先是数据清洗,比如去停用词.去非字母汉字的特殊字符.大写转小写.去掉html标签等. 然后

文本情感分析的基础在于自然语言处理、情感词典、机器学习方法等内容。以下是我总结的一些资源。

词典资源:SentiWordNet<知网>中文版中文情感极性词典 NTUSD情感词汇本体下载 自然语言处理工具和平台:哈尔滨工业大学社会计算与信息检索研究中心isnowfy/snownlp · GitHub 汉语分词:自然语言处理与信息检索共享平台 NLPIR.orgfxsjy/jieba · GitHub 语料资源:信息分类与情感发现 课程:斯坦福大学自然语言处理第七课"情感分析(Sentiment Analysis)" 网站和博客:Text Classification