关于《流浪地球》炸裂的口碑,机器学习竟然是这样评价的————Python文本情感极性分析详解(上)

  • NLP(神经语言程序学/自然语言学习)是当前机器学习领域一个重要的分支,就是用机器学习模型来理解处理人类的自然语言,并给出符合自然语言逻辑的反馈。
  • 自然语言学习中具体的工作包括,教会程序用算法来正确地提取句子的主体成分(分词),判断句子的情感色彩(情感分析)等,并基于此实现文本分类,语言翻译,自动回复等更高级功能。
  • 此文尝试建立多种NLP模型,并利用《流浪地球》影评评语作为样本数据进行训练,对比模型(情感词典模型,机器学习模型(词向量模型、MLP/多层感知机))之间的相同和差异。

一、 基于情感词典的文本情感极性分析

  • 通过情感打分的方式进行文本情感极性判断。
  • score > 0判断为正向,score < 0判断为负向。

1、数据准备

备用情感分析文档
  • 常用情感词典:词典来源于BosonNLP数据下载的情感词典 BosonNLP_sentiment_score.txt
  • 否定词词典,(自己手动构建)构建常见否定词词典 negwords_70.txt
  • 程度副词词典:《知网》情感分析用词语集(beta版)(自己手动为词打分)degreeDict.txt
  • 中文停用词 stopwords_1208.txt
情感分析词文档可以去各自专业网站下载
  • 为统一文件的读取格式,所有文件均已用utf-8编码格式存储
程度副词词典打分(手动添加)标准:
  • “极其|extreme / 最|most”级别 —2.00
  • “很|very”级别 — 1.75
  • “较|more”级别 — 1.50
  • “稍|-ish”级别 — 1.20
  • “欠|insufficiently”级别 — 0.50
  • “超|over”级别 — -1.00
# 读取样本数据信息,流浪地球_影评01.txt为随机抽取的样本
sens = []
with open('流浪地球_影评01.txt','r',
          encoding='utf-8-sig') as f:
    datas = f.readlines()
    for data in datas:
        sen = data.strip()
        sens.append(sen)
print(len(sens))
# 获取停用词列表
with open('files/stopwords_1208.txt','r',
          encoding='utf-8-sig') as f:
   stopwords = f.readlines()
print(len(stopwords))

2、数据获取与清洗

  • 获取电影影评文件
  • 获取停用词文件
  • 详细代码参见《267019条猫眼数据加持,原来你是这样的<流浪地球>
  • ——python数据分析全流程代码实现!(一)》 数据清洗部分
  • github源代码地址:https://github.com/Willsgao/Personal-projects
# 定义句子分词函数
def sent2word(sentence,stopwords):
    # 句子分词处理
    segList = jieba.cut(sentence)
    words = []
    for word in segList:
        if word not in stopwords:
            words.append(word) 
    return words

3、构建情感词典模型

3.1 将词语进行分类和定位
# 导入中文分词相关工具包
from collections import defaultdict
import os, re, codecs
import jieba
import matplotlib.pyplot as mp
# 构建分词分类模型(情感定位)
def classifyWords(words): 
    # (1) 情感词,备用情感词文件存储在files文件夹里
    senDict = defaultdict()
    with open('files/BosonNLP_sentiment_score.txt', 'r', 
              encoding='utf-8-sig') as f:
        senList = f.readlines()
    # 用评语和评分标签(二分)构建字典
    for st in senList:
        sen = st.strip().split(' ')
        if len(sen) <2:
            continue
        senDict[sen[0]] = sen[1]
    
    # (2) 否定词,files[1]为备用否定词文件名
    with open('files/negwords_70.txt', 'r',
              encoding='utf-8-sig') as f:
        negLists = f.readlines()
        # 否定词处理
        negList = []
        for neg in negLists:
            neg = neg.strip()
            if not neg:
                continue
            negList.append(neg)

    # (3) 程度副词,files[2]为备用程度副词文件名
    with open('files/degreeDict.txt','r',
              encoding='utf-8-sig') as f:
        degreeList = f.readlines()
    degreeDict = defaultdict()
    for dg in degreeList:
        degree = dg.strip().split('\t')
        degreeDict[degree[0]] = degree[1]

    
    # 情感词处理
    senWord = defaultdict()
    negWord = defaultdict()
    degreeWord = defaultdict()
    
    # 细化分词的词性感情色彩特征
    for idx,wd in enumerate(words):
        if wd in senDict.keys() and wd not in\
        negList and wd not in degreeDict.keys():
            senWord[idx] = senDict[wd]
        elif wd in negList and wd not in degreeDict.keys():
            negWord[idx] = -1
        elif wd in degreeDict.keys():
            degreeWord[idx] = degreeDict[wd]
    
    return senWord, negWord, degreeWord
