清理CKIP-Transformer輸出結果的技巧與程式範例

閱讀時間約 20 分鐘

CKIP-Transformer是一個繁體中文的自然語言處理(NLP) 模型,雖然速度偏慢,但是在切詞、詞性標記和命名實體識別等方面都有很優秀的表現。然而,CKIP-Transformer 的輸出並非完美無缺,有時需要額外的資料清理才能進行後續應用。在這篇文章中,我將分享一些清理CKIP-Transformer輸出結果的技巧與Python程式範例。

您也可以在這份官方 PDF 文件中查看詞性(parts of speech)的定義。我也在Python程式碼中將所有詞性定義寫成一個list,這樣使用上更為方便。

import pandas as pd
import re
from ckip_transformers.nlp import CkipWordSegmenter, CkipPosTagger, CkipNerChunker


def str_remove_emoji(text):
'''
Remove emoji from text
- This function will preserve traditional Chinese characters
'''
emoji_pattern = re.compile("["
u"\U0001F000-\U0001F9FF" # Extended emoticons and symbols
u"\U0001FA00-\U0001FA6F" # Extended-A
u"\U0001FA70-\U0001FAFF" # Extended-B
u"\U00002600-\U000027BF" # Miscellaneous Symbols and Dingbats
u"\U0001F1E0-\U0001F1FF" # flags (iOS)
u"\U0001F900-\U0001F9FF" # Supplemental Symbols and Pictographs
"]+", flags=re.UNICODE)

return emoji_pattern.sub(r'', text)


def get_pos_definition():

li = [
['A', 'A', 'A', '/*非謂形容詞*/'],
['C', 'Caa', 'Caa', '/*對等連接詞,如:和、跟*/'],
['POST', 'Cab', 'Cab', '/*連接詞,如:等等*/'],
['POST', 'Cba', 'Cbab', '/*連接詞,如:的話*/'],
['C', 'Cbb', 'Cbaa, Cbba, Cbbb, Cbca, Cbcb', '/*關聯連接詞*/'],
['ADV', 'Da', 'Daa', '/*數量副詞*/'],
['ADV', 'Dfa', 'Dfa', '/*動詞前程度副詞*/'],
['ADV', 'Dfb', 'Dfb', '/*動詞後程度副詞*/'],
['ASP', 'Di', 'Di', '/*時態標記*/'],
['ADV', 'Dk', 'Dk', '/*句副詞*/'],
['ADV', 'D', 'Dab, Dbaa, Dbab, Dbb, Dbc, Dc, Dd, Dg, Dh, Dj', '/*副詞*/'],
['N', 'Na', 'Naa, Nab, Nac, Nad, Naea, Naeb', '/*普通名詞*/'],
['N', 'Nb', 'Nba, Nbc', '/*專有名稱*/'],
['N', 'Nc', 'Nca, Ncb, Ncc, Nce', '/*地方詞*/'],
['N', 'Ncd', 'Ncda, Ncdb', '/*位置詞*/'],
['N', 'Nd', 'Ndaa, Ndab, Ndc, Ndd', '/*時間詞*/'],
['DET', 'Neu', 'Neu', '/*數詞定詞*/'],
['DET', 'Nes', 'Nes', '/*特指定詞*/'],
['DET', 'Nep', 'Nep', '/*指代定詞*/'],
['DET', 'Neqa', 'Neqa', '/*數量定詞*/'],
['POST', 'Neqb', 'Neqb', '/*後置數量定詞*/'],
['M', 'Nf', 'Nfa, Nfb, Nfc, Nfd, Nfe, Nfg, Nfh, Nfi', '/*量詞*/'],
['POST', 'Ng', 'Ng', '/*後置詞*/'],
['N', 'Nh', 'Nhaa, Nhab, Nhac, Nhb, Nhc', '/*代名詞*/'],
['Nv', 'Nv', 'Nv1,Nv2,Nv3,Nv4', '/*名物化動詞*/'],
['T', 'I', 'I', '/*感嘆詞*/'],
['P', 'P', 'P*', '/*介詞*/'],
['T', 'T', 'Ta, Tb, Tc, Td', '/*語助詞*/'],
['Vi', 'VA', 'VA11,12,13,VA3,VA4', '/*動作不及物動詞*/'],
['Vt', 'VAC', 'VA2', '/*動作使動動詞*/'],
['Vi', 'VB', 'VB11,12,VB2', '/*動作類及物動詞*/'],
['Vt', 'VC', 'VC2, VC31,32,33', '/*動作及物動詞*/'],
['Vt', 'VCL', 'VC1', '/*動作接地方賓語動詞*/'],
['Vt', 'VD', 'VD1, VD2', '/*雙賓動詞*/'],
['Vt', 'VE', 'VE11, VE12, VE2', '/*動作句賓動詞*/'],
['Vt', 'VF', 'VF1, VF2', '/*動作謂賓動詞*/'],
['Vt', 'VG', 'VG1, VG2', '/*分類動詞*/'],
['Vi', 'VH', 'VH11,12,13,14,15,17,VH21', '/*狀態不及物動詞*/'],
['Vi', 'VHC', 'VH16, VH22', '/*狀態使動動詞*/'],
['Vi', 'VI', 'VI1,2,3', '/*狀態不及物動詞*/'],
['Vt', 'VJ', 'VJ1,2,3', '/*狀態及物動詞*/'],
['Vt', 'VK', 'VK1,2', '/*狀態句賓動詞*/'],
['Vt', 'VL', 'VL1,2,3,4', '/*狀態謂賓動詞*/'],
['Vt', 'V_2', 'V_2', '/*有*/'],
['T', 'DE', '/*的、之、得、地*/', ''],
['Vt', 'SHI', '', '/*是*/'],
['FW', 'FW', '', '/*外文標記*/'],
['COLONCATEGORY', '', '', '/*冒號*/'],
['COMMACATEGORY', '', '', '/* 逗號 */'],
['DASHCATEGORY', '', '', '/* 破折號 */'],
['ETCCATEGORY', '', '', '/* 刪節號 */'],
['EXCLANATIONCATEGORY', '', '', '/* 驚嘆號 */'],
['PARENTHESISCATEGORY', '', '', '/* 括弧 */'],
['PAUSECATEGORY', '', '', '/* 頓號 */'],
['PERIODCATEGORY', '', '', '/* 句號 */'],
['QUESTIONCATEGORY', '', '', '/* 問號 */'],
['SEMICOLONCATEGORY', '', '', '/* 分號 */'],
['SPCHANGECATEGORY', '', '', '/* 雙直線 */']
]
df = pd.DataFrame(
li, columns=['short_label', 'label', 'all_label', 'description'])
return df


