太陽がまぶしかったから

C'etait a cause du soleil.

mecab-python3 で ipadic-neologd を利用して固有名詞を含んだ日本語の計量テキスト分析をする Docker を構築

Text Mining Maniax: フリーソフトで始める日本語計量テキスト分析

Pythonで計量テキスト分析する環境を構築

 蔵書やWebニュースなどの計量テキスト分析をするために、テキストマイニングのための環境を作成しているのだけど、自然言語処理においては形態素解析が必要となる。形態素解析とはテキストの品詞分類を行なって分かち書きをするもの。

発開始当初はChaSenを基にし、ChaSenTNGという名前で開発されていたが、現在はChaSenとは独立にスクラッチから開発されている。ChaSenに比べて解析精度は同程度で、解析速度は平均3-4倍速い。

 日本語の形態素解析エンジンとしてはオープンソースMecabデファクトスタンダードになっているため、Docker イメージ上に mecab をインストールして Python から利用できるように構築する。

 また Mecab から品詞分類をするための単語辞書について、幅広い固有名詞の登録がなされている ipadic-neologd をビルドして利用する。

mecab-python3 で ipadic-neologd を利用する Dockefile

Dockerfile

FROM python:3.9.4-slim-buster

ENV TZ JST-9
ENV PYTHONDONTWRITEBYTECODE=1
ENV PIP_NO_CACHE_DIR=on
ENV PIP_DISABLE_PIP_VERSION_CHECK=on

RUN apt-get update -y && apt-get install -y \
        git curl make xz-utils file sudo \
        mecab libmecab-dev mecab-ipadic mecab-ipadic-utf8 \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /tmp
RUN git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git
WORKDIR /tmp/mecab-ipadic-neologd
RUN ./bin/install-mecab-ipadic-neologd -n -y \
    && rm -r /tmp/mecab-ipadic-neologd

WORKDIR /tmp
COPY ./requirements.txt /tmp/requirements.txt
RUN pip3 install --upgrade pip \
    && pip3 install -r /tmp/requirements.txt \
    && rm /tmp/requirements.txt

RUN ln -s /etc/mecabrc /usr/local/etc/
RUN ln -s /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd /usr/local/etc/

RUN mkdir /data

requirements.txt

(省略)
mecab-python3==1.0.3
unidic-lite==1.0.8

 Python 標準の Debian コンテナに apt-get で mecab および ipadic-neologd のビルドに必要なツールをインストールして、 ipadic-neologd からソースを clone してビルド。使いやすいように特定のパスにシンボリックリンクを張っている。

mecab-python3 で日本語形態素解析

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
__version__ = "0.1.0"

import argparse
import logzero
import settings
import MeCab
import pandas


class MecabTokenize:
    def __init__(self):
        logzero.logfile(
            settings.logfile,
            loglevel=20, maxBytes=1e6, backupCount=3
        )
        self.logger = logzero.logger
        self.mecab = MeCab.Tagger(settings.mecab_param)
        pandas.set_option('display.max_rows', None)

    def tokenize(self, text):
        p = [li.split('\t') for li in self.mecab.parse(text).splitlines()]
        p = [[li[0]] + li[1].split('-') + [None] for li in p if len(li) == 2]
        p = [{'term': li[0], 'info1': li[1], 'info2': li[2]} for li in p]
        return pandas.DataFrame(p)

    def freq(self, text, count=1):
        s = self.tokenize(text).groupby(['term', 'info1', 'info2']).size()
        s = s[s >= count].sort_values(ascending=False)
        return s.reset_index(name='freq')

    def main(self, args):
        self.logger.info(f'{__file__} {__version__} {args}')
        term_list = self.tokenize(args.args1)
        print('単語品詞リスト')
        print(term_list)

        freq_list = self.freq(args.args1)
        print('\n単語出現リスト')
        print(freq_list)


if(__name__ == '__main__'):
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '--version',
        action='version', version=f'{__version__}'
    )
    parser.add_argument('args1')
    args = parser.parse_args()
    MecabTokenize().main(args)

 MeCab.Tagger() で Mecab を辞書指定して起動。 parse() で解析。

