[python人工智能]三十一.keras实现bilstm微博情感分类和lda主题挖掘分析(上)(代码片段)

Eastmount Eastmount     2023-01-08     526

关键词:

从本专栏开始,作者正式研究Python深度学习、神经网络及人工智能相关知识。前一篇文章通过Keras深度学习构建CNN模型识别阿拉伯手写文字图像,一篇非常经典的图像分类文字。这篇文章将结合文本挖掘介绍微博情感分类知识,包括数据预处理、机器学习和深度学习的情感分类,后续结合LDA进行主题挖掘。基础性文章,希望对您有所帮助!

本专栏主要结合作者之前的博客、AI经验和相关视频及论文介绍,后面随着深入会讲解更多的Python人工智能案例及应用。基础性文章,希望对您有所帮助,如果文章中存在错误或不足之处,还请海涵!作者作为人工智能的菜鸟,希望大家能与我在这一笔一划的博客中成长起来。写了这么多年博客,尝试第一个付费专栏,为小宝赚点奶粉钱,但更多博客尤其基础性文章,还是会继续免费分享,该专栏也会用心撰写,望对得起读者。如果有问题随时私聊我,只望您能从这个系列中学到知识,一起加油喔~

前文赏析:


一.BiLSTM模型

LSTM的全称是Long Short-Term Memory,它是RNN(Recurrent Neural Network)的一种。LSTM由于其设计的特点,非常适合用于对时序数据的建模,如文本数据。BiLSTM是Bi-directional Long Short-Term Memory的缩写,是由前向LSTM与后向LSTM组合而成。两者在自然语言处理任务中都常被用来建模上下文信息。

1.RNN

循环神经网络英文是Recurrent Neural Networks,简称RNN。假设有一组数据data0、data1、data2、data3,使用同一个神经网络预测它们,得到对应的结果。如果数据之间是有关系的,比如做菜下料的前后步骤,英文单词的顺序,如何让数据之间的关联也被神经网络学习呢?这就要用到——RNN。

RNN结构如下图所示,按照时间点t-1、t、t+1,每个时刻有不同的x,每次计算会考虑上一步的state和这一步的x(t),再输出y值。在该数学形式中,每次RNN运行完之后都会产生s(t),当RNN要分析x(t+1)时,此刻的y(t+1)是由s(t)和s(t+1)共同创造的,s(t)可看作上一步的记忆。多个神经网络NN的累积就转换成了循环神经网络,其简化图如下图的左边所示。

RNN常用于自然语言处理、机器翻译、语音识别、图像识别等领域。


2.LSTM和BiLSTM

RNN是在有序的数据上进行学习的,RNN会像人一样对先前的数据发生记忆,但有时候也会像老爷爷一样忘记先前所说。为了解决RNN的这个弊端,提出了LTSM技术,它的英文全称是Long short-term memory,长短期记忆,也是当下最流行的RNN之一。

LSTM是在普通的RNN上面做了一些改进,LSTM RNN多了三个控制器,即输入、输出、忘记控制器。左边多了个条主线,例如电影的主线剧情,而原本的RNN体系变成了分线剧情,并且三个控制器都在分线上。

  • 输入控制器(write gate): 在输入input时设置一个gate,gate的作用是判断要不要写入这个input到我们的内存Memory中,它相当于一个参数,也是可以被训练的,这个参数就是用来控制要不要记住当下这个点。
  • 输出控制器(read gate): 在输出位置的gate,判断要不要读取现在的Memory。
  • 忘记控制器(forget gate): 处理位置的忘记控制器,判断要不要忘记之前的Memory。

通过这三个gate能够很好地控制我们的RNN,基于这些控制机制,LSTM是延缓记忆的良药,从而带来更好的结果。


二.数据集介绍

数据描述:

类型描述
数据概览36 万多条,带情感标注 新浪微博,包含 4 种情感,其中喜悦约 20 万条,愤怒、厌恶、低落各约 5 万条
推荐实验情感/观点/评论 倾向性分析
数据来源新浪微博
原数据集微博情感分析数据集,网上搜集,具体作者、来源不详
数据描述微博总体数目为361744: 喜悦-199496、愤怒-51714、厌恶-55267、低落-55267
对应类标0: 喜悦, 1: 愤怒, 2: 厌恶, 3: 低落

