Colab上でのMecabユーザ辞書登録

# はじめに：
- Mecabは日本語のNLPにおける形態素解析のツールです。
- 形態素解析とは、文章を形態素の列に分割し、それぞれの形態素の品詞等を判別する作業です。
    - 例として、<br>
     `頑張りをしっかり反映。`<br>に対して、形態素解析を行うと以下のように分割されます。<br>
`頑張り / を / しっかり / 反映 / 。`<br>
- しかし、Mecab上に登録されている辞書データでは、分割されたくないが分割されてしまうような単語（形態素）も出現します。
- したがって、ここでは分割されてほしくない単語をMecabの辞書内にユーザ辞書として新規登録する方法を示します。
- 環境としては、Google Colablatory下での実行を想定しています。
    - 理由として、Google Colab下でのMecabを使用した文献が少なかったことと、文献が存在してもエラーが発生するため、備忘録的に残したかったからです。

# ユーザ辞書の形式
- Mecabのユーザ辞書はcsvファイルで、各列は以下のフォーマットで解釈されます。

```*.csv
表層形,左文脈ID,右文脈ID,コスト,品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用型,活用形,原形,読み,発音

例）
工藤,1223,1223,6058,名詞,固有名詞,人名,名,*,*,くどう,クドウ,クドウ
```

- 左文脈ID，右文脈ID，コストとは[公式](https://taku910.github.io/mecab/dic.html)では以下のように定義されていました。

>左文脈IDは, その単語を左から見たときの内部状態IDです.
__空にしておくと mecab-dict-index が自動的に ID を付与します.__

>右文脈IDは, その単語を右から見たときの内部状態IDです.
__空にしておくと, mecab-dict-index が自動的に ID を付与します.__

>コストは,その単語がどれだけ出現しやすいかを示しています. 小さいほど, 出現しやすいという意味になります.
似たような単語と 同じスコアを割り振り, その単位で切り出せない場合は, 徐々に小さくしていけばいいと思います.

- 上の __太字__ の箇所では空にしておけばよいと記述されていますが、実際にはエラーが起きたので何かしら適当な値を入れておく必要がありそうです。
    - ここでは、形態素での分割のみを目的としているので、IDには100、コストには1と、適当な値を設定しました。


- したがって、まずは単語を上記のフォーマットにエンコードするコードを以下のように定義します。
- 以下のクラス定義では、出力したいcsvファイルのパスと、単語をリスト形式で格納した変数をパラメータとして必要とします。
    - 他にも、品詞やコストなどのパラメータをセッティングすることもできます。

```python
import csv
class MakeMecabCSV:
    """ Mecabのユーザ辞書の書式でcsvを作成するクラス """
    def __init__(self, csvfile_path, word_list):
        self.csvfile_path = csvfile_path
        self.word_list = word_list
        self.cost = '1'
        self.wclass = '名詞'
        self.wclass1 = '固有名詞'

    # fileモードを指定して、word_listをcsvに一括書き出し
    def makecsv_list(self, fmode='w'):
        with open(self.csvfile_path, fmode, newline='', encoding='utf-8') as f:
            writer = csv.writer(f)
            for word in self.word_list:
                # 表層形,左文脈ID,右文脈ID,コスト,品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用型,活用形,原形,読み,発音
                writer.writerow([word,'100','100','1','名詞','固有名詞','*','*','*','*','*','*','*','mydic'])
            
    # 追加登録メソッド用のセッター
    def set_param(self, cost='10', wclass='名詞', wclass1='固有名詞'):
        self.cost = cost
        self.wclass = wclass
        self.wclass1 = wclass1

    # 1単語ずつの追加登録メソッド
    def makecsv_word(self, word):
        with open(self.csvfile_path , 'a', newline='', encoding='utf-8') as f:
            writer = csv.writer(f)
            writer.writerow([word,'100','100',self.cost,self.wclass,self.wclass1,'*','*','*','*','*','*','*','mydic'])
```

# Mecabユーザ辞書への追加
- 前節でcsvファイルを得たら、colabのセル上で以下のコマンドを順次実行していきます。

- まず、colab上でmecabと辞書のインストールを行います。

```python
!apt-get -q -y install sudo file mecab libmecab-dev mecab-ipadic-utf8 git curl python-mecab > /dev/null
!git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git > /dev/null 
!echo yes | mecab-ipadic-neologd/bin/install-mecab-ipadic-neologd -n > /dev/null 2>&1
!pip install mecab-python3 > /dev/null
!ln -s /etc/mecabrc /usr/local/etc/mecabrc
```

- ユーザ辞書用のディレクトリを作成します。

```python
!mkdir ../var/lib/mecab/dic/userdic
```

- mecab-dict-indexを用いて辞書のコンパイルを行います。
    - 各引数の意味は以下の通りです。
   
```
-d ＜システム辞書が入っているディレクトリ＞ \
-u ＜ユーザ辞書の保存先＞ \
-f ＜CSVファイルの文字コード＞ \
-t ＜ユーザ辞書の文字コード＞ ＜CSVファイル＞
```
```python
!/usr/lib/mecab/mecab-dict-index \
-d /usr/share/mecab/dic/ipadic/ \
-u /content/userdic.dic \
-f utf-8 \
-t utf-8 "/content/drive/MyDrive/Colab Notebooks/<追加csvファイル名>"

# -tのcsvファイルのパスは環境に合わせて適宜変更してください。
# -dを
# -d /var/lib/mecab/dic/debian \
# と設定している文献もありましたが、debian下にはrewrite.defが存在しないためエラーが発生
```

- 出力が以下のようになれば問題ありません。

```
reading /content/drive/MyDrive/ColabNotebooks/<追加csvファイル名> ... <登録単語数>
emitting double-array: 100% |###########################################| 

done!
```

- mecabrc（設定ファイル）にユーザ辞書のパスを追記します。

```python
!echo "userdic = /content/userdic.dic" >> /etc/mecabrc
```

- 以上で設定は完了です。
- ユーザ辞書登録を行った単語を含めて実際に形態素解析を行うと、分かち書きされないことが確認できるかと思います。

# 参考URL
以下のサイトを参考にさせていただきました。
- [Mecabユーザ辞書への単語追加](https://blog.apar.jp/linux/2748/)
- [MeCab: 単語の追加方法](https://taku910.github.io/mecab/dic.html)
- [mecab github](https://github.com/taku910/mecab)