今天小編打算補(bǔ)充一下上一篇上市公司歷史新聞數(shù)據(jù)分析(一)的部分內(nèi)容樱蛤,以及進(jìn)一步闡述如何利用SVM和RandomForest做文本分類及效果對(duì)比痊剖。
? ? ? ?上一篇文章有提到用LDA主題模型做文本特征抽取鬼雀,其實(shí)LDA主要是將“Document x Word”矩陣分解為“Document x Topic”矩陣和“Topic x Word”矩陣。通俗的說(shuō)敛滋,LDA是為了說(shuō)明某一系列的Words放在一起構(gòu)成的Document很有可能在描述某一類Topic寸爆。下圖顯示了在實(shí)驗(yàn)中,將文本集轉(zhuǎn)為lsi向量或lda向量的大致流程:
????????這里順便說(shuō)一下word2vec和doc2vec衩辟,兩者都可以做特征抽取螟炫,但實(shí)驗(yàn)效果都沒(méi)有LDA好,因此也就不描述實(shí)驗(yàn)艺晴。word2vec也叫word embeddings昼钻,就是根據(jù)詞語(yǔ)與上下文詞語(yǔ)的關(guān)系(相關(guān)情況),將已分詞的文本進(jìn)行訓(xùn)練封寞,得到每個(gè)詞的向量表示然评,即詞向量(稠密向量,distributed representation)狈究,并且其中相近意義的詞語(yǔ)將被映射到向量空間中相近的位置碗淌。主要有以下幾點(diǎn)應(yīng)用:(1)計(jì)算詞語(yǔ)間的相似度,比如同樣在城市主題下,衡量“北京”更接近“上汗彷海”還是“廣州”风喇;(2)計(jì)算詞語(yǔ)的類比關(guān)系,比如“King”+“Woman”-“man”近似于“Queen”缕探;(3)計(jì)算文本間的相似度魂莫。word2vec有兩種訓(xùn)練算法,一個(gè)是CBOW模型爹耗,一個(gè)是skip-gram模型耙考,詳細(xì)解釋可參考鏈接<1>。doc2vec又叫做paragraph2vec或者sentenceembeddings潭兽,是一種非監(jiān)督式算法倦始,可以獲得句子/段落/文檔的向量表達(dá),是word2vec的拓展山卦,詳細(xì)解釋可參考鏈接<2>鞋邑。
????????在進(jìn)行文本特征選擇后,接下來(lái)就是文本表示账蓉,也就是把非結(jié)構(gòu)化的文本轉(zhuǎn)為計(jì)算機(jī)可以處理的結(jié)構(gòu)化數(shù)據(jù)形式枚碗。在Gensim的官方教程(參考鏈接<3>)中有提到如何將Gensim類型數(shù)據(jù)轉(zhuǎn)為Numpy和Scipy類型數(shù)據(jù),轉(zhuǎn)換的目的自然是為了適應(yīng)更多機(jī)器學(xué)習(xí)庫(kù)铸本。在模型上肮雨,我選擇了scikit-learn的SVM和RandomForest做對(duì)比。下面是一部分簡(jiǎn)約代碼展示如何用GridSearchCV做參數(shù)優(yōu)化:
fromsklearnimportsvm
fromsklearn.ensembleimportRandomForestClassifier
fromsklearn.externalsimportjoblib
fromsklearn.model_selectionimportGridSearchCV
fromsklearn.metricsimportclassification_report
scores = ['precision']#['precision','recall']
tuned_parameters_svm = {'kernel': ['rbf'],'gamma': [10,20,50,100,150,200], \
'C': [10,15,20,30,50,100]}
tuned_parameters_rdf = {"n_estimators": [10,20,50,80,100],"criterion": ["gini","entropy"], \
"min_samples_leaf": [2,4,6,10,20]}
forscoreinscores:
ifnotos.path.exists('./svm.pkl'):#或'./randomforest.pkl'
clf = GridSearchCV(svm.SVC(), tuned_parameters_svm, cv=5, scoring='%s_weighted'% score)# 構(gòu)造這個(gè)GridSearch的分類器,5-fold
# clf = GridSearchCV(RandomForestClassifier(random_state=14), tuned_parameters_rdf, cv=5, scoring='%s_weighted' % score) # 構(gòu)造這個(gè)GridSearch的分類器,5-fold
clf.fit(train_X, train_Y)# 只在訓(xùn)練集上面做k-fold,然后返回最優(yōu)的模型參數(shù)
joblib.dump(clf,'./svm.pkl')#或'./randomforest.pkl'
else:
clf = joblib.load('./svm.pkl')
print(clf.best_params_)# 輸出最優(yōu)的模型參數(shù)
# for params, mean_score, scores in clf.grid_scores_:
# ? print("%0.3f (+/-%0.03f) for %r" % (mean_score, scores.std() * 2, params))
train_pred = clf.predict(train_X)
test_pred = clf.predict(test_X)# 在測(cè)試集上測(cè)試最優(yōu)的模型的泛化能力.
print(classification_report(test_Y, test_pred))
其中箱玷,scores是優(yōu)化目標(biāo)怨规,可以按照準(zhǔn)確率(precision)或者召回率(recall),當(dāng)然還有別的锡足;tuned_parameters_svm(tuned_parameters_rdf)表示選擇的參數(shù)以及參數(shù)優(yōu)化范圍波丰;訓(xùn)練好的模型最好還是用joblib給保存起來(lái);最后用classification_report打印結(jié)果舱污,如下圖:
依然用山西焦化(600740)作為測(cè)試股票呀舔。首先從所收集的新聞數(shù)據(jù)中抽取與600740相關(guān)的新聞存到新的數(shù)據(jù),并且依據(jù)這些數(shù)據(jù)生成600740的新聞字典以及bow向量扩灯,然后用LDA抽取主題模型向量,并保存霜瘪。最后設(shè)置30個(gè)Epoch珠插,來(lái)對(duì)比SVM和RandomForest在測(cè)試集的分類效果,如下圖:
可見(jiàn)SVM在實(shí)驗(yàn)表現(xiàn)優(yōu)于RandomForest颖对。
????????模型訓(xùn)練好了捻撑,當(dāng)然得測(cè)試一下實(shí)際效果。由于新聞數(shù)據(jù)的收集只是到最近的2月3日,所以用2月3日之后的關(guān)于山西焦化的新聞數(shù)據(jù)進(jìn)行測(cè)試顾患。這里選了新浪財(cái)經(jīng)在2月6日的一篇新聞(網(wǎng)址是參考鏈接<5>)番捂,標(biāo)題是《中央、地方支持政策頻出 煤炭行業(yè)站上了風(fēng)口》江解,和金融界在2月5日的一篇新聞(網(wǎng)址是參考鏈接<6>)设预,標(biāo)題是《[山西焦化]郭文倉(cāng)到終點(diǎn)工程項(xiàng)目督導(dǎo)檢查》,下面是一段簡(jiǎn)約代碼和輸出結(jié)果:
Obj = TextMining(IP="localhost",PORT=27017)
doc = ['中央犁河、地方支持政策頻出,煤炭行業(yè)站上了風(fēng)口 券商研報(bào)浩如煙海鳖枕,投資線索眼花繚亂,第一財(cái)經(jīng)推出\
《一財(cái)研選》產(chǎn)品桨螺,挖掘研報(bào)精華宾符,每期梳理5條投資線索,便于您短時(shí)間內(nèi)獲取有價(jià)值的信息灭翔。專業(yè)團(tuán)隊(duì)\
每周日至每周四晚8點(diǎn)準(zhǔn)時(shí)“上新”魏烫,...'
,\
'郭文倉(cāng)到重點(diǎn)工程項(xiàng)目督導(dǎo)檢查 2月2日,公司黨委書(shū)記、董事長(zhǎng)肝箱、總經(jīng)理郭文倉(cāng),公司董事,股份公司副\
總經(jīng)理哄褒、總工程師、郭毅民,股份公司副總經(jīng)理張國(guó)富狭园、柴高貴 ...'
]
token = Obj.ge2.jieba_tokenize(doc)#分詞
dictionary = corpora.Dictionary.load('./600740_dict.dict')#加載歷史文檔字典
bowvec_doc = [dictionary.doc2bow(text)fortextintoken]#生成新文檔的bow向量
bowvec_all = list(corpora.MmCorpus('D:\\stock_dict_file\\600740\\600740_bowvec.mm'))#加載歷史文檔bow向量
bowvec_all.extend(bowvec_doc)#更新歷史文檔bow向量
_, NewmodelVec = Obj.ge2.CallTransformationModel(dictionary,bowvec_all,modelType='lda',\
tfDim=200,renewModel=False,modelPath='D:\\stock_dict_file\\600740\\')#生成新的lda向量
NewCSRMatrix = Obj.ConvertToCSRMatrix(NewmodelVec)#將新的lda向量轉(zhuǎn)為scipy類型的稀疏矩陣
clf = joblib.load('D:\\stock_dict_file\\600740\\600740_svm.pkl')#加載訓(xùn)練好的svm模型進(jìn)行分類預(yù)測(cè)
fori, newsinenumerate(doc):
ifclf.predict(NewCSRMatrix[i-2,:])[0] ==1:
print('《'+ news.split(' ')[0] +"》"+'是利好消息 ...')
elifclf.predict(NewCSRMatrix[i-2,:])[0] ==-1:
print('《'+ news.split(' ')[0] +"》"+'是利空消息 ...')
else:
print('《'+ news.split(' ')[0] +"》"+'是中立消息 ...')
下面是山西焦化(600740)最近幾天的股票價(jià)格读处,可見(jiàn)2月5日之后股票價(jià)格下跌,當(dāng)然也不排除這幾天的下跌多數(shù)是由系統(tǒng)性風(fēng)險(xiǎn)造成唱矛。但總的來(lái)說(shuō)罚舱,這次的研究還是蠻具有實(shí)戰(zhàn)價(jià)值。
參考鏈接:
<1> http://blog.csdn.net/u014595019/article/details/51884529
<2>?https://www.cnblogs.com/maybe2030/p/5427148.html
<3>?https://radimrehurek.com/gensim/tut1.html#compatibility-with-numpy-and- ? ? ? ?scipy
<4>?http://blog.csdn.net/lixiaowang_327/article/details/53434744
<5>?http://finance.sina.com.cn/stock/hyyj/2018-02-04/doc- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ifyreyvz9053830.shtml
<6>?http://stock.jrj.com.cn/2018/02/05000024071826.shtml