数据示例:

注意,做到实验分析,作者才发现“厌恶-55267”和“低落-55267”的数据集完全相同,因此我们做三分类问题,更重要的是思想。

下载地址:

  • https://github.com/eastmountyxz/Datasets-Text-Mining

参考链接:

  • https://github.com/SophonPlus/ChineseNlpCorpus/blob/master/datasets/simplifyweibo_4_moods/intro.ipynb

三.数据预处理

1.数据读取

首先,我们尝试读取微博数据,看看各个情感类别的数量。

# -*- coding: utf-8 -*-
"""
Created on Mon Sep 27 22:21:53 2021
@author: xiuzhang
"""
import pandas as pd

pd_all = pd.read_csv('simplifyweibo_4_moods.csv')
moods = 0: '喜悦', 1: '愤怒', 2: '厌恶', 3: '低落'

print('微博数目(总体):%d' % pd_all.shape[0])

for label, mood in moods.items(): 
    print('微博数目():'.format(mood,pd_all[pd_all.label==label].shape[0]))

其输出结果如下图所示:


2.中文分词及停用词过滤

接下来,通常是读取文本数据并进行中文分词和数据清洗,停用词过滤主要是清洗掉特殊字符和无关的特征词(如“我们”“这样”“之前”等)。注意通过如下所示的核心代码可以按行读取文件内容,比如输出10行内容。

k = 0
for line in range(len(pd_all)): #label review
    dict_label = pd_all['label'][line]
    dict_review = pd_all['review'][line]
    print(dict_label, dict_review)
    k += 1
    if k>10:
        break

输出结果如下图所示:

Python文本挖掘学习小建议
(1) 如果你是一名文本分析初学者,在写代码过程中,尽量多输出中间结果(打桩调试),这样会让你更加清晰每个步骤所完成的内容,同时方便自主调试我们代码。
(2) 个人建议将中文分词及停用词过滤的文件单独存成另一份文件,这样便于后续的深度学习分类和主题挖掘实验。

包含词频统计的完整代码如下:

# -*- coding: utf-8 -*-
"""
Created on Mon Sep 27 22:21:53 2021
@author: xiuzhang
"""
import pandas as pd
import jieba
import csv
from collections import Counter

#-----------------------------------------------------------------------------
#样本数量统计
pd_all = pd.read_csv('simplifyweibo_4_moods.csv')
moods = 0: '喜悦', 1: '愤怒', 2: '厌恶', 3: '低落'

print('微博数目(总体):%d' % pd_all.shape[0])
for label, mood in moods.items(): 
    print('微博数目():'.format(mood,pd_all[pd_all.label==label].shape[0]))
    
#-----------------------------------------------------------------------------
#中文分词和停用词过滤
cut_words = ""
all_words = ""
stopwords = ["[", "]", ")", "(", ")", "(", "【", "】", "!", ",", "$",
             "·", "?", ".", "、", "-", "—", ":", ":", "《", "》", "=",
             "。", "…", "“", "?", "”", "~", " ", "-", "+", "\\\\", "‘",
             "~", ";", "’", "...", "..", "&", "#",  "....", ",", 
             "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"
             "的", "和", "之", "了", "哦", "那", "一个",  ]

fw = open('simplifyweibo_4_moods_fenci.csv', 'w', encoding='utf-8')

for line in range(len(pd_all)): #label review
    dict_label = pd_all['label'][line]
    dict_review = pd_all['review'][line]
    #print(dict_label, dict_review)
    
    #jieba分词并过滤停用词
    cut_words = ""
    data = dict_review.strip('\\n')
    data = data.replace(",", "")    #一定要过滤符号 ","否则多列
    seg_list = jieba.cut(data, cut_all=False)
    for seg in seg_list:
        if seg not in stopwords:
            cut_words += seg + " "
    all_words += cut_words
    #print(cut_words)
    
    fw.write(str(dict_label)+","+str(cut_words)+"\\n")
    #print(str(dict_label)+","+str(cut_words)+"\\n")
