二维卷积中文微博情感分类项目

简介: 这里完成一个中文微博情感分类项目。这里我使用的数据集是从新浪微博收集的 12 万条数据,正负样本各一半。标签中 1 表示正面评论,0 表示负面评论。数据来源为[https://github.com/SophonPlus/ChineseNlpCorpus/blob/master/datasets/weibo_sen ti_100k/intro.ipynb。](https://github.com/SophonPlus/ChineseNlpCorpus/blob/master/datasets/weibo_sen%20ti_100k/intro.ipynb%E3%80%82)如果你有其他数据的话,

1、数据集说明

  这里完成一个中文微博情感分类项目。这里我使用的数据集是从新浪微博收集的 12 万条数据,正负样本各一半。标签中 1 表示正面评论,0 表示负面评论。数据来源为https://github.com/SophonPlus/ChineseNlpCorpus/blob/master/datasets/weibo_sen ti_100k/intro.ipynb。如果你有其他数据的话,也可以使用其他数据。
  这一次我们使用的数据需要自己做处理,所以我们需要对句子进行分词,分词后再对每 个词根据频率来进行编号。这里我们要使用的分词工具是结巴分词,结巴分词是一个很好用 的中文分词工具,安装方式为打开命令提示符,然后输入命令:

pip install jieba

  安装好以后在 python 程序中直接 import jieba 就可以使用了。

2、二维卷积中文情感分类实战

# 安装结巴分词
# pip install jieba
import jieba 
import pandas as pd 
import numpy as np 
from tensorflow.keras.layers import Dense, Input, Dropout
from tensorflow.keras.layers import Conv2D, GlobalMaxPool2D, Embedding, concatenate
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.models import Model
import tensorflow.keras.backend as K
from sklearn.model_selection import train_test_split
import json
# pip install plot_model
from plot_model import plot_model
from matplotlib import pyplot as plt
# 批次大小
batch_size = 128
# 训练周期
epochs = 3
# 词向量长度
embedding_dims = 128
# 滤波器数量
filters = 32
# 这个数据前半部分都是正样本,后半部分都是负样本
data = pd.read_csv('weibo_senti_100k.csv')
# 查看数据前5行
data.head(),data.tail()

image-20220719232001405

# 计算正样本数量
poslen = sum(data['label']==1)
# 计算负样本数量
neglen = sum(data['label']==0)
print('正样本数量:', poslen)
print('负样本数量:', neglen)

image-20220719231944228

# 测试一下结巴分词的使用
print(list(jieba.cut('做父母一定要有刘墉这样的心态,不断地学习,不断地进步')))

image-20220719232036786

#定义分词函数,对传入的x进行分词
cw = lambda x: list(jieba.cut(x))
# apply传入一个函数,把cw函数应用到data['review']的每一行
# 把分词后的结果保存到data['words']中
data['words'] = data['review'].apply(cw)
# 再查看数据前5行
data.head()

image-20220719232106371

# 计算一条数据最多有多少个词汇
max_length = max([len(x) for x in data['words']])
# 打印看到结果为202,最长的句子词汇数不算太多
# 后面就以202作为标准,把所有句子的长度都填充到202的长度
# 比如最长的句子为2000,那么说明有些句子太长了,我们可以设置一个小一点的值作为所有句子的标准长度
# 比如设置1000,那么超过1000的句子只取前面1000个词,不足1000的句子填充到1000的长度
print(max_length)

image-20220719232119356

# 把data['words']中所有的list都变成字符串格式
texts = [' '.join(x) for x in data['words']]
texts

image-20220719232139893

# 查看一条评论,现在数据变成了字符串格式,并且词与词之间用空格隔开
# 这是为了满足下面数据处理对格式的要求,下面要使用Tokenizer对数据进行处理
texts[4]

image-20220719232151418

# 实例化Tokenizer,设置字典中最大词汇数为30000
# Tokenizer会自动过滤掉一些符号比如:!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n
tokenizer = Tokenizer(num_words=30000)
# 传入我们的训练数据,建立词典,词的编号根据词频设定,频率越大,编号越小,
tokenizer.fit_on_texts(texts) 
# 把词转换为编号,编号大于30000的词会被过滤掉
sequences = tokenizer.texts_to_sequences(texts) 
# 把序列设定为max_length的长度,超过max_length的部分舍弃,不到max_length则补0
# padding='pre'在句子前面进行填充,padding='post'在句子后面进行填充
X = pad_sequences(sequences, maxlen=max_length, padding='pre')  
# X = np.array(sequences)
# 获取字典
dict_text = tokenizer.word_index
# 在字典中查询词dui yi
dict_text['梦想']

image-20220719232220074

# 把token_config保存到json文件中,模型预测阶段可以使用
file = open('token_config.json','w',encoding='utf-8')
# 把tokenizer变成json数据
token_config = tokenizer.to_json()
# 保存json数据
json.dump(token_config, file)
print(X[4])

image-20220719232245270

# 定义标签
# 01为正样本,10为负样本
positive_labels = [[0, 1] for _ in range(poslen)]
negative_labels = [[1, 0] for _ in range(neglen)]
# 合并标签
Y = np.array(positive_labels + negative_labels)
print(Y)
# 切分数据集
x_train,x_test,y_train,y_test = train_test_split(X, Y, test_size=0.2)

image-20220719232258286

# 定义函数式模型
# 定义模型输入,shape-(batch, 202)
sequence_input = Input(shape=(max_length,))
# Embedding层,30000表示30000个词,每个词对应的向量为128维
embedding_layer = Embedding(input_dim=30000, output_dim=embedding_dims)
# embedded_sequences的shape-(batch, 202, 128)
embedded_sequences = embedding_layer(sequence_input)
# embedded_sequences的shape变成了(batch, 202, 128, 1)
embedded_sequences = K.expand_dims(embedded_sequences, axis=-1)

# 卷积核大小为3,列数必须等于词向量长度
cnn1 = Conv2D(filters=filters, kernel_size=(3,embedding_dims), activation='relu')(embedded_sequences)
cnn1 = GlobalMaxPool2D()(cnn1)

# 卷积核大小为4,列数必须等于词向量长度
cnn2 = Conv2D(filters=filters, kernel_size=(4,embedding_dims), activation='relu')(embedded_sequences)
cnn2 = GlobalMaxPool2D()(cnn2)

# 卷积核大小为5,列数必须等于词向量长度
cnn3 = Conv2D(filters=filters, kernel_size=(5,embedding_dims), activation='relu')(embedded_sequences)
cnn3 = GlobalMaxPool2D()(cnn3)

# 合并
merge = concatenate([cnn1, cnn2, cnn3], axis=-1)
# 全链接层
x = Dense(128, activation='relu')(merge)
# Dropout层
x = Dropout(0.5)(x)
# 输出层
preds = Dense(2, activation='softmax')(x)
# 定义模型
model = Model(sequence_input, preds)

plot_model(model, dpi=200)

# 定义代价函数,优化器
model.compile(loss='categorical_crossentropy',
              optimizer='adam',
              metrics=['acc'])

# 训练模型
history=model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          validation_data=(x_test, y_test))