def get_excluded_pos():
'''
Get excluded pos
'''
li = ['WHITESPACE', 'COLONCATEGORY', 'COMMACATEGORY',
'DASHCATEGORY', 'ETCCATEGORY', 'EXCLANATIONCATEGORY',
'PARENTHESISCATEGORY', 'PAUSECATEGORY', 'PERIODCATEGORY',
'QUESTIONCATEGORY', 'SEMICOLONCATEGORY', 'SPCHANGECATEGORY',
'EXCLAMATIONCATEGORY']
return li


def clean_word_pos(word_pos):
'''
Clean word pos
'''
exclude_pos = get_excluded_pos()
word_pos = word_pos[['word', 'pos']]
word_pos['word'] = word_pos['word'].str.replace(' ', '')
# remove zero width joiner
word_pos['word'] = word_pos['word'].str.replace('\u200d', '')
# Convert to lower case
word_pos['word'] = word_pos['word'].str.lower()
# Remove emoji
word_pos['word'] = word_pos['word'].apply(str_remove_emoji)
# Remove abnormal words
word_pos = word_pos[(~word_pos['pos'].isin(exclude_pos))
& (~word_pos['word'].str.contains('http'))
& (~word_pos['word'].str.contains('@'))
& (word_pos['word'].str.len() <= 30)
& (word_pos['word'] != '')
]
word_pos = (word_pos
.groupby(['word', 'pos'])
.size()
.reset_index(name='word_count'))

return word_pos


def clean_word_ner(ner):
'''
Clean word ner
'''
ner = ner[['word', 'ner']]
ner['word'] = ner['word'].str.replace(' ', '')
# remove zero width joiner
ner['word'] = ner['word'].str.replace('\u200d', '')
# Convert to lower case
ner['word'] = ner['word'].str.lower()
# Remove emoji
ner['word'] = ner['word'].apply(str_remove_emoji)
# Remove abnormal words
ner = ner[(ner['word'].str.len() <= 30)
& (ner['ner'].str.len() <= 20)
& (ner['word'] != '')
]
ner = (ner
.groupby(['word', 'ner'])
.size()
.reset_index(name='word_count'))
return ner


def run_ckip_transofomer():
'''
Duplicated and adjusted from official GitHub
https://github.com/ckiplab/ckip-transformers/blob/master/example/example.py
'''

# Show version
print(__version__)

# Initialize drivers
print("Initializing drivers ... WS")
ws_driver = CkipWordSegmenter(model="bert-base")
print("Initializing drivers ... POS")
pos_driver = CkipPosTagger(model="bert-base")
print("Initializing drivers ... NER")
ner_driver = CkipNerChunker(model="bert-base")
print("Initializing drivers ... done")
print()

