零、引

注:本篇仅记录我一次构建NLP情感向量模型的经历,并非技术教程,如有错漏欢迎指出。

毕设脑子一抽,设计了个巨复杂的系统,简单来说就是,构建一个以微服务为基础,Nacos作为注册中心,Thrift作为RPC框架,采用Laravel、Vue的全分离式前后端集群,具有CDN与对象存储文件服务的网络优化,使用Redis、MySQL、MongoDB集群,具有数据抓取与清洗服务,核心算法采用LSTM与BERT等NLP学习的综合网络股票信息平台。

好吧,其实我自己也不是很理解为什么我做了这么个玩意儿,本来是纯粹想着秀技,结果秀着秀着把自己秀进去了,虽然工作已经稳了,其他事情也基本没了,但是这么个玩意儿说实话在俩月内写完也确实不太现实emm。

不过好在,至少在中期答辩之前把整体框子搭出来了,也顺便炼了一枚小丹(其实是两枚),所以在此简单记录一下炼丹的过程,由于我本人钻研的是后端,所以对于机器学习并不甚了解,所以只懂得浅薄道理,如果有错漏欢迎大家指正。

至于我毕设系统的其他部分,由于是个天坑,所以博客文章这边准备之后再慢慢填(当然也有可能彻底鸽掉)

一、环境搭建

首先当然是对算法的选择,因为是对网络股评进行分析,所以肯定是NLP相关的算法。

我在上一家公司的时候做过医疗方向上的NLP系统,当时用的是BERT模型进行的病历标注,所以这次我一开始想的是用BERT先做一次词性标注,然后再聚类成不同维度,根据维度数据构建一个股价相关回归模型,简单尝试了一下,发现可供训练的数据集特别少,而且实在是太麻烦了,一两天内完成属实不太现实,于是就直接做情感分析模型了。