else:
    fw.close()

#-----------------------------------------------------------------------------
#词频统计
all_words = all_words.split()
print(all_words)

c = Counter()
for x in all_words:
    if len(x)>1 and x != '\\r\\n':
        c[x] += 1
        
#输出词频最高的前10个词
print('\\n词频统计结果:')
for (k,v) in c.most_common(10):
    print("%s:%d"%(k,v))

输出结果如下图所示:

  • simplifyweibo_4_moods_fenci.csv

统计出现次数最多的10个单词如下图所示,我们可以通过大连理工大学情感词或词性来计算喜怒哀乐不同类别的常见特征词。读者可以去尝试下,也可以看我之前写的博客。


3.词频可视化分析

接着我们读取分词后的CSV文件,然后运用PyEcharts绘制词云图。

该部分代码如下:

# -*- coding: utf-8 -*-
"""
Created on Mon Sep 27 22:21:53 2021
@author: xiuzhang
"""
import pandas as pd
import csv
from collections import Counter

#-----------------------------------------------------------------------------
#读取分词后特征词
cut_words = ""
all_words = ""
pd_all = pd.read_csv('simplifyweibo_4_moods_fenci.csv')
moods = 0: '喜悦', 1: '愤怒', 2: '厌恶', 3: '低落'
print('微博数目(总体):%d' % pd_all.shape[0])
for label, mood in moods.items(): 
    print('微博数目():'.format(mood,pd_all[pd_all.label==label].shape[0]))
    
for line in range(len(pd_all)): #label review
    dict_label = pd_all['label'][line]
    dict_review = pd_all['review'][line]
    cut_words = dict_review
    all_words += str(cut_words)
    #print(cut_words)

#-----------------------------------------------------------------------------
#词频统计
all_words = all_words.split()
c = Counter()
for x in all_words:
    if len(x)>1 and x != '\\r\\n':
        c[x] += 1
print('\\n词频统计结果:')
for (k,v) in c.most_common(10):
    print("%s:%d"%(k,v))
    
#存储数据
name ="data-word-count.csv"
fw = open(name, 'w', encoding='utf-8')
i = 1
for (k,v) in c.most_common(len(c)):
    fw.write(str(i)+','+str(k)+','+str(v)+'\\n')
    i = i + 1
else:
    print("Over write file!")
    fw.close()

#-----------------------------------------------------------------------------
#词云分析
from pyecharts import options as opts
from pyecharts.charts import WordCloud
from pyecharts.globals import SymbolType

#生成数据 word = [('A',10), ('B',9), ('C',8)] 列表+Tuple
words = []
for (k,v) in c.most_common(200):
    words.append((k,v))

#渲染图
def wordcloud_base() -> WordCloud:
    c = (
        WordCloud()
        .add("", words, word_size_range=[20, 40], shape='diamond') #shape=SymbolType.ROUND_RECT
        .set_global_opts(title_opts=opts.TitleOpts(title='词云图'))
    )
    return c
wordcloud_base().render('微博评论情感分析词云图.html')

输出结果如下图所示:

其实上图效果并不很好,如果想要获得更高质量的效果,且对比多种情感,怎么实现呢?请读者下来自行提升,下面是对应的效果图。


四.机器学习情感分析

经过上述的预处理后,接下来我们将直接介绍BiLSTM实现微博情感分类。数据集修改为:

  • 类别0:喜悦-199496
  • 类别1:愤怒-51714
  • 类别2:低落-55267

再次强调,作者代码中会含详细注释和中间过程输出,也建议初学者这样尝试。或许代码风格不是很美观,但只有掌握每行代码的实质,为什么怎样做?会得到怎么的输出结果,才能为后续做深入的分析和工程提供更好地编程习惯和理解。如果您是大佬,也请原谅我喜欢使用 print 的不足吧!

