はじめに
この記事では、Mac環境においてDoc2VecとJuman++による日本語文章分類を行うための環境構築手順についてまとめます。極力パッケージ管理ツールを使用することを方針とします。環境構築が主目的なのでDoc2VecやJuman++の詳細には触れません。
環境
以下の環境を構築します。
環境名 | バージョン | 入手元 |
---|---|---|
OS | macOS Sierra | - |
Python | 3.6.6rc1 | 公式からダウンロード |
KNP | 4.1.9 | Homebrew |
Juman++ | 1.0.2 | Homebrew |
PyKNP | 0.3 | 公式からダウンロード |
gensim | 3.4.0 | pip |
HomebrewやPythonはインストール済みとします。
手順
環境構築に必要な手順は大きく分けて、
- 形態素解析ライブラリJuman++のインストール
- Doc2Vecライブラリgensimのインストール
になります。
形態素解析ライブラリJuman++のインストール
日本語の形態素解析ライブラリはMecabが有名ですが、最近はJuman++なるものも使われるみたいです。今回私はブログ記事の分類をしたかったため、そちらに向いているとされるJuman++の方を使用します。
また、Pythonを開発言語として使用するため、以下のパッケージをインストールする必要があります。
- KNP(構文解析システム)
- Juman++(形態素解析システム)
- PyKNP(KNPとJuman++のPythonバインディング)
KNPのインストール
構文解析システムのKNPをインストールします。KNPはデフォルトのHomebrewリポジトリに含まれていないので、自然言語処理に関連するライブラリに特化したHomebrewリポジトリnlpからインストールします。結構時間がかかるので要注意です。
brew tap uetchy/nlp
brew install knp
Juman++のインストール
形態素解析システムのJuman++をインストールします。こちらはデフォルトのHomebrewリポジトリに含まれているのでそのままインストールできます。
brew install jumanpp
PyKNPのインストール
KNPとJuman++のPythonバインディングのPyKNPはpipに含まれていなので自前でビルドしてインストールします。
wget http://nlp.ist.i.kyoto-u.ac.jp/nl-resource/knp/pyknp-0.3.tar.gz
tar xvf pyknp-0.3.tar.gz
cd pyknp-0.3
sudo python setup.py install
Doc2Vecライブラリgensimのインストール
gensimのインストール
pipでインストールできます。
pip install gensim
動作確認
確認用データ
確認用データにはlivedoorニュースコーパスを使用しました。
wget http://www.rondhuit.com/download/ldcc-20140209.tar.gz
tar xvfz ldcc-20140209.tar.gz
tarを解答するとtextというフォルダが展開され、そこに大量のテキストデータが入っています。
確認用コード
いくつか既存のコード例がありますが、今回の環境のバージョンだと動かなかったため、動作確認用コードを書きました。
- ドキュメントに半角スペースが含まれていると上手く処理できない
-
Jumanpp().analysis()
は改行コードがあるところまでしか処理しない
というところで少しつまづきましたが、
- 半角スペースを全角スペースに置換する
- 予めドキュメントを一行ずつ抽出して
Jumanpp().analysis()
に投げる
ことで解決しました。
from pyknp import Jumanpp
from gensim import models
from gensim.models.doc2vec import TaggedDocument
path_list = ["text/topic-news/topic-news-6903190.txt",
"text/topic-news/topic-news-6907153.txt",
"text/topic-news/topic-news-6909425.txt"]
def normalized_sentence(sentence):
return sentence.replace(' ', ' ')
def parse_words(filepath):
with open(filepath, encoding='utf-8') as f:
document = f.read()
words = []
for sentence in filter(None, document.split('\n')):
result = Jumanpp().analysis(normalized_sentence(sentence))
words += [mrph.midasi for mrph in result.mrph_list()]
return words
class TaggedFileDocuments(object):
def __init__(self, path_list):
self.path_list = path_list
def __iter__(self):
for file_path in self.path_list:
yield TaggedDocument(words=parse_words(file_path), tags=[file_path])
if __name__ == '__main__':
# データ作成
documents = TaggedFileDocuments(path_list)
# モデル作成
model = models.Doc2Vec(documents,
dm=0,
vector_size=300,
workers=4,
window=15,
alpha=0.025,
min_alpha=0.025,
min_count=1,
sample=1e-6,
epochs=20)
# モデルのファイル書き出し
model.save("doc2vec.model")
確認結果
python3 doc2vec_ex.py
python3
>>> from gensim import models
>>> model = models.Doc2Vec.load('doc2vec.model')
>>> model.docvecs.most_similar("text/topic-news/topic-news-6903190.txt", topn=1)
[('data/text/topic-news/topic-news-6907153.txt', 0.3459581732749939)]
生成したモデルから、指定した文章に最も類似する文章とその類似度を抽出できました。