parseToNodeは形態素ごとにNodeインスタンスの生成時にNodeの全ての要素をあらかじめ取得するので、そのときのオーバーヘッドがだいぶ大きいようです。

  parseToNode() で next を回していくような記法もできるが遅いのと pythonイテレータ記法に合ってないため、parse() のテキスト結果をリスト内包記法で二次元配列に変換。それを pandas.DataFrame 形式にしてよしなに取り扱えるようにしている。

 freq() では上記の pandas.DataFrame 内の出現回数を数えて pandas.DataFrame を再生成。SQLで group by したのと同じ効果。

 size() は pandas.Series のマルチインデックス形式になってしまうので DataFrame 形式に再変換をかけるまでを関数の責務としている。

コマンド引数に渡したテキストを形態素解析して単語出現数計測

% docker-compose run --entrypoint 'python /data/src/mecab_tokenize.py' mecab-test '私はmecabをPythonで取り扱うテストをしています。mecabは日本語形態素解析をするためのツールです。'

Creating mecab-test_mecab-test_run ... done
[I 210530 15:40:37 mecab_tokenize:34] /data/src/mecab_tokenize.py 0.1.0 Namespace(args1='私はmecabをPythonで取り扱うテストをしています。mecabは日本語形態素解析をするためのツールです。')
単語品詞リスト
      term info1 info2
0        私    名詞   代名詞
1        は    助詞   係助詞
2    mecab    名詞  固有名詞
3        を    助詞   格助詞
4   Python    名詞  固有名詞
5        で    助詞   格助詞
6     取り扱う    動詞    自立
7      テスト    名詞  サ変接続
8        を    助詞   格助詞
9        し    動詞    自立
10       て    助詞  接続助詞
11       い    動詞   非自立
12      ます   助動詞  None
13       。    記号    句点
14   mecab    名詞  固有名詞
15       は    助詞   係助詞
16     日本語    名詞    一般
17   形態素解析    名詞  固有名詞
18       を    助詞   格助詞
19      する    動詞    自立
20      ため    名詞   非自立
21       の    助詞   連体化
22     ツール    名詞    一般
23      です   助動詞  None
24       。    記号    句点

単語出現リスト
      term info1 info2  freq
0        を    助詞   格助詞     3
1        は    助詞   係助詞     2
2        。    記号    句点     2
3    mecab    名詞  固有名詞     2
4   Python    名詞  固有名詞     1
5      日本語    名詞    一般     1
6    形態素解析    名詞  固有名詞     1
7     取り扱う    動詞    自立     1
8      テスト    名詞  サ変接続     1
9      ツール    名詞    一般     1
10       の    助詞   連体化     1
11       で    助詞   格助詞     1
12       て    助詞  接続助詞     1
13      ため    名詞   非自立     1
14      する    動詞    自立     1
15       し    動詞    自立     1
16       い    動詞   非自立     1
17       私    名詞   代名詞     1

 ここままでコマンド引数に渡したテキストを形態素解析して単語出現数を表示するプログラムを作成した。あとは入力するテキストを取得したり、対象品詞をフィルターしたり、結果をファイル出力するなどを案件に合わせて実装することで計量テキスト分析の環境が整った。

 Mecab を Window や Mac などに直接インストールしていくと環境依存の問題に悩まされたり、マシン変更時の再インストール手順が手間なので、 Docker 化しておくことで手軽に取り扱えるようにした。 また Python のオブジェクトとして取り扱うことで pandas などの解析系ライブラリに処理を合流させることが可能となる。

 日本語計量テキスト分析ができるようになると、用語の普及過程や論点の移り変わりなどが定量的に示せるため社会学研究などからも注目されている。また自身の蔵書タイトルの頻出単語から自分自身の興味関心が改めてわかったりもする。そんなわけで、mecab-python3 で ipadic-neologd を利用して固有名詞を含んだ日本語の計量テキスト分析をする Docker 環境を構築したので活用していきたい。