ML-情感分析1-使用W2V与SVM进行情感分析


前言

情感分析是当前比较火热的自然语言处理领域,当前情感分析主要有三种方式,第一种使用情感词典进行情感分析,第二种是使用机器学习的方式进行情感分析,最后一种是综合前两种方式进行分析。本篇文章主要介绍如何使用机器学习的方式来解决情感分析问题。需要涉及到SVM(支持向量机)、PCA和Word2Vec的相关知识,如果读者还有什么不了解的话可以自行搜索学习。简单来说可以将SVM理解成一个分类器,区分正面和负面情绪。PCA(主成分分析法)可以理解成是一个告诉你哪些输入特征更加重要的算法,Word2Vec是一个可以将文字转换为机器可理解的向量的算法。希望这篇文章可以让读者简单了解情感分析过程中需要考虑的几个基本步骤

获取训练语料

作者在这里使用的是一个携程酒店正面负面评论的语料库,有3000条负面评论和7000条正面评论。可以从CSDN上面下载。如果您实在找不到下载资源可以从文末的给出的链接中下载。 同时我们还需要获取一个停用词表,这里我选择使用了中科院提供的一个停用词表

预处理语料

我们刚刚获得的语料格式如下:


负面共有3000个txt,正面共有7000个txt。需要注意的是,作者在实际编码的过程中发现这些文件并不是UTF-8,因此我们首先需要将这些文件处理成utf-8的格式,方便接下来的操作。

import os

class DecodeRes:  
    """
    将原始数据重新编码成UTF-8
    """
    def decodeNeg2UTF8(self):
        for i in range(0, 7000):
            with open("../datas/pos/pos.{0}.txt".format(i), 'r', errors='ignore') as f:
                content = f.read().strip()
                with open('../datas/pos/pos{0}.txt'.format(i), 'w', encoding='utf-8') as new_file:
                    new_file.write(content)
                    print(content)
            os.remove('../datas/pos/pos.{0}.txt'.format(i))

    def decodePos2UTF8(self):
        for i in range(0, 3000):
            with open("../datas/neg/neg.{0}.txt".format(i), 'r', errors='ignore') as f:
                content = f.read().strip()
                with open('../datas/neg/neg{0}.txt'.format(i), 'w', encoding='utf-8') as new_file:
                    new_file.write(content)
                    print(content)
            os.remove('../datas/neg/neg.{0}.txt'.format(i))

接下来我们需要清洗数据,即清除文本中的特殊字符、英文字符、标点和数字等。

    def clean(self,string):
        """
        清洗特殊符号、标点符号、大写字母、小写字母、数字
        :param string:
        :return:
        """
        string = re.sub("[\s+\.\!\/_,$%^*(+\"\']+|[+——!,。?、~@#¥%……&*();]+|[A-Z]+|[a-z]+|[0-9]", "", string)
        return string

清洗结束之后我们就可以对文本进行分词操作了,这里需要说一下常用的英文自然语言处理工具如NLTK、Stanford NLP Core等都不支持中文分词,不过别担心,国内有很多好用的工具可以对中文进行分词,常用的就是jieba分词,是GitHub上一个开源工具,安装很简单,详见Github页面

        seg = jieba.cut(content, cut_all=False)
        s = '-'.join(seg)
        seg_list = s.split('-')

下面我们需要去除停用词、那么什么是停用词呢?主要指的是一些对情感分析没有太多帮助的常见的无实际意义的词,比如说“的”。

    def clean_detected_words(self,cutted_list):
        """
        清除停用词
        :param cutted_list:
        :return:
        """
        detected_list = []
        with open('../datas/Detected_words_ZH.txt','r',encoding='utf-8',errors='ignore') as f:
            detected_list = f.readlines()

        #下面2行代码的含义是删除最后的\n符号
        for i in range(0,len(detected_list)):
            detected_list[i] = detected_list[i][:-1]

        detected_dics = {}.fromkeys(detected_list,1)
        result = []
        for cutted in cutted_list:
            if cutted not in detected_dics:
                result.append(cutted)
        return result