image-20220719232338890

# 保存模型
model.save('cnn_model.h5') 

3、模型预测

from keras.models import load_model
from keras.preprocessing.text import tokenizer_from_json
from keras.preprocessing.sequence import pad_sequences
import jieba
import numpy as np
import json
# 载入tokenizer
json_file=open('token_config.json','r',encoding='utf-8')
token_config=json.load(json_file)
tokenizer=tokenizer_from_json(token_config)
#载入模型
model=load_model('cnn_model.h5')
#情感预测
def predict(text):
    # 对句子分词
    cw=list(jieba.cut(text))# ['今天天气', '真', '好', ',', '我要', '去', '打球']
    # list转字符串,元素之间用' '隔开
    texts=' '.join(cw) # 字符串 '今天天气 真 好 , 我要 去 打球'
    # print([texts])# ['今天天气 真 好 , 我要 去 打球']
    # 把词转换为编号,编号大于30000的词会被过滤掉
    sequences=tokenizer.texts_to_sequences([texts]) # [texts] 是把字符串变成列表
    # model.input_shape为(None, 202),202为训练模型时的序列长度
    # 把序列设定为202的长度,超过202的部分舍弃,不到202则补0
    sequences=pad_sequences(sequences=sequences
                            ,maxlen=model.input_shape[1] # 202
                            ,padding = 'pre')
    # 模型预测 shape(1,2)
    predict_result=model.predict(sequences)
    # 取出predict_result中元素最大值所对应的索引
    result=np.argmax(predict_result)
    if(result==1):
        print('正面情绪')
    else:
        print('负面情绪')

