[NLP] 利用KeyBERT從多篇文章取得關鍵字(HashTag) using Google Colab

本節將利用Google Colab平台運作KeyBERT,在指定的模型中在多篇新聞(文章)取得各篇的關鍵字

可以快速建立關建字(HashTag)

所提供都是實作,如先前還不了解上述的名詞

實作前還請到各項技術文章,從基礎閱讀套件、模型的始沒

從NLP的文章中找到Google提供無監督學習的AI技術 - BERT

並有高手利用這樣的技術發展KeyBERT 套件

設定好斷詞的方法與提供現成的模型

將文章一一帶入換出多個關鍵字,這裡開始實作

本節將用Jieba 進行中文斷詞,目前還沒看到有沒有其他更好的斷詞套件

#環境 Python 3.10.12
#安裝相關套件
pip install jieba
pip install keybert
#建立必要檔案
#建立自制斷詞檔、停用詞檔
!echo >./custom_dict.txt
!echo >./stopWords.txt
!echo >./mySentence.txt

上述檔案用途分別是

custom_dict.txt:客制文章可能的詞句,如流行用語、新事件名稱、專有名詞等 ex:以巴戰爭

stopWords.txt:停用詞內容需要從這個檔案進行,如標點符號、數字、中文語助詞等等

前置作業都準備好後,就可以開始進行文章的斷詞方式、停用詞排除等作業

供後續KeyBERT 套件使用

#先用jieba進行斷詞,因為後續會需要把斷詞做停用詞排除
#所以使用jieba.lcut,把結果轉為list
def ws_zh2(text):
  words = jieba.cut(text, cut_all =False) #不另匯入停用詞的方式
  words2 = jieba.lcut(text, cut_all =False) #如要使用停用詞要使用的方式
  # 讀入停用詞
  wordStopwords = {}.fromkeys([ line.rstrip() for line in open('./stopWords.txt', encoding='utf8') ])


  # 將分詞詞頻加入hash中
  hushWords = {}

  for word in words2:
    if word not in wordStopwords:
      if word in hushWords:
        hushWords[word] += 1
      else:
        hushWords[word] = 1
  #print('停用詞排除後:',' | '.join(hushWords))
  return hushWords
#Import進KeyBERT
from keybert import KeyBERT
from sklearn.feature_extraction.text import CountVectorizer

透過KeyBERT套件,可以自建文字轉向量的過程

本節就是透過jieba跟自建的詞、停用詞做運算後得出結果再進模型運算出所要的關鍵字

所以會利用到CountVectorizer的協助將結果向量轉進KeyBERT套件

#設定現有模型
vectorizer =CountVectorizer(tokenizer=ws_zh2)
kw_model = KeyBERT(model='paraphrase-multilingual-mpnet-base-v2') 

tokenizer:填入客製的function name

model:KeyBERT提供的模型有很多懂,如要使用中文,需要找多語言的模型才能運算出精準的結果 

模型總覽

#取得關鍵字
def getKeywords(text) :
  keywords = kw_model.extract_keywords(text,vectorizer=vectorizer)
  return keywords

而本節的目標是有多篇文章,要找出每一篇文章的關鍵字有哪些

多篇文章的建置規格是

1.篇與篇的連結以「BACK」做區分

2.每篇第一行為標題、每篇第一行以後開頭為數字自動忽略不讀取、每篇第二行固定是新聞來源所以忽略

