大家好,我是带我去滑雪!
利用之前爬取2023年10月17日至2024年7月13日的65万余条东方财富网的上证指数股吧的股民评论数据,基于jieba库对股民情绪进行识别,在进行中文分词、去除停用词、合并同义词和长短句分离后,对长文本使用长短期记忆网络(LSTM)情绪分类,对短文本使用朴素贝叶斯(NBM)情绪分类,建立了股民情绪识别的LSTM-NBM混合模型。混合模型的正向文本和负向文本的识别准确率分别为77%、88%。下面开始代码实战。
目录
(1)基于jieba库的文本处理
(2)长文本LSTM情绪分类模型
(3)短文本NBM的模型构建
(1)基于jieba库的文本处理
识别股民情绪时,机器学习模型的选择因句子长度的不同而异。长句子依赖于词汇间的相互作用和逻辑关系来传达意义,而短句子则能通过极少的词语直接明确其含义。为了能够更加高效的代入后续训练模型中,需要对股民评论中非结构化的文本要进行相应的预处理,本文采用jieba分词方法。jieba是一种流行的中文分词工具,它可以将文本切分成有意义的单词,是目前Python中最常用的中文分词库之一,具有简单易用、高效准确的特点。下面依次进行:
- 去除停用词
- 合并同义词
- 长短句分离:将经过分词、去停用词、合并同义词后的文本数据,按照10字节大小分为长短文本,对于不同长短的文本数据采取不同的情感分析模型。
import pandas as pd
all_data=pd.read_csv('E:\工作\硕士\博客\朴素贝叶斯与LSTM情感分类代码与数据(2)\data.csv',encoding="ANSI")
all_data
all_data['PL']
输出结果:
import pandas as pd
import jieba
stop_list = pd.read_csv("E:\工作\硕士\博客\博客粉丝问题\朴素贝叶斯与LSTM情感分类代码与数据\停用词.txt",index_col=False,quoting=3,sep="\t",names=['stopword'], encoding='utf-8')
#Jieba分词函数
def txt_cut(juzi):lis=[w for w in jieba.lcut(juzi) if w not in stop_list.values]return (" ").join(lis)
df=pd.read_csv('E:\工作\硕士\博客\博客粉丝问题\朴素贝叶斯与LSTM情感分类代码与数据\data.csv',encoding="ANSI")
df['cutword']=df['PL'].astype('str').apply(txt_cut)
df=df[['date','PL','cutword']]
df
df.to_excel('E:\工作\硕士\博客\博客粉丝问题\朴素贝叶斯与LSTM情感分类代码与数据\分词后的评论.xlsx',index=False)
import pandas as pd
df = pd.read_csv('E:\工作\硕士\博客\博客粉丝问题\朴素贝叶斯与LSTM情感分类代码与数据\分词后的评论.csv',encoding="ANSI")
df.set_index('date', inplace=True)
long_texts = df[df['cutword'].str.len() > 10]
short_texts = df[df['cutword'].str.len() <= 10]
long_texts.to_csv('E:\工作\硕士\博客\博客粉丝问题\朴素贝叶斯与LSTM情感分类代码与数据\分词后的长文本.csv',encoding="ANSI") # 保存长文本
short_texts.to_csv('E:\工作\硕士\博客\博客粉丝问题\朴素贝叶斯与LSTM情感分类代码与数据\分词后的短文本.csv',encoding="ANSI") # 保存短文本
(2)长文本LSTM情绪分类模型
长短期记忆网络能比CNN能更好地处理时间序列任务;同时LSTM解决了RNN的长期依赖问题,并缓解了在训练过程中反向传播造成的“梯度消失”问题。因此对于长文本,本文利用LSTM进行建模分析:建立股票领域的情感词典,当长文本在经过文本分词后,利用python 中gensim的Word2Vec方法将其转换成词向量,再将样本按照一定的比例划分为训练集和测试集,通过LSTM模型得到最终的长文本情绪识别结果。
import pandas as pd
all_data= pd.read_csv(r'E:\工作\硕士\博客\博客粉丝问题\朴素贝叶斯与LSTM情感分类代码与数据\长文本带标签汇总评论.csv',encoding="ANSI")
all_data
text_list = all_data["cutword"]
text_list.head(10)
#训练词向量word2vec
from gensim.models import Word2Vecw2vmodel = Word2Vec(vector_size=100) #训练n_dim为100
w2vmodel.build_vocab(text_list)
%time w2vmodel.train(text_list,\total_examples = w2vmodel.corpus_count, epochs = 10)
# 用各个词向量直接平均的方式生成整句对应的向量
def m_avgvec(words, w2vmodel):return pd.DataFrame([w2vmodel.wv[w]for w in words if w in w2vmodel.wv]).agg("mean")
# 生成建模用矩阵
%time train_vec = pd.DataFrame([m_avgvec(s, w2vmodel) for s in text_list])
train_vec.head()
import osfrom keras.preprocessing.text import Tokenizer
from keras_preprocessing.sequence import pad_sequences
from keras.preprocessing import sequence
from keras.models import Sequential
from keras.utils import np_utils
from keras.layers.core import Dropout, Activation, Lambdafrom keras.layers import Dense, Embedding, LSTM
from keras.utils.np_utils import to_categorical
from keras.callbacks import ModelCheckpoint
from keras.models import load_model
from keras.optimizers import Adam
from sklearn.model_selection import train_test_splitx_train_lstm, x_test_lstm, y_train_lstm, y_test_lstm = train_test_split(text_list, all_data['label'], test_size = 0.4)
embedding_matrix = w2vmodel.wv.vectors#使用embedding_matrix的长度作为top_words
top_words_w2v = embedding_matrix.shape[0]#以下参数设置同上
maxlen = 100
batch_size = 32
nb_classes = 2
nb_epoch =1tokenizer1 = Tokenizer(nb_words = top_words_w2v)
tokenizer1.fit_on_texts(x_train_lstm)sequences_train1 = tokenizer1.texts_to_sequences(x_train_lstm)
sequences_test1 = tokenizer1.texts_to_sequences(x_test_lstm)x_train_seq1 = pad_sequences(sequences_train1, maxlen=maxlen)
x_test_seq1 = pad_sequences(sequences_test1, maxlen=maxlen)y_train_seq1 = np_utils.to_categorical(y_train_lstm, nb_classes)
y_test_seq1 = np_utils.to_categorical(y_test_lstm, nb_classes)
# 设置Word2Vec为embedding layer
embedding_layer = Embedding(embedding_matrix.shape[0], embedding_matrix.shape[1],weights=[embedding_matrix])# 基于Word2Vec embedding建立LSTM
model_w2v_lstm = Sequential()
model_w2v_lstm.add(embedding_layer) #选择上面设置好的Word2Vec为embedding layer
model_w2v_lstm.add(LSTM(128, dropout=0.2, recurrent_dropout=0.2))
model_w2v_lstm.add(Dense(nb_classes))
model_w2v_lstm.add(Activation('softmax'))
model_w2v_lstm.summary()
# 编译模型
model_w2v_lstm.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])
model_w2v_lstm.fit(x_train_seq1, y_train_seq1, batch_size=batch_size, epochs=nb_epoch, verbose=1)
输出结果:
(3)短文本NBM的模型构建
对于短文本,本文采用NBM模型进行建模分析,短文本进行分词、去停用词等预处理后,能得到较短的核心词汇,将核心词汇代入情感词典后,代入NBM模型即可得到最终的短文本的情绪识别结果。同样按照一定比例分为训练集和测试集。
NBM 模型基于其原理,初步通过对两变量的联合分布进行概率估算,利用现有数据集的训练来掌握此计算方法。首先是先验概率的学习,然后是条件概率分布的学习,目的是实现概率分布的匹配。由于NBM模型在处理稀疏数据时可能遇到零概率问题,这会导致朴素贝叶斯公式的计算失误,本文采用拉普拉斯平滑来解决这一问题,假设每个特征的出现频率高于实际观测值。
import pandas as pd
data1 = pd.read_csv('E:\工作\硕士\博客\博客粉丝问题\朴素贝叶斯与LSTM情感分类代码与数据\分词后的短文本.csv',encoding="ANSI")
data1
from snownlp import SnowNLP
data1['emotion'] = data1['cutword'].apply(lambda x:SnowNLP(x).sentiments)
data1
#计算积极评论与消极评论各自的数目
pos = 0
neg = 0
for i in data1['emotion']:if i >= 0.5:pos += 1else:neg += 1
print('积极评论,消极评论数目分别为:')
pos,neg
#获取消极评论数据
data2=data1[data1['emotion']<0.5]
data2.head(10)
data2.to_excel('E:\工作\硕士\博客\博客粉丝问题\朴素贝叶斯与LSTM情感分类代码与数据\短文本消极评论.xlsx',index=False)#保存数据
data3=data1[data1['emotion']>0.5]
data3.head(10)
data3.to_excel('E:\工作\硕士\博客\博客粉丝问题\朴素贝叶斯与LSTM情感分类代码与数据\短文本积极评论.xlsx',index=False)#保存数据
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import networkx as nx
plt.rcParams['font.sans-serif'] = ['KaiTi']
plt.rcParams['axes.unicode_minus'] = False
import jieba
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import MultinomialNB
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.svm import SVC
from sklearn.neural_network import MLPClassifier
pos_df = pd.DataFrame([line.replace('\n', '') for line in open('positive.txt',encoding='UTF-8').readlines()],columns=['text'])
pos_df['label']=1 #正面标签为1
neg_df = pd.DataFrame([line.replace('\n', '') for line in open('negtive.txt',encoding='UTF-8').readlines()],columns=['text'])
neg_df['label']=0 #负面标签为0
#朴素贝叶斯
model1 = MultinomialNB()
model_list=[model1]
model_name=['朴素贝叶斯']
scores=[]
for i in range(len(model_list)):model_C=model_list[i]name=model_name[i]model_C.fit(X_train, y_train)s=model_C.score(X_test, y_test)scores.append(s)print(f'{name}方法在测试集的准确率为{round(s,3)}')
#预测概率
prob = model_C.predict_proba(X_test)
#预测类别
pred = model_C.predict(X_test)
#数据透视表,混淆矩阵
table = pd.crosstab(y_test, pred, rownames=['Actual'], colnames=['Predicted'])
table
输出结果:
需要数据集的家人们可以去百度网盘(永久有效)获取:
链接:https://pan.baidu.com/s/173deLlgLYUz789M3KHYw-Q?pwd=0ly6
提取码:2138
更多优质内容持续发布中,请移步主页查看。
博主的WeChat:TCB1736732074
点赞+关注,下次不迷路!