Photo by Joshua Hoehne / Unsplash

[NLP]實作:如何抽取繁體中文文章關鍵字

NLP Jun 19, 2023
快速導覽

前言

今天來介紹一個關鍵字抽取方法KeyBERT,雖然目前已經有許多抽取關鍵字的方法,像是TF-IDF、Rake、TextRank和TAKE……等等,KeyBERT的作者希望能夠創造更為簡單易用且輕量的方法,它使用BERT embedding和cosince similarity去尋找文章中最為重要的字詞,它的概念非常簡單,就是將整篇文章與每個字詞一一的計算相似度,與整篇文章相似度愈高的字詞代表是越重要的關鍵字。

以下會介紹如何使用KeyBERT來抽取繁體中文文章中的關鍵字,分為三個部分進行介紹。所有程式碼都在Colab中,大家可以跟著一起實作。

  • 第一部分為中文斷詞方法介紹,中文在抽取關鍵字前需要先進行斷詞,中文不像英文可以直接以空白作為分隔形成單字,像是"我喜歡你"斷完詞後會是"我"、"喜歡"、"你"。
  • 第二部分為透過KeyBERT模組來進行關鍵字抽取。
  • 第三部分介紹embedding模型抽換的方法,除了使用預設的embedding模型,還可以從Hugging Face網站上挑選喜歡的預訓練語言模型來抽換。
整篇文章與每個字詞一一的計算相似度

中文斷詞

這裡使用CKIP Tagger來進行斷詞,CKIP Tagger除了斷詞外,還能用來詞性標註和實體辨識,我們這邊只使用它的斷詞功能,另外兩個功能我們下次再來進行介紹。

  1. 安裝ckiptagger
pip install -U ckiptagger[tf,gdown]

2. 讀取套件

from ckiptagger import data_utils, construct_dictionary, WS, POS, NER

3. 下載模型,可選擇其中一個來源下載,有時會因為下載次數過多無法下載,可以嘗試切換下載資源。

# data_utils.download_data_gdown("./") # gdrive-ckip
data_utils.download_data_url("./") # iis-ckip

4. 讀取模型,Ckip Tagger包含斷詞(WS)、詞性標註(POS)、和實體辨識(NER)。詞性標註是將斷完的詞標註詞性,ex:我(N) 喜歡(V) 你(N)。實體辨識是從句子中挑選出實體,像是人名、組織名稱等等。這邊只用到斷詞,所以只讀取WS。

ws = WS("./data")
# pos = POS("./data")
# ner = NER("./data")

5. 文章範例

docs="台裔球星林書豪加盟高雄17直播鋼鐵人,12日首秀拿下21分,而個人單場13助攻追平聯盟紀錄,獲選台灣職籃P.LEAGUE+單週MVP,也是鋼鐵人本季首名獲此殊榮的球員。林書豪在球迷引頸期盼下,12日在主場高雄市鳳山體育館首度披上鋼鐵人7號戰袍出賽,率隊以95比80擊敗福爾摩沙台新夢想家,收下本季第3勝,終止4連敗。林書豪首秀先發上陣,吸引滿場超過5000名球迷進場,出賽逾41分鐘,繳出21分、13助攻的「雙10」成績,其中單場助攻數,更一舉追平台灣職籃P.LEAGUE+(簡稱PLG)紀錄。PLG聯盟今天公布第15週單週MVP,在球迷票選的部分,林書豪獲得66.9%壓倒性的得票率,成為鋼鐵人本季首名獲選單週最有價值球員(MVP)的球員。鋼鐵人接下來將展開客場之旅,18日將作客台中洲際迷你蛋,對手同樣是夢想家,鋼鐵人在林書豪帶領下,將力拚2連勝。"

6. 進行斷詞,ws函數可以一次傳入多篇文章進行斷詞,所以參數需要以list的格式輸入,再以[0]取出第一篇文章斷完詞的結果。

