绿松树

搜索
查看: 112|回复: 1

十分钟搭建一个满足毕设要求的文本情感分析系统

[复制链接]

3

主题

6

帖子

12

积分

新手上路

Rank: 1

积分
12
发表于 2023-1-17 15:51:55 | 显示全部楼层 |阅读模式
摘要
本系统基于机器学习方法进行文本情感分析研究,实现对语言文本的情感分析,数据集有中英文共64475条数据,包括高兴、伤心、恶心、生气、害怕、惊讶等6中情感,分析准确率在98%以上。
先看一段demo


https://www.zhihu.com/video/1585308419980025857
1、实验流程
实验流程图:



实验流程图

具体而言,数据预处理过程包括数据清洗、分词、去停用词等;word2vec将文本训练成词向量形式;机器学习算法训练,将数据集以7:3比例划分训练集和验证集,训练集用于训练模型,验证集用于下一步骤模型验证,来测试模型效果,使用混淆矩阵、精准率、召回率、F1值来验证模型性能。
2、代码实现
先来看看数据集的样子



每一行是一条数据

前面的数据是情感标签,分别为高兴0、伤心1、恶心2、生气3、害怕4、惊讶5
首先导入需要的工具包,各工具包用途注释已经给出
from Segment_ import * #zhcnSegment自己编写的数据预处理模块,包含分词等功能
import pandas as pd # pandas、csv、numpy是读取文件或处理数组等工具包
import csv
import numpy as np
import time # 获取时间
from sklearn import svm # sklearn工具包导入支持向量机算法
from sklearn.model_selection import train_test_split #从sklearn工具包导入数据集划分工具
from sklearn.metrics import f1_score,confusion_matrix #从sklearn工具包导入评价指标:混淆矩阵和f1值
from classification_utilities import display_cm #给混淆矩阵加表头
import joblib #储存或调用模型时使用
import multiprocessing #多进程模块
import PySimpleGUI as sg #gui工具包
import gensim # 从gensim工具包中导入Word2Vec工具包
from gensim.models import Word2Vec
from gensim.models.word2vec import LineSentence
import warnings #忽略告警
warnings.filterwarnings(action='ignore', category=UserWarning, module='gensim')  1、数据预处理
def read_data():
    wds = Seg()
    # 分词后的数据集存放在data文件夹中data.seg.txt里
    target = codecs.open('./data/data.seg.txt', 'w', encoding='utf8')
    # 待分词文档导入
    with open('./data/data.txt',encoding='utf8') as f:
        lineNum = 1
        line = f.readline()
        # 逐行进行分词处理
        while line:
            seg_list = wds.cut(line, cut_all=False)
            line_seg = ' '.join(seg_list)
            target.writelines(line_seg)
            lineNum = lineNum + 1
            line = f.readline()
        f.close()
        target.close()2、训练word2vec
先定义返回特征词向量和构建文档词向量两个函数
# 返回特征词向量
def getWordVecs(wordList, model):
    vecs = []
    for word in wordList:
        word = word.replace('\n', '')
        try:
            vecs.append(model[word])
        except KeyError:
            continue
    return np.array(vecs, dtype='float')
    # 构建文档词向量
def buildVecs(filename, model):
    fileVecs = []
    with codecs.open(filename, 'rb', encoding='utf-8') as contents:
        for line in contents:      
            wordList = line.split(' ')
            vecs = getWordVecs(wordList, model)
            if len(vecs) > 0:
                vecsArray = sum(np.array(vecs)) / len(vecs)  # mean
                fileVecs.append(vecsArray)
    return fileVecs训练word2vec
# inp为输入语料, outp1 为输出模型, outp2为原始c版本word2vec的vector格式的模型
fdir = './data/'
inp = fdir + 'data.seg.txt'
outpbi = fdir + 'data.seg.text.bin'
outp1 = fdir + 'data.seg.text.model'
outp2 = fdir + 'data.seg.text.vector'
# 训练skip-gram模型
model = Word2Vec(LineSentence(inp), size=100, window=5, min_count=5,
                 workers=multiprocessing.cpu_count())
