👋

【自然言語処理】形態素解析のためのトークナイザー(関数)を作る

2022/09/02に公開

はじめに

Python初心者のわたくしが偉そうなことは言えませんが、自然言語処理においては、形態素解析が命と思っています。
 
mecab用の 優秀な辞書NEologd を使って、形態素解析のためのトークナイザー(関数) を作ったので、今後、自分が形態素解析をする際に使うためにも、記事として残しておきたいと思います。
 

具体的には、テキストを与えたら、

  1. 記号類を削除
  2. 数字を0にする
  3. ストップワードを除外する
  4. そのうえで、名詞・動詞・形容詞だけを抽出する

というトークナイザー(関数) になります。

NEologdは週に2回以上更新されるなど、新語・固有表現に強い辞書として定評があります。インストールが少し面倒ですが、とにかく優秀なので、知らない方は、是非、一度使ってみてほしいと思います。

NEologdの詳細はこちらをご覧ください

https://engineering.linecorp.com/ja/blog/mecab-ipadic-neologd-new-words-and-expressions/

 
 

GoogleコラボでMeCabとNEologd辞書を使えるようにする

まずは、googleコラボでmecabとNEologdを使えるようにインストールする必要があります。
ここに記載しているコードは以下の記事を参考にしています。
 
https://qiita.com/jun40vn/items/78e33e29dce3d50c2df1
 

形態素分析ライブラリーMeCab と 辞書(NEologd)のインストール

!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

 

辞書が格納されているパスを確認

!echo `mecab-config --dicdir`"/mecab-ipadic-neologd"

 

NEologdの威力を確認

サンプルテキストを与えて、標準辞書とNEologd辞書の違いを見てみます。
サンプルテキストは、鬼滅の刃、スターバックス、経営方針です。

import MeCab

sample_txt ="鬼滅の刃、スターバックス、経営方針"

mecab = MeCab.Tagger()
print("標準辞書:\n", mecab.parse(sample_txt))

# さきほど確認した辞書のパスを pathに代入します。その際、頭に、辞書の-dを入れておきます。
path = "-d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd"
mecab = MeCab.Tagger(path)
print("Neologd辞書: \n",mecab.parse(sample_txt))

結果はこちら

標準辞書の場合、鬼滅の刃は、「鬼」「滅」「の」「刃」になってしまいます。
スターバックスも「スター」「バックス」に、経営方針も「経営」「方針」に形態素解析されます。
一方、NEologd辞書は、適切にワードを認識しています。

標準辞書:
 鬼	名詞,一般,*,*,*,*,鬼,オニ,オニ
滅	名詞,一般,*,*,*,*,滅,メツ,メツ
の	助詞,連体化,*,*,*,*,の,ノ,ノ
刃	名詞,一般,*,*,*,*,刃,ハ,ハ
、	記号,読点,*,*,*,*,、,、,、
スター	名詞,一般,*,*,*,*,スター,スター,スター
バックス	名詞,一般,*,*,*,*,バックス,バックス,バックス
、	記号,読点,*,*,*,*,、,、,、
経営	名詞,サ変接続,*,*,*,*,経営,ケイエイ,ケイエイ
方針	名詞,一般,*,*,*,*,方針,ホウシン,ホーシン
EOS

Neologd辞書: 
 鬼滅の刃	名詞,固有名詞,一般,*,*,*,鬼滅の刃,キメツノヤイバ,キメツノヤイバ
、	記号,読点,*,*,*,*,、,、,、
スターバックス	名詞,固有名詞,組織,*,*,*,スターバックス,スターバックス,スターバックス
、	記号,読点,*,*,*,*,、,、,、
経営方針	名詞,固有名詞,一般,*,*,*,経営方針,ケイエイホウシン,ケイエイホーシン
EOS

 

トークナイザーを作る

ストップワードの取得

  • ストップワードとして、自ら設定することも可能ですが、ここでは、一般的なストップワードをダウンロードして使っていきたいと思います。
  • !wget urlで簡単に取得できます。
!wget http://svn.sourceforge.jp/svnroot/slothlib/CSharp/Version1/SlothLib/NLP/Filter/StopWord/word/Japanese.txt

トークナイザー(関数)

import re
#stopwordsの指定
with open("/content/Japanese.txt","r") as f:
    stopwords = f.read().split("\n")


#トークナイザー
def mecab_tokenizer(text):

    replaced_text = text.lower()
    replaced_text = re.sub(r'[【】]', ' ', replaced_text)       # 【】の除去
    replaced_text = re.sub(r'[()()]', ' ', replaced_text)     # ()の除去
    replaced_text = re.sub(r'[[]\[\]]', ' ', replaced_text)   # []の除去
    replaced_text = re.sub(r'[@@]\w+', '', replaced_text)  # メンションの除去
    replaced_text = re.sub(r'\d+\.*\d*', '', replaced_text) #数字を0にする

    path = "-d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd"
    mecab = MeCab.Tagger(path)
    parsed_lines = mecab.parse(replaced_text).split("\n")[:-2]
    
    #表層形を取得
    # surfaces = [l.split('\t')[0] for l in parsed_lines]
    #原形を取得
    token_list = [l.split("\t")[1].split(",")[6] for l in parsed_lines]
    #品詞を取得
    pos = [l.split('\t')[1].split(",")[0] for l in parsed_lines]
    # 名詞,動詞,形容詞のみに絞り込み
    target_pos = ["名詞","動詞","形容詞"]
    token_list = [t for t, p in zip(token_list, pos) if p in target_pos]
    
    # stopwordsの除去
    token_list = [t for t in token_list if t  not in stopwords]
    
    # ひらがなのみの単語を除く
    kana_re = re.compile("^[ぁ-ゖ]+$")
    token_list = [t for t in token_list if not kana_re.match(t)]
    
    return ' '.join(token_list)

トークナイザーを試す

適当な文章をトークナイザーに入れてみましょう。
ある上場企業の有価証券報告書テキストデータの一部をトークナイズしてみました。

text = "IoT関連ビジネスへの進化を目指し、主として電子・工業材料分野に継続的に供給されており、引き続き、拡大が期待される東アジア市場に向け事業を展開してまいります。"
mecab_tokenizer(text)

出力結果はこちら

適切に形態素解析できていますね。

IOT 関連 ビジネス 進化 目指す 電子 工業 材料 分野 継続 供給 引き続く 拡大 期待 東アジア 市場 向ける 事業 展開

さいごに

いかがでしたでしょうか。
優秀なトークナイザーを使えば、その後の自然言語処理の精度も格段に上がると思います。逆に、トークナイザーを疎かにすると、自然言語処理の精度も悪くなりやすいので注意が必要です。
今度は、spaCyのGiNZAを使ったトークナイザーを作ってみたいと思います。

Discussion