ws([docs])[0]
>>>
[台裔,球星,林書豪,加盟,高雄,17,直播,鋼鐵人,,,12日,首秀,拿下,21,分,,,而,個人,單,場,13,助攻,追平,聯盟,紀錄,,,獲選,台灣,職籃,P.,LEAGUE+,單,週,MVP,,,也,是,鋼鐵人,本,季,首,名,獲,此,殊榮,的,球員,。,林書豪,在,球迷,引頸,期盼,下,,,12日,在,主場,高雄市,鳳山,體育館,首度,披上,鋼鐵人,7,號,戰袍,出賽,,率隊,以,95,比,80,擊敗,福爾摩沙,台新,夢想家,,,收下,本,季,第3,勝,,,終止,4,連敗,。,林書豪,首秀,先發,上陣,,,吸引,滿,場,超過,5000,名,球迷,進場,,,出賽,逾,41,分鐘,,,繳出,21,分,、,13,助攻,的,「,雙,10,」,成績,,,其中,單場,助攻數,,,更,一舉,追平,台灣,職籃,P,.,LEAGUE+,(,簡稱,PLG,),紀錄,。,PLG,聯盟,今天,公布,第15,週,單,週,MVP,,,在,球迷,票選,的,部分,,,林書豪,獲得,66.9%,壓倒性,的,得票率,,,成為,鋼鐵人,本,季,首,名,獲選,單,週,最,有,價值,球員,(,MVP,),的,球員,。,鋼鐵人,接下來,將,展開,客場,之,旅,,,18日,將,作客,台中,洲際,迷你蛋,,,對手,同樣,是,夢想家,,,鋼鐵人,在,林書豪,帶領,下,,,將,力拚,2,連勝,。]

KeyBERT使用

斷完詞後,我們可以開始進行關鍵字抽取了。

  1. 安裝KeyBERT
pip install keybert

2. 讀取KeyBERT和CountVectorizer套件,CountVectorizer是用來計算字詞詞頻用的。

from keybert import KeyBERT
from sklearn.feature_extraction.text import CountVectorizer

3. 改寫剛剛上面斷詞時所使用的ws函式,將斷詞函式改寫成只對單一篇文章斷詞,並回傳斷詞結果。

def ws_zh(text):
    words = ws([text])
    return words[0]

4. 創建CountVectorizer

vectorizer = CountVectorizer(tokenizer=ws_zh)

5. 使用KeyBERT進行關鍵字抽取,得到關鍵字結果及關鍵字分數。

kw_model = KeyBERT()
keywords = kw_model.extract_keywords(docs,vectorizer=vectorizer)
keywords

>>>
[('p.league+', 0.3402),
 ('追平', 0.2293),
 ('首秀', 0.2227),
 ('林書豪', 0.2156),
 ('連勝', 0.1852)]

模型抽換

剛剛的關鍵字抽取,是使用預設的embedding模型,embedding模型會大大影響關鍵字的結果,我們從Hugging Face挑選一個多語言的embedding模型,可以看到抽取出來的關鍵字有不同的結果,大家也可以從Hugging Face挑選自己喜歡的模型來抽換。

kw_model = KeyBERT(model='distiluse-base-multilingual-cased-v1')
keywords = kw_model.extract_keywords(docs,vectorizer=vectorizer)
keywords

>>>
[('林書豪', 0.286),
 ('鋼鐵人', 0.2723),
 ('職籃', 0.2184),
 ('鳳山', 0.2178),
 ('體育館', 0.1903)]

相信大家都已經學會使用KeyBERT來抽取中文文章的關鍵字,完全沒碰過自然語言處理的朋友可能會不知道什麼是embedding,embedding是將文字轉換成向量,讓電腦或機器能夠讀懂人類語言的一種方式,embedding的模型有許多種,之後再寫一篇文章詳細的介紹文字嵌入(word embedding)。


Tags