# 保存模型
model.wv.save_word2vec_format(outpbi, binary=True)
model.save(outp1)
model.wv.save_word2vec_format(outp2, binary=False)根据上面的模型 得到本数据集的文本向量
inp22 = fdir + 'data.seg.text.vector'
model22 = gensim.models.KeyedVectors.load_word2vec_format(inp22, binary=False)
Input22 = buildVecs(fdir + 'data.seg.txt', model22)
f = codecs.open('./data/data.seg.txt', mode='r', encoding='utf-8')
line = f.readlines()
data = pd.concat([df_y, df_x], axis=1)
# 将结果保存在data.csv文件里面
data.to_csv(fdir + 'data.csv')下面就是机器学习训练和验证过程了
def classification_():
    # 读取数据
    df = pd.read_csv('./data/word2vec.csv')
    # 读取标签
    y = df.iloc[:, 1]
    # 标签对应的情感
    labels = ['joy', 'sadness', 'disgust', 'anger', 'fear', 'surprise', ]
    # 读取数据
    x = df.iloc[:, 2:]
    # 将训练集划分训练、验证两部分
    X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=42)
    print('支持向量机....')
    clf = svm.SVC(C=100, probability=True)
    clf.fit(X_train, y_train)
    joblib.dump(clf, "model.m")
    print('混淆矩阵')
    cv_conf = confusion_matrix(y_test, clf.predict(X_test))
    display_cm(cv_conf, labels, display_metrics=True, hide_zeros=False)
    micro_f1 = f1_score(y_test, clf.predict(X_test), average='micro')
    macro_f1 = f1_score(y_test, clf.predict(X_test), average='macro')
    print('macro_f1', macro_f1)
    print('micro_f1', micro_f1)
    print('准确率: %.2f' % clf.score(x, y))
    print('..................................')

实验结果



识别效果不错

单条文本的识别
def predict_(a):
    inp = './data/data.seg.text.vector'
    model = gensim.models.KeyedVectors.load_word2vec_format(inp, binary=False)
    wds = Seg()
    seg_list = wds.cut(a, cut_all=False)
    line_seg = ' '.join(seg_list)
    line_seg = line_seg.split(' ')
    vecs = getWordVecs(line_seg, model)
    if len(vecs) > 0:
        vecsArray = sum(np.array(vecs)) / len(vecs)  # mean
        clf = joblib.load("model.m")
        vecsArray = vecsArray.reshape(1, 100)
        kk = clf.predict(vecsArray)
        if kk == [0]:
            return "表达开心"
        if kk == [1]:
            return "表达伤心"
        if kk == [2]:
            return "表达恶心"
        if kk == [3]:
            return "表达生气"
        if kk == [4]:
            return "表达害怕"
        if kk == [5]:
            return "表达惊喜"
    else:
        return "表达中性情感"算法部分到这就可以结束了,后面是可视化界面搭建的过程,我使用的是PySimpleGUI工具包,理由只有一个,那就是简单好用,两三个小时就能从零到入门,缺点就是界面太丑了,只能是能用,话不多说,直接看代码吧