3.2 计算句子感情色彩得分
  • 在此,简化的情感分数计算逻辑:所有情感词语组的分数之和
  • 得分公式:单句最后得分sen_score = (-1)^(negWord数量)x(degreeWord数量)x(句子得分)
  • 总分合计:final_score = sum(sen_score)
# 定义情感得分函数
def scoreSent(senWord, negWord, degreeWord, words):
    W = 1
    score = 0
    # 存储所有情感词位置的列表
    senLoc = list(senWord.keys())
    negLoc = list(negWord.keys())
    degreeLoc = list(degreeWord.keys())
    senloc = -1
    
    # 遍历句子中所有单词的segResult,i为单词的绝对位置
    for i in range(len(words)):
        # 如果该词为情感词
        if i in senLoc:
            # loc 为情感词位置列表的序号
            senloc += 1
            # 直接添加该情感词分数
            score += W * float(senWord[i])
            # print("score = %f"% score)
            if senloc < len(senLoc) - 1:
                # 判断该情感词与下一情感词之间是否存在否定词或程度副词
                # j为绝对位置
                for j in range(senLoc[senloc], senLoc[senloc+1]):
                    # 如果含有否定词
                    if j in negLoc:
                        W *= -1
                    # 如果含有程度副词
                    elif j in degreeLoc:
                        W *= float(degreeWord[j])
    return score
3.3 样本预处理
  • 将样本数据进行预处理,满足格式要求
# 对样本进行分词处理
scores = []
for sentence in sens:
    words = sent2word(sentence,stopwords)
    senWord, negWord, degreeWord = \
    classifyWords(words)
    score = scoreSent(senWord, 
                      negWord, degreeWord, words)
    # 为排除句子长度(分词个数)对分值的影响,进行归一化处理
    score /= len(words)
    scores.append(score)
print(len(scores))

4、数据可视化

  • 对坐标数据进行归一化处理
  • 绘制趋势变化散点图
# 以得分作为纵坐标,顺序值作为横坐标画散点图
import numpy as np
x = []
y = []
scores = sorted(scores)
min_score = min(scores)
max_score = max(scores)
wid = max_score - min_score
for idx,score in enumerate(scores):
    x.append(idx)
    y.append(float((score-min_score)/wid))
x = np.array(x)
y = np.array(y)
# 可视化代码
mp.figure('Wardering Earth Sentiment Score', facecolor='lightgray')
mp.title('Wardering Earth Sentiment Score', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
ax = mp.gca()
ax.xaxis.set_minor_locator(
    mp.MultipleLocator(20))
ax.yaxis.set_minor_locator(
    mp.MultipleLocator())
ax.grid(which='major', axis='both', linewidth=0.5,
        linestyle='--', color='orangered')
mp.scatter(x, y, c='dodgerblue')
mp.show()

在这里插入图片描述

5、情感词典模型小结

  • 1、两级的评价感情色彩比较强烈,尤其是夸赞一方;
  • 即使经过归一化处理仍能看出与均值偏差加大。
  • 2、受极值范围影响,主体评价部分评语得分较为和缓;
  • 不能准确形象地反映总体观众对电影的评价结果。
  • 3、对于正负向文本的判断,该算法忽略了很多其他的否定词、程度副词
  • 和情感词搭配的情况;用于判断情感强弱也过于简单。
  • 4、关于y轴得分与星级评价的关系需要结合具体业务分析,此处暂不处理。

该模型只能作为基础定性的评价模型

(未完待续……)
github源代码地址:
https://github.com/Willsgao/Personal-projects
参考网址:
https://www.jianshu.com/p/4cfcf1610a73
https://blog.csdn.net/chenpe32cp/article/details/77801600

  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值