if __name__ == '__main__':
    predict('今天天气真好,我要去打球')
    predict("一大屋子人,结果清早告停水了,我崩溃到现在[抓狂]")
    predict("今天我很高兴")
    # pass

image-20220719232428480

  原始数据中有大量表情符号,如[爱你],[哈哈],[鼓掌],[可爱]等,这些表情符号中对应的文字从较大程度上代表了这一句话的情感。所以我们做的这个项目之所以得到这么高的准确率,跟这里的表情符号是有很大关系。大家如果使用其他数据集来做情感分类, 应该也会得到不错的结果,但是应该很难得到 98%这么高的准确率。
目录
相关文章
|
canal 缓存 NoSQL
【Redis系列笔记】双写一致性
本文讨论了缓存不一致问题及其后果,如价格显示错误和订单计算错误。问题主要源于并发和双写操作的异常。解决方案包括使用分布式锁(但可能导致性能下降和复杂性增加)、延迟双删策略(通过延迟删除缓存来等待数据同步)以及异步同步方法,如通过Canal和MQ实现数据的最终一致性。面试中,可以提及这些策略来确保数据库和缓存数据的一致性。
1247 1
【Redis系列笔记】双写一致性
FEC1 Waiting for PHY auto negotiation to complete......... TIMEOUT !
FEC1 Waiting for PHY auto negotiation to complete......... TIMEOUT !
547 0
|
存储 Kubernetes 关系型数据库
|
Ubuntu 网络协议 Android开发
使用ruri快速构建跨架构chroot容器
【7月更文挑战第10天】使用ruri快速构建跨架构chroot容器:先确认binfmt_misc支持;安装qemu-user-static;用rootfstool脚本获取rootfs;下载最新ruri二进制;解压rootfs并启动容器;配置DNS。完成这些步骤后,可在x86_64上运行arm64的Ubuntu容器。注意,ruri处于实验阶段,使用前需评估风险,并根据需求调整与优化。此流程提供基础参考,具体操作可能需微调。
372 6
|
11月前
|
存储 Oracle 关系型数据库
oracle数据恢复—Oracle数据库文件大小变为0kb的数据恢复案例
存储掉盘超过上限,lun无法识别。管理员重组存储的位图信息并导出lun,发现linux操作系统上部署的oracle数据库中有上百个数据文件的大小变为0kb。数据库的大小缩水了80%以上。 取出&并分析oracle数据库的控制文件。重组存储位图信息,重新导出控制文件中记录的数据文件,发现这些文件的大小依然为0kb。
|
Java API 数据库
详细介绍如何使用Spring Boot简化Java Web开发过程。
Spring Boot简化Java Web开发,以轻量级、易用及高度可定制著称。通过预设模板和默认配置,开发者可迅速搭建Spring应用。本文通过创建RESTful API示例介绍其快速开发流程:从环境准备、代码编写到项目运行及集成数据库等技术,展现Spring Boot如何使Java Web开发变得更高效、简洁。
258 1
|
缓存 Unix 索引
Pandas中to_datetime()转换时间序列函数一文详解
Pandas中to_datetime()转换时间序列函数一文详解
3709 0
Pandas中to_datetime()转换时间序列函数一文详解
|
easyexcel Java API
SpringBoot集成EasyExcel 3.x:高效实现Excel数据的优雅导入与导出
SpringBoot集成EasyExcel 3.x:高效实现Excel数据的优雅导入与导出
2322 1
|
机器学习/深度学习 存储 人工智能
基于深度学习的乳腺癌智能检测分割与诊断系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标分割、人工智能(1)
基于深度学习的乳腺癌智能检测分割与诊断系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标分割、人工智能
|
运维 JavaScript Serverless
Function Compute
函数计算(Function Compute)是云计算领域的一种服务模型,由云服务提供商(例如阿里云、AWS、Google Cloud 等)提供。它是一种无服务器计算服务,允许开发者编写和部署函数,以响应事件触发,而无需管理底层的服务器和基础设施。函数计算提供了弹性的计算资源分配、按需计费、自动扩缩容等特性,使开发者能够聚焦于编写函数逻辑而不必担心底层的运维工作。
475 2