---
# System prepended metadata

title: NLP - ckiptagger
tags: [self-learning, ' NLP']

---

---
title: NLP - ckiptagger
tags: self-learning, NLP
---
{%hackmd BkVfcTxlQ %}

# **_NLP - ckiptagger_**
> [name=BessyHuang] [time=Sun, Apr 12, 2020]

# **課程大綱**
[TOC]

:::warning
**_Reference:_**
* [CKIP Lab - 下載軟體與資源](https://ckip.iis.sinica.edu.tw/resource/)
    * 中文斷詞暨實體辨識系統
        * [線上展示](https://ckip.iis.sinica.edu.tw/service/ckiptagger/)
        * [GitHub: CkipTagger](https://github.com/ckiplab/ckiptagger)
        * [Python API: ckiptagger](https://pypi.org/project/ckiptagger/)
        * [Paper: Why Attention? Analyze BiLSTM Deficiency and Its Remedies in the Case of NER](https://arxiv.org/abs/1908.11046)
* [中文自然語言處理 (NLP) 的進展與挑戰](https://allen108108.github.io/blog/2019/11/01/%E4%B8%AD%E6%96%87%E8%87%AA%E7%84%B6%E8%AA%9E%E8%A8%80%E8%99%95%E7%90%86%20(NLP)%20%E7%9A%84%E9%80%B2%E5%B1%95%E8%88%87%E6%8C%91%E6%88%B0/)
:::

---
## **筆記**

### Ckiptagger
* 開源的國產自動化斷詞工具(CKIP Lab)
    * 可依據自己需求，修改原始碼，增加新功能或特色，用於處理文本、語義分析的使用。
* 功能
    * 繁體中文斷詞(WS)
    * 詞性標註(POS)
    * [18類專有名詞的實體辨識(NER)](https://github.com/ckiplab/ckiptagger/wiki/Entity-Types)
* 特色
    * 加強斷詞表現
    * 可以不自動刪／改字
    * 支援不限長度的句子
    * 使用者自訂功能：提供參考／強制 詞典
* [優勢](https://www.ithome.com.tw/news/132838)
    > 以多達5萬句的ASBC 4.0漢語語料庫測試集，來進行中文斷詞測試時，
    > CkipTagger表現遠高於中國的結巴，
    > 中研院在中文斷詞準確度可達到97.49%，
    > 相較之下，中國的結巴只有90.51%。
    > 

:::info
(WS) prec (WS) rec (WS) f1 (POS) acc


:::

### Jieba VS. Ckiptagger
* [最強中文自然語言處理工具CKIPtagger](https://mc.ai/%E6%9C%80%E5%BC%B7%E4%B8%AD%E6%96%87%E8%87%AA%E7%84%B6%E8%AA%9E%E8%A8%80%E8%99%95%E7%90%86%E5%B7%A5%E5%85%B7ckiptagger/)








---
## **中文斷詞工具：實作**

### Installation (for GPU)
```
$ pip3 install ckiptagger
$ pip3 install tensorflow-gpu
$ pip3 install gdown
```

### 基本範例

* 下載 model and extracts to ./data/
    * model: data.zip (2GB) 

        ```python=
        from ckiptagger import data_utils

        data_utils.download_data_gdown("./")
        ```

* 開始斷詞 WS, 詞性標註 POS, 命名實體識別 NER

    ```python=
    import os
    from ckiptagger import WS, POS, NER

    # Setting GPU
    os.environ["CUDA_VISIBLE_DEVICES"] = "0"

    # Load model & Setting GPU
    ws = WS("./data", disable_cuda=False)
    pos = POS("./data", disable_cuda=False)
    ner = NER("./data", disable_cuda=False)

    # Run the WS-POS-NER pipeline
    sentence_list = [
        "你現在一時的同情，不是幫助，只會讓她更痛苦，因為你永遠不會是她的家人，而她自始自終還是一個人。",
        "因為是兩個人做的事情，有人牽著，去哪裡都可以；有人回應著，說什麼也可以，因為那是兩個人的事情，就算再無聊，它都變得好幸福。——慕橙",
        "如果人的記憶，只能選擇一秒鐘的額度，我希望，就是這一瞬間。——光晞",
        "如果時間能夠倒轉那有多好，當然那是不可能的事情，但是能有讓時間暫停的魔法，那就是攝影，不是嗎？攝影師讓瞬間，變成永恆的魔法。——攝影師 ",
    ]

    word_sentence_list = ws(
        sentence_list,
        # sentence_segmentation = True, # To consider delimiters 分隔符號
        # segment_delimiter_set = {",", "。", ":", "?", "!", ";"}), # This is the defualt set of delimit$
        # recommend_dictionary = dictionary1, # words in this dictionary are encouraged
        # coerce_dictionary = dictionary2, # words in this dictionary are forced
    )

    pos_sentence_list = pos(word_sentence_list)
    entity_sentence_list = ner(word_sentence_list, pos_sentence_list)

    print('WS: ', word_sentence_list)
    print('POS: ', pos_sentence_list)
    print('NER: ', entity_sentence_list)

    for name in entity_sentence_list[2]:
        print(name)
    ```

* Output
    
    ```
    WS:  [['你', '現在', '一時', '的', '同情', '，', '不', '是', '幫助', '，', '只', '會', '讓', '她', '更', '痛苦', '，', '因為', '你', '永遠', '不會', '是', '她', '的', '家人', '，', '而', '她', '自始自終', '還', '是', '一', '個', '人', '。'], ['因為', '是', '兩', '個', '人', '做', '的', '事情', '，', '有', '人', '牽', '著', '，', '去', '哪裡', '都', '可以', '；', '有', '人', '回應', '著', '，', '說', '什麼', '也', '可以', '，', '因為', '那', '是', '兩', '個', '人', '的', '事情', '，', '就算', '再', '無聊', '，', '它', '都', '變', '得', '好', '幸福', '。', '—', '—', '慕橙'], ['如果', '人', '的', '記憶', '，', '只', '能', '選擇', '一', '秒鐘', '的', '額度', '，', '我', '希望', '，', '就', '是', '這', '一瞬間', '。', '—', '—', '光晞'], ['如果', '時間', '能夠', '倒轉', '那', '有', '多', '好', '，', '當然', '那', '是', '不可能', '的', '事情', '，', '但是', '能', '有', '讓', '時間', '暫停', '的', '魔法', '，', '那', '就', '是', '攝影', '，', '不', '是', '嗎', '？', '攝影師', '讓', '瞬間', '，', '變成', '永恆', '的', '魔法', '。', '—', '—', '攝影師', ' ']]

    POS:  [['Nh', 'Nd', 'Nd', 'DE', 'VJ', 'COMMACATEGORY', 'D', 'SHI', 'VC', 'COMMACATEGORY', 'Da', 'D', 'VL', 'Nh', 'Dfa', 'VH', 'COMMACATEGORY', 'Cbb', 'Nh', 'D', 'D', 'SHI', 'Nh', 'DE', 'Na', 'COMMACATEGORY', 'Cbb', 'Nh', 'VH', 'D', 'SHI', 'Neu', 'Nf', 'Na', 'PERIODCATEGORY'], ['Cbb', 'SHI', 'Neu', 'Nf', 'Na', 'VC', 'DE', 'Na', 'COMMACATEGORY', 'V_2', 'Na', 'VC', 'Di', 'COMMACATEGORY', 'VCL', 'Ncd', 'D', 'VH', 'SEMICOLONCATEGORY', 'V_2', 'Na', 'VC', 'Di', 'COMMACATEGORY', 'VE', 'Nep', 'D', 'VH', 'COMMACATEGORY', 'Cbb', 'Nep', 'SHI', 'Neu', 'Nf', 'Na', 'DE', 'Na', 'COMMACATEGORY', 'Cbb', 'D', 'VH', 'COMMACATEGORY', 'Nh', 'D', 'VG', 'DE', 'Dfa', 'VH', 'PERIODCATEGORY', 'DASHCATEGORY', 'DASHCATEGORY', 'Nb'], ['Cbb', 'Na', 'DE', 'Na', 'COMMACATEGORY', 'Da', 'D', 'VC', 'Neu', 'Nf', 'DE', 'Na', 'COMMACATEGORY', 'Nh', 'VK', 'COMMACATEGORY', 'D', 'SHI', 'Nep', 'Nd', 'PERIODCATEGORY', 'DASHCATEGORY', 'DASHCATEGORY', 'Nb'], ['Cbb', 'Na', 'D', 'VAC', 'Nep', 'V_2', 'Dfa', 'VH', 'COMMACATEGORY', 'D', 'Nep', 'SHI', 'A', 'DE', 'Na', 'COMMACATEGORY', 'Cbb', 'D', 'V_2', 'VL', 'Na', 'VHC', 'DE', 'Na', 'COMMACATEGORY', 'Nep', 'D', 'SHI', 'Na', 'COMMACATEGORY', 'D', 'SHI', 'T', 'QUESTIONCATEGORY', 'Na', 'VL', 'Nd', 'COMMACATEGORY', 'VG', 'VH', 'DE', 'Na', 'PERIODCATEGORY', 'DASHCATEGORY', 'DASHCATEGORY', 'Na', 'WHITESPACE']]

    NER:  [set(), {(40, 41, 'CARDINAL', '兩'), (3, 4, 'CARDINAL', '兩')}, {(11, 14, 'TIME', '一秒鐘'), (31, 33, 'PERSON', '光晞')}, set()]


    (11, 14, 'TIME', '一秒鐘')
    (31, 33, 'PERSON', '光晞')
    ```

* 定義字典

    ```python=
    from ckiptagger import construct_dictionary

    word_to_weight = {
        "慕橙": 1,
        "一個人": 1,
        "一個": 2, # 權重較重, 代表會斷詞成 '一個' '人', 而非 '一個人'
    }
    dictionary2 = construct_dictionary(word_to_weight)
    print(dictionary2)


    word_sentence_list = ws(
            sentence_list,
            # sentence_segmentation = True, # To consider delimiters 分隔符號
            # segment_delimiter_set = {",", "。", ":", "?", "!", ";"}), # This is the defualt set of delimit$
            recommend_dictionary = dictionary1, # words in this dictionary are encouraged 鼓勵，支援
            coerce_dictionary = dictionary2, # words in this dictionary are forced 強制
        )
    ```

* `recommend_dictionary`：支援字典
    * Ex：句子中有"梁慕橙"，但字典卻只定義"慕橙"，則ckiptagger會把"梁慕橙"辨識為人名。
* `coerce_dictionary`：強制字典
    * 只要出現在"定義字典"裡面的詞，且權重較重，就會直接強制成詞。
    * Ex：句子中有"梁慕橙"，但字典卻只定義"慕橙"，則ckiptagger會把"慕橙"變成詞，但並不會辨識為人名。