# Input text
text = [
"傅達仁今將執行安樂死,卻突然爆出自己20年前遭緯來體育台封殺,他不懂自己哪裡得罪到電視台。",
"美國參議院針對今天總統布什所提名的勞工部長趙小蘭展開認可聽證會,預料她將會很順利通過參議院支持,成為該國有史以來第一位的華裔女性內閣成員。",
"空白 也是可以的~",
]

# Run pipeline
print("Running pipeline ... WS")
ws = ws_driver(text)
print("Running pipeline ... POS")
pos = pos_driver(ws)
print("Running pipeline ... NER")
ner = ner_driver(text)
print("Running pipeline ... done")
print()

# Flag each [word, pos, ner]
word_pos_li = []
word_ner_li = []
for sentence_ws, sentence_pos, sentence_ner in zip(ws, pos, ner):
# Concatenate word, pos
for word_ws, word_pos in zip(sentence_ws, sentence_pos):
word_pos_li.append([word_ws, word_pos])

# Flag ner
for entity in sentence_ner:
word_ner_li.append([entity.word, entity.ner])

return word_pos_li, word_ner_li


def main():
word_pos_li, word_ner_li = run_ckip_transofomer()
word_pos = clean_word_pos(word_pos_li)
word_ner = clean_word_ner(word_ner_li)
print(word_pos)
print(word_ner)


if __name__ == "__main__":
main()

這段程式碼也同步發表在我的GitHub上。



