Python實作新聞情緒分析(Sentiment Analysis)

什麼是情緒分析(Sentiment Analysis)?

情緒分析就是針對文本背後所詮釋的情緒進行分析。近來年機器學習和資料探勘正廣為學界和業界使用,而情緒分析則類似於資料探勘中的文字探勘,計算文本中各個字詞所代表的情緒分數,解讀進而轉化成資訊。

近年來比較常見的作法是針對新聞內容分析,投資的世界其實是一場資訊戰,投資人透過會計資訊、技術線圖的指標…等資訊進行投資決策,而情緒分析就像是伴隨科技更為進步的一種分析方法,針對字詞傳達出樂觀(Optimistic)、悲觀(Pessimistic)的情緒來判斷標的價格變化。

Python套件-Jieba結巴斷詞

在文本分析中,斷詞是一個大議題,因為沒辦法正確的斷詞,就得不出正確的資訊,而中文斷詞在執行上有個相當窒礙難行的地方,在於中文的詞與詞之間並沒有明顯的分隔。

舉例來說,市場預期未來六個月將持續高通膨。這句話就是許多詞的組合,例如市場(名詞)、預期(動詞)、未來(名詞)...等等,但如果寫成英文呢

英文: Market expects high inflation rate will last six months.

詞與詞之間有明顯的空白分隔,因此可以輕易地區分出這句話中共有多少詞,但中文的區隔邏輯是不一的。

Jieba套件就是用於解決中文斷詞的問題,來看下面的例子。

jieba斷詞程式碼範例

導入了結巴斷詞套件後,設定要用來判斷字詞的辭典,進行斷詞。

import jieba
jieba.set_dictionary('./dict.txt.big')
 
text = "市場預期未來六個月將持續上漲"
seg_list = jieba.cut(text, cut_all=True, HMM=True)
print('/'.join(seg_list))
 
# 市場/預期/未來/六個/六個月/將/持續/上漲

上方cut()函數中有個參數cut_all,當設定為True時是全模式,設定為False的時候是精確模式。

精確模式不會有同的字分到兩個詞的問題,全模式則是將所有可能都列出來。

seg_list = jieba.cut(text, cut_all=False, HMM=True)
print('/'.join(seg_list))

# 市場/預期/未來/六個月/將/持續/上漲

透過斷詞套件的輔助,解決了困難的斷詞作業,接著就能用文本中的詞句來計算情緒分數。

情緒分數計算

計算情緒分數的作業上,還缺一個很重要的元素,就是字詞所隱含的情緒方向和分數,在這使用台灣大學情緒字典(NTUSD),裏頭提供正面詞彙和負面詞彙的字典。

台大自然語言處理實驗室中還提供了英文字詞及對應的分數,裏頭有許多很棒的資源可以使用,提供參考。

接著隨機挑一篇財金新聞來做分析,原文連結在這

article = "台股在昨日成功站上萬七關卡後,今日早盤雖穩守萬七,仍再度陷入狹幅震盪整理,航運股相對弱勢,靠著電子股持續挺出,尤其 IC 載板、砷化鎵和電池材料族群相對強勁來維繫多頭動能,法人認為,上方有季線和半年線反壓,但目前成交量僅 2900 億元左右,仍有待時間化解套牢賣壓。由於外資上修欣興明年獲利,並看好 ABF 產業仍處在上升循環,ABF 載板三雄早盤相當強勢,欣興挾著財報利多直奔漲停,景碩漲 6%,南電漲近半根停板。砷化鎵族群也再度成為盤面焦點,穩懋、宏捷科均漲超過半根停板,全新漲近 4%。電池材料股續強,立凱 - KY 漲停,美琪瑪漲逾 2.5%,康普續漲 1.5% 之上。IC 設計相關個股表現也強勢,信驊一度大漲近 9%,立積漲超過 7%,普誠、聚積、驊訊、創惟和愛普等漲半根停板上下,智原、九暘、昇佳電子、茂達、九齊等漲逾 2%。不過,航運族群持續成為賣壓來源,新興、中航和裕民跌超過 3%,四維航、慧洋 - KY、志信、正德、萬海和台驊投控跌 2% 上下,長榮跌逾 1.5%,台航、中櫃、陽明、榮運、中菲行、遠雄港等均遭壓在盤下。統一投顧指出,短期均線持續走揚,但月線和季線仍處下行趨勢,9 月以來的上檔套牢賣壓需時間化解,應提防短線反彈結束。統一投顧也提醒,儘管近來美股財報獲利優於預期比例高達 8 成,激勵美股走勢,但中國限電問題對全球供應鏈的衝擊充滿不確定性,通膨和縮減購債議題不確定性仍存,仍須小心系統性風險。元大投顧則認為,大盤明顯已陷入均線糾結所造成萬七關卡的迷思,本波指數碰到季線下穿半年線處即萬七附近,多空呈現拉鋸,所幸回檔測試賣壓,並未失守月線,短線可以 5 日線做為強弱研判依據,有待放量上攻,否則整理期將拉長。"

接著讀取正負面詞彙的資料

with open('NTUSD_positive_unicode.txt', encoding='utf-16', mode='r') as f:
   positive_words = []
   for l in f:
       positive_words.append(l.strip())

with open('NTUSD_negative_unicode.txt', encoding='utf-16', mode='r') as f:
   negative_words = []
   for l in f:
       negative_words.append(l.strip())

有了文本和字典後,就能透過剛剛介紹的jieba套件來完成。

score = 0
jieba_result = jieba.cut(article, cut_all=False, HMM=True)
for word in jieba_result:
   if word in positive_words:
       score += 1
   elif word in negative_words:
       score -= 1
   else:
       pass

   print(f'詞彙:{word}, 總分:{score}')

# 輸出結果
"""
詞彙:成功, 總分:1
詞彙:陷入, 總分:0
詞彙:獲利, 總分:1
詞彙:成為, 總分:2
詞彙:超過, 總分:1
詞彙:超過, 總分:0
詞彙:成為, 總分:1
詞彙:超過, 總分:0
詞彙:提防, 總分:-1
詞彙:反彈, 總分:-2
詞彙:獲利, 總分:-1
詞彙:優於, 總分:0
詞彙:激勵, 總分:1
詞彙:問題, 總分:0
詞彙:衝擊, 總分:-1
詞彙:縮減, 總分:-2
詞彙:小心, 總分:-1
詞彙:明顯, 總分:0
詞彙:陷入, 總分:-1
"""

在上面的例子簡化了計算的方法,直接用正面字詞為1分,負面則為-1分的方式計算,實際上還有許多的計算方法,而不同的詞隱含的分數也可能多寡不一。

經過斷詞和情緒字詞判斷後,得出本篇新聞的情緒分數為-1,這篇新聞屬於盤勢解析的分類,而綜合許多盤勢解析的新聞之後,就能簡易的計算出當前市場投資人情緒分數。

About author
主題大多圍繞Python相關。ycy.tai@gmail.com
Comments