國泰世華銀打詐 雙路並進
04:10 2023/10/12 工商時報 戴瑞瑤
「我們立志成為詐騙集團最討厭的銀行。」國泰世華銀行拿下國銀阻詐金額冠軍,
至8月底成功阻詐約7.2億元,國泰世華銀營運長吳建興接受本報專訪表示,雖阻詐
對銀行營業收入沒有直接貢獻,但有助於提高客戶對銀行的信任,作為客戶資產的
守門員,國泰世華銀對阻詐是責無旁貸。
國泰世華銀至今阻詐金額能登業界之冠,主要歸功兩作為。第一,7月成立「打詐
小組」,加強橫向聯繫。吳建興表示,雖然打詐小組是7月成立,但之前各分行、
部門本來都有在各自職責上打詐,成立小組是為加強橫向聯繫,把原來各部門在做
的,橫向串起來做任務編組,讓打詐更有效率、精準度更高。
舉例來說,國泰世華內部有洗錢防制監控中心、數據部,原本分頭進行偵測及監
控。數據中心主要藉由警示戶特徵值,來搜尋現有客戶是否有可能變為「潛在警示
戶」,而洗防中心則是看每天的金流,結合在一起後,可以做更多角度的觀察,像
是「久未往來戶」突然有大筆金流進來,以前會落在洗錢防制來監控,但現在也當
作可能是幫詐騙集團洗錢來觀察。
第一線分行也共同合作,分行過去多會教第一線行員辨別人頭戶等,但存匯部門也
會觀察警示戶態樣,雙方後來合作針對各分行主管開設「加強研習班」,透過角色
扮演訓練第一線行員當遇到客戶開戶有異狀要婉拒,但客戶咆哮時該如何應對,或
如何辨別客戶是否真的需要開戶等。藉由事前開戶、事中交易、事後交易分析,交
叉比對後讓判斷更精準,更能有效攔阻可能的詐騙。
第二,數位強化推出「國泰盾2.0」。吳建興表示,「國泰盾」建構約三~四年,
最早是用在分析信用卡盜刷,現在擴大到防詐上,過去數位使用在防詐較偏向單一
軸線看客戶交易行為可疑之處、或久未往來戶突然有大量金額進出等,現在改以
「人」為主軸做多角度分析。
吳建興說明,客戶開戶後,可能會綁手機號碼,或開通網銀、ATM操作、用信用
卡刷卡等,以客戶為主體,觀察這位客戶在每一項過程中的交易時間序、交易地
點,也去看交易金額與過去行為是否吻合,從「規則」去看交易之間是否有矛盾之
處,再來判斷是否需進一步動作,可能會暫停ATM或網銀等使用,讓有可疑行為
的客戶必須回到分行作身份驗證,才能再放行。
舉例來說,觀察車手習性,多是金流「快進快出」,多筆進、整筆領出,且10分
鐘內錢都會被轉走,若某客戶連續好幾次都是快進快出,就會被列入觀察,又或某
客戶綁定手機的地點,不在過去常交易的地點,顯示帳戶可能被他人使用,再藉由
其他數據觀察後,認為可疑的帳戶就會先將數位交易通路先關掉,客戶轉帳就需回
分行進行驗身。據國泰世華內部統計,數位交易被關掉的可疑帳戶,有高達9成以
上沒有再回到分行作身分驗證,顯示此機制有起到相當的防禦作用。BACK

國人財務調查 17%選擇躺平
04:10 2023/10/12 工商時報 戴瑞瑤
有多少人有信心存夠退休金?國泰世華銀行11日發表首份結合總體經濟模型的全
民財務健康關鍵報告,其中國人估計至少要準備1,431萬元才能退休,有29%受訪
者對未來財務有信心,可望達成退休準備,但同時有17%的受訪者決定人生將一
路「躺平」,永遠不可能財富自由。
這份報告是在今年5、6月進行問卷調查,回收有效樣本數逾2萬份,以日常生活支
出、風險抵抗力、財務信心、財務規劃、心理富足程度等五大構面進行分析,並區
分「現在」及「未來」,依分數區分財務健康類型。
調查顯示,約29%受訪者對未來財務有規劃且有信心達成設定的目標,有近六成
受訪者將退休規劃視為主要理財課題,認為至少要準備1,431萬元才能退休,退休
後每月生活費約需5萬元。
在29%未來財務有信心者中,主要可分三類型:一是「財務資優生」約17%,這
類族群目前收入不錯,且收支比控制佳、有儲蓄,投資也有明確目標並依規劃執
行,退休準備已逐漸完善,較有機會提前退休。
二是「穩健計畫通」約10%,雖現在收入中等,但生活費負擔壓力適中,收支控
制合宜,面對風險雖未完全準備好,但具備基礎金融知識,也擅於將各項財務目標
納入人生藍圖中。
三是「熱血夢想家」約2%,雖現在收入有限,但願意努力追求更好的財務狀況,
財務目標規劃清楚、投資意願高,也願意了解金融知識,是未來的「潛力股」。
令人較憂心的是約有17%受訪者是「財務躺平族」,收入不佳、也沒有追求更高
收入的慾望,常面臨收支不平衡,甚至有帳單繳款逾期的情況,且不喜歡了解金融
知識、投資意願也低,更直接「躺平」放棄做財務規劃。
國泰世華銀行資深副總經理胡醒賢表示,民眾要強化財務健康有三大關鍵,一是計
畫,制定收支儲蓄與投資目標,優先準備風險因應計畫,如規劃保障與逾六個月的
生活預備金;二是紀律,控制收入與支出,確實儲蓄,至少每季定期檢視財務計畫
執行狀態;三是技能,持續提升金融知識且實踐投資行動。BACK