# -*- coding: utf-8 -*-
"""
Created on Mon Sep 27 22:21:53 2021
@author: xiuzhang
"""
import pandas as pd
import numpy as np
from collections import Counter
from scipy.sparse import coo_matrix
from sklearn import feature_extraction  
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report

from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn import svm
from sklearn import neighbors
from sklearn.naive_bayes import MultinomialNB

#-----------------------------------------------------------------------------
#读取分词后特征词
pd_all = pd.read_csv('weibo_3_fenci.csv')
moods = 0: '喜悦', 1: '愤怒', 2: '低落'
print('微博数目(总体):%d' % pd_all.shape[0])
for label, mood in moods.items(): 
    print('微博数目():'.format(mood,pd_all[pd_all.label==label].shape[0]))

labels = []
contents = []
for line in range(len(pd_all)):  #label review
    labels.append(pd_all['label'][line])
    contents.append(str(pd_all['review'][line]))
print(len(labels),len(contents))

#-----------------------------------------------------------------------------
#TFIDF计算
#将文本中的词语转换为词频矩阵 矩阵元素a[i][j] 表示j词在i类文本下的词频
vectorizer = CountVectorizer(min_df=50)   #MemoryError控制参数

#该类会统计每个词语的tf-idf权值
transformer = TfidfTransformer()

#第一个fit_transform是计算tf-idf 第二个fit_transform是将文本转为词频矩阵
tfidf = transformer.fit_transform(vectorizer.fit_transform(contents))
for n in tfidf[:5]:
    print(n)
print(type(tfidf))

#获取词袋模型中的所有词语  
word = vectorizer.get_feature_names()
for n in word[:10]:
    print(n)
print("单词数量:", len(word))  #74806 12884

#将tf-idf矩阵抽取出来,元素w[i][j]表示j词在i类文本中的tf-idf权重
X = coo_matrix(tfidf, dtype=np.float32).toarray() #稀疏矩阵 float
#X = tfidf.toarray()
print(X.shape)
print(X[:10])

#数据划分
X_train, X_test, y_train, y_test = train_test_split(X, 
                                                    labels, 
                                                    test_size=0.3, 
                                                    random_state=1)
print(len(X_train),len(X_test),len(y_train),len(y_test))

