-
0 项目背景
利用LSTM对生猪市场咨询进行情感分析。由于农业领域数据集缺失,以及训练好的词向量模型,尤其是各项打好标签的数据缺失,因此本项目先借用训练好的词向量模型,获得 文本数据中的词的词向量,采用聚类分析,将文本数据集分为正向和负向两部分;继而采用LSTM模型进行分类训练,训练好的LSTM模型对每天新闻咨询进行情感分析。模型的流程如下:
-
参考资料及模型
-
北京师范大学中文信息处理研究所与中国人民大学 DBIIR 实验室的研究者开源的"chinese-word-vectors" github链接为:
-
01模型过程
-
导入必要的库
import numpy as np
import matplotlib.pylab as plt
import re
import jieba
import bz2
from sklearn.model_selection import train_test_split
from gensim.models import word2vec,KeyedVectors
import os
import pandas as pd
from tensorflow.python.keras.models import Sequential
from tensorflow.python.keras.layers import Dense,GRU,Embedding,LSTM,Bidirectional
from tensorflow.python.keras.preprocessing.text import Tokenizer
from tensorflow.python.keras.preprocessing.sequence import pad_sequences
from tensorflow.python.keras.optimizers import RMSprop,Adam
from tensorflow.python.keras.callbacks import EarlyStopping,ModelCheckpoint,TensorBoard,ReduceLROnPlateau
def clean_text(text):
text = text.replace('\n','')
text = re.sub('\d.?-\d.?-\d.?','',text)
text = re.sub('\s','',text)
text = re.sub('\d.?','',text)
text = re.sub('\.','',text)
text = re.findall('[\u4e00-\u9fa5]',text)
text = (''.join(text))
return text
fileList = os.listdir('../生猪市场资讯/猪价格网')
stop_words = pd.read_table('stopwords.txt',sep='\t',encoding='utf-8')
doc = []
for file in fileList:
try:
da1 = pd.read_table('../生猪市场资讯/猪价格网/'+file)
d = da1.iloc[:,0].tolist()
text=(''.join(d))
doc.append(text)
except:
print(file)
fileList = os.listdir('../生猪市场资讯')
stop_words = pd.read_table('stopwords.txt',sep='\t',encoding='utf-8')
for file in fileList:
try:
da1 = pd.read_table('../生猪市场资讯/'+file)
d = da1.iloc[:,0].tolist()
text=(''.join(d))
doc.append(text)
except:
print(file)
- 分词并去除停用词
cn_model = KeyedVectors.load_word2vec_format('sgns.financial.bigram',binary=False,unicode_errors="ignore")
doc_tokens = []
for t in doc:
text = clean_text(t)
text_s = jieba.cut(text)
text_clean = [word for word in text_s if word not in stop_words.aboard.tolist()]
cut_list = [i for i in text_clean]
for i,word in enumerate(cut_list):
try:
cut_list[i]=cn_model.vocab[word].index
except KeyError:
cut_list[i] = 0
doc_tokens.append(cut_list)
- 分析句子长度,通过分析句子长度分布情况获取较为合理的句子长度
因为词向量模型的训练数据并非全部来自于养殖行业咨询数据,对于一些特定的词并没有纳入词向量模型,未剔除误差,剔除文本tokens<50的文本。
#处理token较小的部分:计数<50
doc_tokens_delete=[]
num_tokens=[len(tokens) for tokens in doc_tokens]
num_tokens = np.array(num_tokens)
for i in range(len(doc_tokens)):
if num_tokens[i] < 50:
doc_tokens_delete.append(i)
doc_tokens_new=np.delete(doc_tokens,doc_tokens_delete)
``
num_tokens_new=[len(tokens) for tokens in doc_tokens_new]
num_tokens_new = np.array(num_tokens_new)
plt.hist(np.log(num_tokens_new),bins=100)
从文本tokens分布情况来看,其分布近似于正态分布,因此利用区间估计知识,将最大的文本tokens设置为:
max_tokens = int(np.mean(num_tokens_new) + 2*np.std(num_tokens_new))
- 修剪文本词库
#padding(填充)与 truncating(修剪)
doc_pad = pad_sequences(doc_tokens_new,maxlen=max_tokens,padding='pre',truncating='pre')
doc_pad[doc_pad>=num_words]=0
- 聚类分析并可视化
利用k-means算法将文本聚类分类为2类,并通过利用PCA降维将文本tonkens文本数据降维为两维,绘制散点图可视化。
#聚类分析
#聚类
#1.1 k-means
from sklearn import cluster
model_cluster = cluster.KMeans(n_clusters=2)
doc_label = model_cluster.fit(doc_pad)
# In[128]:
#聚类分析可视化
from sklearn.decomposition import PCA
model_pca = PCA(n_components=2)
model_pca.fit(doc_pad)
x=model_pca.transform(doc_pad)
x2 = []
x1=[]
for i in x:
x1.append(i[0])
x2.append(i[1])
# In[129]:
import matplotlib.pyplot as plt
import seaborn as sns
color = {0:'red',1:'blue'}
plt.scatter(x1,x2,color=[color[i] for i in doc_label.labels_],alpha=0.6)
通过上图可视化的结果来看,聚类的效果还是比较明显的,这也为后面训练LSTM模型打下了基础。
-
构建LSTM模型
-
构建词向量层
这里的目的利用文本tokens在词向量模型里面反向查找各个词的向量表示。
#构建embedding marrix
embedding_dim = 300
num_words = 50000
embedding_matrix = np.zeros((num_words,embedding_dim))
for i in range(num_words):
embedding_matrix[i,:] = cn_model[cn_model.index2word[i]]
embedding_matrix = embedding_matrix.astype('float32')
#构建词向量层、LSTM层、全连接层
model = Sequential()
model.add(Embedding(num_words,embedding_dim,weights=[embedding_matrix],input_length=max_tokens,trainable=False))
model.add(Bidirectional(LSTM(units=64, return_sequences=True)))
model.add(LSTM(units=16, return_sequences=False))
model.add(Dense(1,activation='sigmoid'))
optimizer = Adam(lr=1e-3)
model.compile(loss='binary_crossentropy',metrics=['accuracy'])
model.summary()
模型框架如下图,可以看见参数主要用于词向量层。
-构建权重存储点及训练停止条件并训练模型
采用十折交叉验证,训练20轮,步长为128.
#建立一个权重的存储点
path_checkpoint = 'sentiment_checkpoin.keras'
checkpoint = ModelCheckpoint(filepath=path_checkpoint,monitor='')
try:
model.load_weightsweights(path_checkpoint)
except Exception as e:
print(e)
earlystopping = EarlyStopping(monitor='val_loss',patience=5,verbose=1)
lr_reduction=ReduceLROnPlateau(monitor='val_loss',factor=0.1,min_lr=1e-8,patience=0,verbose=1)
callbacks=[earlystopping,checkpoint,lr_reduction]
#training: 7:3的比例划分测试集和验证集
(doc_pad_train ,doc_pad_test,doc_label_train,doc_label_test) = train_test_split(doc_pad,doc_label.labels_,test_size=0.3)
model.fit(doc_pad_train,doc_label_train,validation_split=0.1,epochs=20,batch_size=128,callbacks=callbacks)
训练过程如下图所示
- 验证
模型结果输出为一个概率值,在此我们认为result<0.5即为属于分类集0类,反之即为分类集1类。
result=model.predict(doc_pad_test)
for i in range(len(result)):
if result[i]< 0.5:
result[i] = 0
else:
result[i] =1
acc=0
for i in range(len(doc_pad_test)):
if doc_label_test[i] == result[i]:
acc +=1
acc/300
从最后的准确率来看,LSTM模型准确率可达97%,模型的结果可观。
-
03结语
-
农业领域开展人工智能技术应用尚处于起步阶段,缺少数据集,只能寄希望与其他领域已经开放的标准数据集或者预训练模型;
-
本项目采用聚类的方式获得样本集的原始标签,可解释性较差,后续将利用其他行业已有的用于文本分类或者情感分析的标准数据集 ,探索建议迁移学习模型的可能。