训练词向量

这里使用Word2Vec算法进行向量化的操作,如何使用Word2Vec可以参见我的这篇文章

def buildVecs(filename, model,debug):  
    """
    输入文件名,首先进行数据清洗,然后利用word2vec获得他们的向量化表示,
    :param filename:
    :param model:
    :return:
    """
    with open(filename, 'r',encoding='utf-8',errors='ignore') as f:
        # print txtfile
        content = f.read().replace("\n", '').strip()
        cleaner = CleanDatas.CleanDatas()
        content = cleaner.clean(content)
        seg = jieba.cut(content, cut_all=False)
        s = '-'.join(seg)
        seg_list = s.split('-')
        if len(cleaner.clean_detected_words(seg_list)) > 0:
            seg_list = cleaner.clean_detected_words(seg_list)
        result = []
        for i in seg_list:
            if i in model:
                result.append(model[i])
        array_mean=0.0
        if len(result) != 0:
            array_mean = sum(np.array(result))/len(result)
        else:
            print(debug)
        return array_mean

标准化

# standardization
X = scale(X)  

向量降维

我们使用word2vec算法训练出的向量都是400维的,其实这其中有很多维度对于最终的结果影响并不大,我们可以适当的删除一些从而提高效率和准确率。这里使用的方法是PCA(主成分分析法),如果您还不了解,可以看看这篇文章。这里使用的是sklearn工具包中的PCA组件,sklearn的安装也是十分简单,您可以直接在网络上搜索。

#无监督使用PCA训练X
pca = PCA(n_components=400)  
pca.fit(X)  
#创建图表并指定图表大小
# figsize: w,h tuple in inches
plt.figure(1, figsize=(4, 3))  
plt.clf()  
plt.axes([.2, .2, .7, .7])  
plt.plot(pca.explained_variance_, linewidth=2)  
plt.axis('tight')  
plt.xlabel('n_components')  
plt.ylabel('explained_variance_')  
plt.show()  

可以得到下图:


PCA算法会自动根据特征的重要性重新排序,我们可以看到重新排序之后的前100维度数据基本可以涵盖所有的信息了,所以我们就可以降维到100维。

#由图知我们保留前100维的数据
X_reduced = PCA(n_components = 100).fit_transform(X)  

训练SVM模型

在训练前我们需要简单的将数据分成训练集和测试集。

#分割训练集和测试集,选取500负和1000正作为测试集
X_reduced_train = X_reduced[0:2500]  
X_reduced_train = np.concatenate((X_reduced_train,X_reduced[3000:9000]))  
y_reduced_train = Y[0:2500]  
y_reduced_train = np.concatenate((y_reduced_train,Y[3000:9000]))  
X_reduced_test = X_reduced[2500:3000]  
X_reduced_test = np.concatenate((X_reduced_test,X_reduced[9000:10000]))  
y_reduced_test = Y[2500:3000]  
y_reduced_test = np.concatenate((y_reduced_test,Y[9000:10000]))  

使用sklearn中是SVM模块,核函数选用线性函数。

#构建SVM模型
clf = SVC(C = 2, probability = True, kernel='linear')

clf.fit(X_reduced_train, y_reduced_train)  
print('Test Accuracy: %.5f'% clf.score(X_reduced_test, y_reduced_test))

print("test:")  
print(clf.predict(X_reduced_test))  
print("value:")  
print(y_reduced_test)  

这样一来我们的程序便可以运行,最后会输出准确率。

参考文章与资源

Python做文本情感分析之情感极性分析
中文情感挖掘酒店语料 密码:97gq
停用词表 密码:mhuo


分享博文


评论博文


Last one :   ML-情感分析2-使用向量空间模型与SVM进行情感分析

Next article :   ML-训练自己的Word2Vec模型