[Python人工智能] 三十一.Keras实现BiLSTM微博情感分类和LDA主题挖掘分析(上)
Posted Eastmount
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Python人工智能] 三十一.Keras实现BiLSTM微博情感分类和LDA主题挖掘分析(上)相关的知识,希望对你有一定的参考价值。
从本专栏开始,作者正式研究Python深度学习、神经网络及人工智能相关知识。前一篇文章通过Keras深度学习构建CNN模型识别阿拉伯手写文字图像,一篇非常经典的图像分类文字。这篇文章将结合文本挖掘介绍微博情感分类知识,包括数据预处理、机器学习和深度学习的情感分类,后续结合LDA进行主题挖掘。基础性文章,希望对您有所帮助!
文章目录
本专栏主要结合作者之前的博客、AI经验和相关视频及论文介绍,后面随着深入会讲解更多的Python人工智能案例及应用。基础性文章,希望对您有所帮助,如果文章中存在错误或不足之处,还请海涵!作者作为人工智能的菜鸟,希望大家能与我在这一笔一划的博客中成长起来。写了这么多年博客,尝试第一个付费专栏,为小宝赚点奶粉钱,但更多博客尤其基础性文章,还是会继续免费分享,该专栏也会用心撰写,望对得起读者。如果有问题随时私聊我,只望您能从这个系列中学到知识,一起加油喔~
- Keras下载地址:https://github.com/eastmountyxz/AI-for-Keras
- TensorFlow下载地址:https://github.com/eastmountyxz/AI-for-TensorFlow
前文赏析:
- [Python人工智能] 一.TensorFlow2.0环境搭建及神经网络入门
- [Python人工智能] 二.TensorFlow基础及一元直线预测案例
- [Python人工智能] 三.TensorFlow基础之Session、变量、传入值和激励函数
- [Python人工智能] 四.TensorFlow创建回归神经网络及Optimizer优化器
- [Python人工智能] 五.Tensorboard可视化基本用法及绘制整个神经网络
- [Python人工智能] 六.TensorFlow实现分类学习及MNIST手写体识别案例
- [Python人工智能] 七.什么是过拟合及dropout解决神经网络中的过拟合问题
- [Python人工智能] 八.卷积神经网络CNN原理详解及TensorFlow编写CNN
- [Python人工智能] 九.gensim词向量Word2Vec安装及《庆余年》中文短文本相似度计算
- [Python人工智能] 十.Tensorflow+Opencv实现CNN自定义图像分类案例及与机器学习KNN图像分类算法对比
- [Python人工智能] 十一.Tensorflow如何保存神经网络参数
- [Python人工智能] 十二.循环神经网络RNN和LSTM原理详解及TensorFlow编写RNN分类案例
- [Python人工智能] 十三.如何评价神经网络、loss曲线图绘制、图像分类案例的F值计算
- [Python人工智能] 十四.循环神经网络LSTM RNN回归案例之sin曲线预测
- [Python人工智能] 十五.无监督学习Autoencoder原理及聚类可视化案例详解
- [Python人工智能] 十六.Keras环境搭建、入门基础及回归神经网络案例
- [Python人工智能] 十七.Keras搭建分类神经网络及MNIST数字图像案例分析
- [Python人工智能] 十八.Keras搭建卷积神经网络及CNN原理详解
[Python人工智能] 十九.Keras搭建循环神经网络分类案例及RNN原理详解 - [Python人工智能] 二十.基于Keras+RNN的文本分类vs基于传统机器学习的文本分类
- [Python人工智能] 二十一.Word2Vec+CNN中文文本分类详解及与机器学习(RF\\DTC\\SVM\\KNN\\NB\\LR)分类对比
- [Python人工智能] 二十二.基于大连理工情感词典的情感分析和情绪计算
- [Python人工智能] 二十三.基于机器学习和TFIDF的情感分类(含详细的NLP数据清洗)
- [Python人工智能] 二十四.易学智能GPU搭建Keras环境实现LSTM恶意URL请求分类
- [Python人工智能] 二十六.基于BiLSTM-CRF的医学命名实体识别研究(上)数据预处理
- [Python人工智能] 二十七.基于BiLSTM-CRF的医学命名实体识别研究(下)模型构建
- [Python人工智能] 二十八.Keras深度学习中文文本分类万字总结(CNN、TextCNN、LSTM、BiLSTM、BiLSTM+Attention)
- [Python人工智能] 二十九.什么是生成对抗网络GAN?基础原理和代码普及(1)
- [Python人工智能] 三十.Keras深度学习构建CNN识别阿拉伯手写文字图像
- [Python人工智能] 三十一.Keras实现BiLSTM微博情感分类和LDA主题挖掘分析(上)
一.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人工智能] 三十一.Keras实现BiLSTM微博情感分类和LDA主题挖掘分析(上)的主要内容,如果未能解决你的问题,请参考以下文章
[Python人工智能] 三十四.Bert模型 keras-bert库构建Bert模型实现微博情感分析
[Python人工智能] 三十六.基于Transformer的商品评论情感分析 keras构建多头自注意力(Transformer)模型
[Python人工智能] 三十六.基于Transformer的商品评论情感分析 keras构建多头自注意力(Transformer)模型
[Python人工智能] 三十九.VS Code配置Python编程和Keras环境及手写数字识别(基础篇)