主窗口的搭建:
def make_window(theme):
    sg.theme(theme)
    # 菜单栏
    menu_def = [['Help', ['About...', ['你好']]], ]
    # 主界面之一:文本识别界面
    News_detection = [
        [sg.Menu(menu_def, tearoff=True)],
        [sg.Text('')],
        [sg.Multiline(s=(60, 20), key='_INPUT_news_', expand_x=True)],
        [sg.Text('')],
        [sg.Text('', s=(12)), sg.Text('识别结果:', font=("Helvetica", 15)),
         sg.Text('     ', key='_OUTPUT_news_', font=("Helvetica", 15))],
        [sg.Text('')],
        [sg.Text('', s=(12)), sg.Button('识别', font=("Helvetica", 15)), sg.Text('', s=(10)),
         sg.Button('清空', font=("Helvetica", 15)),
         sg.Text('', s=(4))],
        [sg.Text('')],
        [sg.Sizegrip()]
    ]
    # 主界面之二:文本识别内容的管理,可以查看自己识别的内容
    News_management = [
        [sg.Table(values=read_table_data('./data/table_data.csv')[1:][:], headings=['文本内容', '识别时间', '识别结果'],
                  max_col_width=30,
                  auto_size_columns=True,
                  display_row_numbers=False,
                  justification='center',
                  num_rows=20,
                  alternating_row_color='LightGrey',
                  key='-TABLE_de-',
                  selected_row_colors='red on yellow',
                  enable_events=True,
                  expand_x=True,
                  expand_y=True,
                  vertical_scroll_only=False,
                  enable_click_events=True,  # Comment out to not enable header and other clicks
                  )
         ],

        [sg.Button('删除选中的结果', font=("Helvetica", 15)), sg.Button('查看识别结果', font=("Helvetica", 15))],
        [sg.Sizegrip()]
    ]
    empty = []
    layout = [[sg.MenubarCustom(menu_def, key='-MENU-', font='Courier 15', tearoff=True)],
              [sg.Text('中英文情感识别系统', size=(50, 1), justification='center', font=("Helvetica", 16),
                       relief=sg.RELIEF_RIDGE, k='-TEXT HEADING-', enable_events=True, expand_x=True)]]
    layout += [[sg.TabGroup([[
        sg.Tab(' 文 本 识 别 ', News_detection),
        sg.Tab('                                                     ', empty),
        sg.Tab(' 结 果 管 理  ', News_management,element_justification="right",)]],
                            expand_x=True, expand_y=True,font=("Helvetica", 16)),

    ]]
    window = sg.Window('中英文情感识别系统', layout,
                       right_click_menu_tearoff=True, grab_anywhere=True, resizable=True, margins=(0, 0),
                       use_custom_titlebar=True, finalize=True, keep_on_top=True)
    window.set_min_size(window.size)
    return window界面中的功能函数:
def main():
    window = make_window(sg.theme())
    while True:
        event, values = window.read(timeout=100)
        if event in (None, 'Exit'):
            print("[LOG] Clicked Exit!")
            break
        elif event == '识别':
            kk = predict_(values['_INPUT_news_'])
            time2 = time.strftime('%Y-%m-%d %H:%M:%S')
            newuser = [values['_INPUT_news_'], time2, kk]
            with open('./data/table_data.csv', 'a', newline='') as studentDetailsCSV:
                writer = csv.writer(studentDetailsCSV, dialect='excel')
                writer.writerow(newuser)
            window['_OUTPUT_news_'].update(kk)
            window["-TABLE_de-"].update(values=read_table_data('./data/table_data.csv')[1:][:])
        elif event == '清空':
            window['_OUTPUT_news_'].update(' ')
            window['_INPUT_news_'].update('')
        elif event == '查看识别结果':
            window["-TABLE_de-"].update(values=read_table_data('./data/table_data.csv')[1:][:])
        elif event == '删除选中的结果':
            data = pd.read_csv('./data/table_data.csv', encoding='gbk')
            data.drop(data.index[int(values['-TABLE_de-'][0])], inplace=True)
            # 如果想要保存新的csv文件,则为
            data.to_csv("./data/table_data.csv", index=None, encoding="gbk")
            window["-TABLE_de-"].update(values=read_table_data('./data/table_data.csv')[1:][:])
    window.close()
    exit(0)3、总结展望
在深度学习方法bert、transform方法大杀四方的时候,机器学习方法、word2vec似乎用的人很少了,但是就效果而言,传统方法也不是一无是处,深度学习是机器学习中的一种方法,了解基本的机器学习流程,对深度学习一样有帮助。
回复

使用道具 举报

2

主题

5

帖子

9

积分

新手上路

Rank: 1

积分
9
发表于 2023-1-17 15:52:21 | 显示全部楼层
您好,请问这个数据集来源于哪里呀[蹲][拜托][拜托][抱抱]
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|绿松树

GMT+8, 2025-5-10 21:40 , Processed in 0.070685 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表