自動將整批文章套入取得各篇關鍵字做hash tag

keywords = {}
#.rstrip():删除 string 字符串末尾的指定字符,默認空格、換行符號(\n)、回車符號(\r)、製表符號。
line1 = {}.fromkeys([ line.rstrip() for line in open('./mySentence.txt', encoding='utf8') ])
breaklline = False
sentence2 = ''
lineCnt = 0
for line in line1 :
  lineCnt += 1
  if len(line) > 0 and line[0].isnumeric(): #每行開頭為數字忽略
    if lineCnt > 0: lineCnt = lineCnt -1
    continue
  else:
    if len(line) == 0 :
      lineCnt = 0
      #sentence2 +='<br>'
      continue
    else :
      if 'BACK' in line : lineCnt = 0 #固定用BACK區分多篇文章
      if sentence2 != '' and lineCnt == 2 : #每篇文章的第二列忽略
        sentence2 += '|' #標題列後加「|」做為識別
      sentence2 += line
sentence2 = sentence2.split('BACK')
#print(sentence2)

for s in sentence2:
  splitS = s.split('|')
  if len(splitS) >=2 : #有標題、有內文的文章才會進行判讀
    title = splitS[0] #標題
    content = splitS[1] #內文
    keys = getKeywords(content)
    #print(keys)
    keywords[title]=keys
  else :
    print('Error:',s)
print('Result---------------------------------')
for r in keywords:
  print(r,':',keywords[r])

上述就是利用KeyBERT做文章關鍵字提取的實作

 

另外,可以將上述做圖像化(文字雲:WordCloud),讓許多高層有感的實作

能應用在例如:今日的財經新聞重點是什麼的概念中

#安裝文字雲的套件
pip install wordcloud
from wordcloud import WordCloud, STOPWORDS, ImageColorGenerator
import matplotlib.pyplot as plt

因為前面的實例是多篇文章自已有自已的關鍵字群,要畫成文字雲

就要把所有關鍵字排成一組陣列再畫圖

畫圖後顯示則要透過matplotlib.pyplot進行

def getAllKeywords(allKeys):
  all_keywords = ''
  for r in allKeys:
    #all_keywords += ' ' +
    for k in allKeys[r]:
      if all_keywords != '':
        all_keywords +=' '
      all_keywords += k[0]
      #print((k[0]))
  #print(all_keywords)
  return all_keywords

中文的文字雲都需要設定可以顯示中文的字型

通常就上網下載Google提供的免費中文字型NotoSansCJKtc就可以,但這裡走指令下載方式

#在Google Colab下載字型並安裝在Google Colab虛擬機上
!wget 'https://noto-website-2.storage.googleapis.com/pkgs/NotoSansCJKtc-hinted.zip'
!mkdir tmp
!mkdir tmp/fonts
!unzip -o NotoSansCJKtc-hinted.zip -d tmp/fonts
#Result > tmp/fonts/NotoSansMonoCJKtc-Bold.otf
#開始制作中文文字雲
#取得所有關鍵字
all_keys = getAllKeywords(keywords)
#開始製作文字雲
wc = WordCloud(font_path="./tmp/fonts/NotoSansMonoCJKtc-Bold.otf", #設置字體
  background_color="white", #背景顏色
  max_words = 2000 , #文字雲顯示最大詞數
  mask=None,       #   背景圖片
  random_state=None,               #   隨機碼生成各分詞顏色
  stopwords=None #停用字詞
  )
wc.generate(all_keys)
#詞雲轉為圖片存檔
wc.to_file("sys_wordcloud.jpg")
#顯示詞雲
plt.imshow(wc)
plt.axis("off")
plt.figure(figsize=(10,6), dpi = 100)
plt.show()

文字雲除了上述的基本呼叫方法,另可以更換圖型與顏色

先透過網址下載圖片(建議有去背的圖片)

import urllib.request
#下載圖片並另存
urllib.request.urlretrieve('url://xxx.png',"xxx_1.png")
   
#開啟圖片寫入變數img
from PIL import Image , ImageOps
img = Image.open('./xxx_1.png')
img   

文字雲讀取圖片填滿文字是找出圖片深色的部分取代,達到圖片套用的效果

可參考文字雲文件

import numpy as np
#圖片不做調整:直接圖片轉為陣列
char_mask = np.array(img) 

#圖片要做調整:將要被文字填滿的區域轉為黑色
# image_gray = img.convert('L') #背景變灰色
# image_invert = ImageOps.invert(image_gray)
# char_mask = np.array(image_invert)
im = Image.fromarray(char_mask)
im

 

完整範例at google colab