翻了几篇论文,最后决定利用分词+词向量+LSTM的方式构建情感分析模型。分词就不用说了,自己练太费劲,直接用jieba,词向量也好办,word2vec方便的很,最后就是LSTM网络的构建,我选择的是直接用TensorFlow和Keras构建神经网络,方便,快捷,主要是不需要动脑(

既然选择了tf,那就先进行一个环境的搭建。python自不必说,由于我电脑不知道重装过多少次了,需要先装一下轮子。TensorFlow在高版本上直接默认的就是GPU版本,不像以前,要安装tensorflow-gpu,现在直接安装tensorflow就可以了。

其他的都还好说,最坑的其实是word2vec,这个需要源码编译一下,所以需要装gcc。因为我一直用的都是CLion+cygwin,所以自然gcc没什么问题,本来我是这么想的。结果我给忘了我上次重装完系统就只装了Visual Studio,没装cygwin,我还研究了半天我gcc哪去了,后来才想起来没装,属于是降智了。

requirements.txt如下

numpy
matplotlib
pandas
jieba
Cython
word2vec
tensorflow
gensim
scikit-learn
python-dotenv
requests
keras
Flask
BeautifulSoup4
html5lib

python依赖装好之后,简单整一下cuda,其实这块TensorFlow官网GPU支持文档已经非常详细了,按着一步一步走就行了。

首先是GPU驱动,CUDA 11.2要求驱动在450.80.02以上版本,这对于我一个常年保持最新驱动的人来说那肯定是没什么问题,不过我的不是studio驱动,是game驱动,不过为了跑个模型就换成studio我觉得不值当,就没动,采用的是512.59版本。

1651552241028.png

然后去英伟达官网下载一下CUDA工具包,因为工具包是附带CUPTI的所以不需要额外考虑,我下载的版本是11.6.2的最新版。

最后是安装cuDNN,这个安装起来稍微麻烦一点,下载归档之后将bin,include,lib文件夹里的全部文件放到CUDA安装路径下对应的文件夹里就行,需要注意对应的版本。

最后还可以装一下TensorRT,我嫌麻烦就没装。

安装完之后用命令行工具检查一下情况。

nvidia-smi

1651552644239.png

二、数据集

构建好了学习环境,我简单找了一下数据集,在GitHub上面找到了一个中文NLP的训练集收集的仓库,因为时间紧任务重,就直接拿来用了。其实一开始我下载的是清华的语料库,下载下来发现只有分类标注,就放弃了,后来选择了两个微博的情感向量标注数据集。

因为这方面训练用的数据结构比较简单,所以数据集还算工整。用panda简单处理一下就可以直接用了,当然我没做数据清洗,懒了。

1651553001197.png

1651553044830.png

数据集有了之后,用jieba简单做一下分词,就可以进行网络的构建了。(其实还应该清洗一下数据的,但是实在是来不及了)

# 引入轮子
import jieba
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from gensim.models.word2vec import Word2Vec
from sklearn.model_selection import train_test_split
from keras.models import Sequential
from keras.layers import Dense, LSTM, Embedding

# panda加载数据
df = pd.read_csv('data/weibo_senti_100k.csv')

# 利用plot绘制数据集分布
df.label.value_counts().plot(kind='pie', autopct='%0.05f%%', labels=['negative', 'positive'],
                             colors=['#f48fb1', '#ccff90'])
plt.savefig("out/data.png")
plt.show()
plt.clf()

# 对数据集进行jieba分词
df = df.sample(frac=1)
word_cut = lambda x: jieba.lcut(x)
df['words'] = df["review"].apply(word_cut)
x = df["words"]

三、浅层网络构建

数据集准备好了之后,先利用word2vec简单构建一下浅层网络,利用训练集先构建一个简单的词向量模型,将词语转换为词向量方便后面训练。

# word2vec模型
w2v = Word2Vec(vector_size=300,min_count=10)
w2v.build_vocab(x)
w2v.train(x,
          total_examples=w2v.corpus_count,
          epochs=20)

# 保存模型
w2v.save('model/w2v_model.pkl')

# 将文本转化为向量的方法
def average_vec(text):
    vec = np.zeros(300).reshape((1, 300))
    for word in text:
        try:
            vec += w2v.wv[word].reshape((1, 300))
        except KeyError:
            continue
    return vec

# 将词向量保存为 Ndarray
x_vec = np.concatenate([average_vec(z) for z in x])
y = pd.get_dummies(df['label']).values

完成了word2vec模型训练并获取了词向量后,利用sklearn构建训练集,训练集80%,测试集20%。

X_train, X_test, y_train, y_test = train_test_split(x_vec, y, test_size=0.2)

四、LSTM网络构建

通过Keras快速构建一个简单的LSTM网络模型

model = Sequential()
model.add(Embedding(100000, 100))
model.add(LSTM(100, dropout=0.2, recurrent_dropout=0.2))
model.add(Dense(2, activation='softmax'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
model.summary()

五、模型训练与保存

现在,我们对上面的模型利用构建好的测试集进行一个丹的炼,然后把损失函数和准确率绘图。这里我训练次数epochs选择40次,批次大小128,这个批次大小正好吃掉我的10G显存,整体训练下来耗时大概需要10小时左右。

# 训练参数
epochs = 40
batch_size = 128

# 模型训练
history = model.fit(X_train,
                    y_train,
                    epochs=epochs,
                    batch_size=batch_size,
                    validation_split=0.2)
history_dict = history.history
history_dict.keys()

#利用plot绘制损失与准确率
acc = history_dict['accuracy']
val_acc = history_dict['val_accuracy']
loss = history_dict['loss']
val_loss = history_dict['val_loss']

epochs = range(1, len(acc) + 1)

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.savefig("out/loss.png")
plt.show()
plt.clf()

plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.savefig("out/accuracy.png")
plt.legend()
plt.show()

# 进行一个模型的保存
model.save("model/svm_model")

六、验证结果与测试

通过上面的训练后,最终得出了一个acc 0.88的模型,还算理想,毕竟是在答辩前赶出来的,也不能奢望什么。

1651553912599.png

1651553928857.png

然后简单写一下测试方法,对模型进行一个简单的测试

import jieba
import numpy as np
import keras.models
from gensim.models.word2vec import Word2Vec

def average_vec(words):
    w2v = Word2Vec.load('model/w2v_model.pkl')
    vec = np.zeros(300).reshape((1, 300))
    for word in words:
        try:
            vec += w2v.wv[word].reshape((1, 300))
        except KeyError:
            continue
    return vec

def model_predict(string):
    words = jieba.lcut(str(string))
    words_vec = average_vec(words)
    keras.models.logging.set_verbosity(keras.models.logging.ERROR)
    model = keras.models.load_model("model/svm_model")
    result = np.argmax(model.predict(words_vec))
    if int(result) == 1:
        return "正向"
    else:
        return "负向"

while True:
    text = input("input> ")
    res = model_predict(text)
    print(text + " | " + res)

1651554031474.png

总体上看,准确率其实一般,因为训练集并不是专业的金融数据,有太多奇怪的数据在里面。只能说,凑合用。

七、模型的使用

最后,利用Flask构建一个简单的HTTP API服务,这部分具体的代码我已经放到我的Git上了,感兴趣可以自行查看,我这里只放一下Postman的测试了。

1651554280773.png

最后与其他服务进行一个联调,带有环境的界面大概是这个样子

1651554463005.png

八、结语

其实整个项目现在都是赶鸭子上架的状态,写的很烂,所以就这样吧。

本毕业设计项目源代码仓库地址:UtopiaXC's GitLab - UtopiaXC Graduation Project

本模型仓库:UtopiaXC's GitLab - Stock Model Service

 九、参考与感谢

看了很多篇论文,就不放在这了,以后会写在毕业论文的参考文献里面,至于代码,因为大量参考了别人的代码,所以这里放出来源

基于LSTM的电商评论情感分析-TensorFlow2实现(内附源码)【自然语言处理NLP-100例】

本篇内容为原创内容,采用CC BY-NC-SA 4.0协议许可
2022-05-03 13:05
UtopiaXC
于大连


尽管如此,世界依旧美丽