本文轉載自:ARON HACK - 清理CKIP-Transformer輸出結果的技巧與程式範例

    留言0
    查看全部
    發表第一個留言支持創作者!
    在 Visual Studio Code(VSCode)或是其分支專案(如 Cursor)中,當你執行 Python 程式碼時(使用 Shift + Enter),預設會在終端機中顯示輸出結果。這種執行方式會執行整個程式,使用上非常不方便,因為你沒辦法只執行部分程式碼並檢查變數。
    日本NHK最近製作了一部關於中國文件外洩的調查報導,內容中有相當大的篇幅聚焦在台灣。雖然由外國媒體報導不免顯得諷刺,但也增加了記錄片的公信力與客觀性。以下為完整中文版。
    安裝 Llama 2 方法1. 使用官方指南安裝 Llama 2 Meta官方提供的Llama 2安裝方法很容易出錯,你需要先在Meta的網站上申請權限,然後執行Git Repository中的shell腳本來下載模型。當你嘗試執行模型時,可能會遇到以下錯誤: UserWarning: A
    在程式實驗室中,有一個方塊是「播放指定動作」。根據官方文件,這個方塊可以將凱比機器人的動作ID賦予給一個變數,再讓凱比做出該動作。這樣只需要更改變數中的動作ID,就可以讓凱比做出不同的動作。
    最近,我嘗試使用Flutter和大型語言模型開發我的個人AI助理的手機App,其中一項功能是監控系統。當某個程式出現錯誤時,我希望可以透過Firebase發出Alert,並在手機上接收推播通知。不幸的是,我發現我必須先付99美元的年費取得Apple開發者帳號,才能使用Apple推播通知服務(APN
    現在長文應該很少人看,所以我先說重點。我認為兩岸議題的終極提問只有兩個:你支持台灣獨立或是兩岸統一?如果你支持台灣獨立,當兩岸開戰時,你會選擇投降或抵抗?
    在 Visual Studio Code(VSCode)或是其分支專案(如 Cursor)中,當你執行 Python 程式碼時(使用 Shift + Enter),預設會在終端機中顯示輸出結果。這種執行方式會執行整個程式,使用上非常不方便,因為你沒辦法只執行部分程式碼並檢查變數。
    日本NHK最近製作了一部關於中國文件外洩的調查報導,內容中有相當大的篇幅聚焦在台灣。雖然由外國媒體報導不免顯得諷刺,但也增加了記錄片的公信力與客觀性。以下為完整中文版。
    安裝 Llama 2 方法1. 使用官方指南安裝 Llama 2 Meta官方提供的Llama 2安裝方法很容易出錯,你需要先在Meta的網站上申請權限,然後執行Git Repository中的shell腳本來下載模型。當你嘗試執行模型時,可能會遇到以下錯誤: UserWarning: A
    在程式實驗室中,有一個方塊是「播放指定動作」。根據官方文件,這個方塊可以將凱比機器人的動作ID賦予給一個變數,再讓凱比做出該動作。這樣只需要更改變數中的動作ID,就可以讓凱比做出不同的動作。
    最近,我嘗試使用Flutter和大型語言模型開發我的個人AI助理的手機App,其中一項功能是監控系統。當某個程式出現錯誤時,我希望可以透過Firebase發出Alert,並在手機上接收推播通知。不幸的是,我發現我必須先付99美元的年費取得Apple開發者帳號,才能使用Apple推播通知服務(APN
    現在長文應該很少人看,所以我先說重點。我認為兩岸議題的終極提問只有兩個:你支持台灣獨立或是兩岸統一?如果你支持台灣獨立,當兩岸開戰時,你會選擇投降或抵抗?
    你可能也想看
    Google News 追蹤
    Thumbnail
    這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
    上兩篇有關List的文章,此篇文上兩章的延續,整理一些常用的方法和操作。 [Python]List(列表)新增、修改、刪除元素 [Python基礎]容器 list(列表),tuple(元組) 還有一些常用的 list 方法和操作,讓你能更靈活地處理列表數據
    Thumbnail
    在 Python 中,print( ) 函數用於將結果輸出到螢幕上。當你嘗試將不同資料型別(例如字串和數字)混合在一起輸出時,print( )函數無法直接處理這些不同型別的資料,因此你需要先將它們轉換為相同的資料型別。通常,這意味著需要將數字轉換為字串型別,以便與其他字串一同輸出。 雖然我們也可以
    “所有人寫的程式會變成指令 每一道指令是由CPU執行 而CPU所能理解的指令類型有限”
    Thumbnail
    本文介紹了流行的Python套件NLTK(Natural Language Toolkit)的主要特點、功能和在中文和英文語料上的應用。從安裝到實際應用,深入介紹了分詞、停用詞去除、詞性標註、命名實體識別等NLP任務的具體實現和步驟,幫助讀者理解和應用NLTK。
    在Python中, 要寫一個完整的「符元化類 Tokenizer Class」, 這個Class需要的功能有: 1.「編碼 Encode」:將「文本 Text」分割成「符元 Token」。 2.「詞彙 Vocabulary」:將「符元 Token」映射到「符元ID TokenID
    在學習大語言模型的技術細節時, 弄清楚「輸入文本 Input Text」與「符元化文本 Tokenized Text」之間的差異會很方便[1]。 舉個具體的例子: 輸入文本:Hello, 你好. Obsidian is great! 符元化文本:['Hello', ',',
    Thumbnail
    在數據分析的工作中,處理 CSV 檔案是一項基礎且重要的技能,CSV 格式的檔案是以純文字形式儲存表格數據,簡潔的結構使其普遍應用於數據儲存。本文將介紹如何使用Python 來讀取、處理和儲存 CSV 檔案。
    Thumbnail
    在日常中我們都會將很多事物定上了一個標籤,例如將商品標記價格,替孩子取姓名,公司上冠上職稱等等。 在Python中也有這種方法,就是字典的形式{ 'name' : 'crab', 'apple', 1000 }去呈現
    Thumbnail
    這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
    上兩篇有關List的文章,此篇文上兩章的延續,整理一些常用的方法和操作。 [Python]List(列表)新增、修改、刪除元素 [Python基礎]容器 list(列表),tuple(元組) 還有一些常用的 list 方法和操作,讓你能更靈活地處理列表數據
    Thumbnail
    在 Python 中,print( ) 函數用於將結果輸出到螢幕上。當你嘗試將不同資料型別(例如字串和數字)混合在一起輸出時,print( )函數無法直接處理這些不同型別的資料,因此你需要先將它們轉換為相同的資料型別。通常,這意味著需要將數字轉換為字串型別,以便與其他字串一同輸出。 雖然我們也可以
    “所有人寫的程式會變成指令 每一道指令是由CPU執行 而CPU所能理解的指令類型有限”
    Thumbnail
    本文介紹了流行的Python套件NLTK(Natural Language Toolkit)的主要特點、功能和在中文和英文語料上的應用。從安裝到實際應用,深入介紹了分詞、停用詞去除、詞性標註、命名實體識別等NLP任務的具體實現和步驟,幫助讀者理解和應用NLTK。
    在Python中, 要寫一個完整的「符元化類 Tokenizer Class」, 這個Class需要的功能有: 1.「編碼 Encode」:將「文本 Text」分割成「符元 Token」。 2.「詞彙 Vocabulary」:將「符元 Token」映射到「符元ID TokenID
    在學習大語言模型的技術細節時, 弄清楚「輸入文本 Input Text」與「符元化文本 Tokenized Text」之間的差異會很方便[1]。 舉個具體的例子: 輸入文本:Hello, 你好. Obsidian is great! 符元化文本:['Hello', ',',
    Thumbnail
    在數據分析的工作中,處理 CSV 檔案是一項基礎且重要的技能,CSV 格式的檔案是以純文字形式儲存表格數據,簡潔的結構使其普遍應用於數據儲存。本文將介紹如何使用Python 來讀取、處理和儲存 CSV 檔案。
    Thumbnail
    在日常中我們都會將很多事物定上了一個標籤,例如將商品標記價格,替孩子取姓名,公司上冠上職稱等等。 在Python中也有這種方法,就是字典的形式{ 'name' : 'crab', 'apple', 1000 }去呈現