#-----------------------------------------------------------------------------
# 逻辑回归分类方法模型
LR = LogisticRegression(solver='liblinear')
LR.fit(X_train, y

[python人工智能]三十九.vscode配置python编程和keras环境及手写数字识别(基础篇)

从本专栏开始,作者正式研究Python深度学习、神经网络及人工智能相关知识。前一篇文章利用Keras构建无监督学习Autoencoder模型并实现聚类分析。这篇文章将介绍基础知识,因为很多读者咨询我如何用VSCode配置Keras深度学习环境,... 查看详情

[python人工智能]三十六.基于transformer的商品评论情感分析keras构建多头自注意力(transformer)模型

从本专栏开始,作者正式研究Python深度学习、神经网络及人工智能相关知识。前一篇文章利用Keras构建深度学习模型并实现了情感分析。这篇文章将介绍Transformer基础知识,并通过Keras构建多头自注意力(Transformer)模型,实现IMDB... 查看详情

[python人工智能]三十六.基于transformer的商品评论情感分析keras构建多头自注意力(transformer)模型

从本专栏开始,作者正式研究Python深度学习、神经网络及人工智能相关知识。前一篇文章利用Keras构建深度学习模型并实现了情感分析。这篇文章将介绍Transformer基础知识,并通过Keras构建多头自注意力(Transformer)模型,实现IMDB... 查看详情

[python人工智能]三十三.bert模型keras-bert库构建bert模型实现文本分类(代码片段)

...专栏开始,作者正式研究Python深度学习、神经网络及人工智能相关知识。前一篇文章开启了新的内容——Bert,首先介绍Keras-bert库安装及基础用法,这将为后续文本分类、命名实体识别提供帮助。这篇文章将通过keras-b... 查看详情

[python人工智能]三十四.bert模型keras-bert库构建bert模型实现微博情感分析(代码片段)

...专栏开始,作者正式研究Python深度学习、神经网络及人工智能相关知识。前一篇文章开启了新的内容——Bert,首先介绍Keras-bert库安装及基础用法及文本分类工作。这篇文章将通过keras-bert库构建Bert模型,并实现微博... 查看详情

[python人工智能]三十.keras深度学习构建cnn识别阿拉伯手写文字图像(代码片段)

...专栏开始,作者正式研究Python深度学习、神经网络及人工智能相关知识。前一篇文章分享了生成对抗网络GAN的基础知识,包括什么是GAN、常用算法(CGAN、DCGAN、infoGAN、WGAN)、发展历程、预备知识,并通过Keras... 查看详情

[python人工智能]三十八.keras构建无监督学习autoencoder模型及mnist聚类可视化详解(代码片段)

...专栏开始,作者正式研究Python深度学习、神经网络及人工智能相关知识。前一篇文章详细讲解了基于Transformer的商品评论情感分析案例。本篇文章将分享无监督学习Autoencoder的原理知识,然后介绍Keras构建自编码的案例ÿ... 查看详情

[python人工智能]三十七.keras构建无监督学习autoencoder模型及mnist聚类可视化详解(代码片段)

...专栏开始,作者正式研究Python深度学习、神经网络及人工智能相关知识。前一篇文章详细讲解了基于Transformer的商品评论情感分析案例。本篇文章将分享无监督学习Autoencoder的原理知识,然后介绍Keras构建自编码的案例ÿ... 查看详情

智能指针(三十一)

        我们在程序开发中,难免会遇到内存泄漏。那么什么是内存泄漏呢?就是动态申请堆空间,用完后不归还。在C++语言中没有垃圾回收机制,在后续的语言如Java、C#等高级语言中就存在垃圾回收... 查看详情

[python人工智能]三十二.bert模型keras-bert基本用法及预训练模型(代码片段)

...专栏开始,作者正式研究Python深度学习、神经网络及人工智能相关知识。前一篇文章结合文本挖掘介绍微博情感分类知识,包括数据预处理、机器学习和深度学习的情感分类。这篇文章将开启新的内容——Bert,首先... 查看详情

springboot入门教程(三十一):自定义starter

分享一个朋友的人工智能教程(请以“右键”->"在新标签页中打开连接”的方式访问)。比较通俗易懂,风趣幽默,感兴趣的朋友可以去看看。在springboot中,使用的最多的就是starter。starter可以理解为一个可拔插式的插件,例如... 查看详情

前端基础进阶(三十一):javascript执行上下文和执行栈

参考网址:https://juejin.cn/post/684490...https://juejin.cn/post/684490... 查看详情

学习笔记第三十一节课

iptablesfilter表小案例需要把80端口和21端口22端口放行,22端口指定一个ip段,只有这个ip段的访问才可以,其他的都拒绝。用一个shell脚本去实现。ipt定义了一个变量,为了后面去加载它。正常执行一个命令写一个绝对的命令,不... 查看详情

初级算法探索——动态规划篇(三十一)

未完待续 查看详情

初级算法探索——动态规划篇(三十一)

未完待续 查看详情

react工作记录三十一dva.js初识

前言我是歌谣我有个兄弟巅峰的时候排名c站总榜19叫前端小歌谣曾经我花了三年的时间创作了他现在我要用五年的时间超越他今天又是接近兄弟的一天人生难免坎坷大不了从头再来歌谣的意志是永恒的放弃很容易但是坚持一定很... 查看详情

开始写游戏---第三十一篇

开始写游戏---第三十一篇  今天:    1、增加物品使用组件    2、增加物品使用功能、增加蓝条    上图:    1、增加物品使用组件          效果图:              代码: ... 查看详情

出差(三十一)

      今天是一个好日子,又赶上周末,双喜临门。好日子的原因是今天是上家公司的payday,这次到账最后一笔工资,算是跟公司划清界线了。       换了新的环境,payday改到了每月... 查看详情