Python ディープラーニング

【Python】Doc2Vecで類似文書の表示

投稿日:

概要

自然言語処理分野において単語の分散表現を獲得する手法としてWord2Vecがありますが、その文章版、つまり文章を分散表現することができる手法としてDoc2Vecがあります。今回はPythonでDoc2Vecの使い方について勉強しました。

タスク設定

文章群をDoc2Vecでベクトル化し、そのなかの一つの文章を選び、それと類似度の高い文書を文書群の中から選んで表示する。

使用する諸々

  • Mecab 0.996
  • gensim
  • livedoor News

MeCabは以下で構築したものを使います。

Step1:データ取得

今回は以下からlivedoor Newsコーパスをダウンロードして使用させて頂きました。ありがとうございます。
livedoor ニュースコーパス:https://www.rondhuit.com/download.html#ldcc

ldcc-20140209.tar.gzをサイトからダウンロードし7zipで展開しました。
ディレクトリ構造としてはこのような形になっていて、各フォルダの中に.txtの形式でコーパスが格納されていました。

text
|- dokujo-tsushin
|- it-life-hack
|- kaden-channel
|- livedoor-homme
|- movie-enter
|- peachy
|- smax
|- sports-watch
|- topic-news
|- CHANGES.txt
|- README.txt

今回はkaden-channelとsports-watchデータを使用することにします。

Step2:gensimのインストール

pip install gensim

Step3:モデル作成

データ読み込み

まずは展開したデータをglobで読み込みます。kaden-channelとsports-watchのみにしています。

import os
from glob import glob
os.chdir('[展開したディレクトリ]\\text')

text = []
#家電チャンネル読み込み
for file in glob('kaden-channel\\*.txt'):
    with open(file,encoding="utf-8") as f:        
        text.append([f.read()])

l_kaden = len(text)
print('家電チャンネル記事数:',l_kaden)
        
#スポーツウォッチ読み込み
for file in glob('sports-watch\\*.txt'):
    with open(file,encoding="utf-8") as f:        
        text.append([f.read()])     

print('スポーツチャンネル記事数:',len(text)-l_kaden)
家電チャンネル記事数: 865
スポーツチャンネル記事数: 901

形態素解析

gensimのDoc2Vecに文章を渡すためには形態素解析をしておく必要があります。
以下のようにMeCabのparseメソッドを使用して分かち書きした上でリストに格納していきます。

#形態素解析
import MeCab
m = MeCab.Tagger("-Ochasen")
text_wakati= []
for w in text:
    text_wakati.append([d.split()[0] for d in m.parse(w[0]).splitlines()])

学習用データ準備

次にDoc2Vecメソッドに食わせるための学習用データセットを作っていきます。gensimのTaggedDocumentメソッドに分かち書きしたデータリストとインデックス番号を渡し、学習用データを作成します。

from gensim.models.doc2vec import TaggedDocument
cnt = 0
doc_train = []
for words in text_wakati:
    doc_train.append(TaggedDocument(words,[cnt]))
    cnt += 1

モデル作成

作ったdoc_trainリストをDoc2Vecに渡し、モデルを作成します。

from gensim.models.doc2vec import Doc2Vec
model = Doc2Vec(doc_train,dm=1, size=200, min_count=10, epochs=20)

パラメータ説明(やってみた感じエポック数は少なすぎるとあまり精度が上がらない印象でした。)

  • dm=1でPV-DM
  • size:ベクトル表現するときの次元サイズ
  • min_count:無視する出現回数閾値
  • epoch:エポック数

Step4:評価(定性)

記事の中から適当に一つ選んで、それと類似する上位5件のインデックスの記事を表示して、人間が見た時に似たような記事が選ばれているのかを評価してみます。
下記のコードでindexの数字を変えて任意の記事を選びます。上から865記事は家電チャンネルなので、以下のindex=1500の例はスポーツウォッチの記事から選んでいることになります。

index = 1500
sims = model.docvecs.most_similar(index)
sims
(1492, 0.7714306712150574),
 (1398, 0.6727927923202515),
 (1753, 0.6568506360054016),
 (1501, 0.6562802791595459),
 (1546, 0.6521874666213989),
 (1560, 0.6450892686843872),
 (1073, 0.6395328044891357),
 (1106, 0.6377852559089661),
 (1732, 0.6305040121078491),
 (1585, 0.630274772644043)
print(text[index],'\n')
print(text[1492],'\n')

index 1500の記事はテニスの錦織圭選手関連の記事で、類似度トップで上がってきたindex 1492の記事も同じくテニスの錦織圭選手の話題が含まれる記事でした。大した前処理もせずにこんな簡単に類似文書がでてくるのはすごいですね。また、少なくとも家電チャンネルからは一つも選ばれていないため、それなりの学習はできている様子です。


ちなみに上記で選ばれた記事の中には女子サッカーの話題なども含まれていたので、もう少し前処理やパラメータチューニングを追い込んでみてもいいのかもと思いました。上でも書いていますが、epoch数を増やすとやはり精度が上がってくる感じがありました。端末のスペックがある場合はもっとepoch数を増やしてもいいのかもしれないです。

参考にさせて頂いたサイト

類似検索など:Doc2Vecについてまとめる

パラメータチューニングなど:Doc2Vecによる文書ベクトル推論の安定化について

-Python, ディープラーニング

執筆者:


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

Windows10環境のPython3でMeCabを使えるようにするまで

Contents1 概要2 環境3 Step1 : MeCabのインストール4 Step2 : mecab-python3のインストール5 Step3 : 動作確認5.1 もしエラーが出る場合 概要 …

【Python】標準偏差と分散の計算

Contents1 目的2 標準偏差3 Pythonによる標準偏差の計算4 分散 目的 以前の記事で四分位偏差によりデータの分散度の計算を行いましたが、四分位偏差ではデータの代表値である四分位数のみを …

AnacondaをWindowsへインストールする

Contents1 目的2 環境3 Step 1 : インストーラのダウンロード4 Step2 : インストール5 STEP3 : pythonコードテスト6 まとめ 目的 AnacondaをWind …

Pythonからデータベース接続(PostgreSQL,Oracle,MySQL)

Contents1 目的2 PostgreSQLの場合3 MySQLの場合4 Oracleの場合 目的 pythonからデータベースに接続するコードをすぐ忘れるので、書き留める PostgreSQLの …

【Python】pandas dateframeで日時を日付と時間に分ける

Contents1 元データ2 日付と時刻にばらすコード 元データ このようなデータフレームがあり、日付と時刻にばらしたい場合の話。 import pandas as pd import dateti …

言語切り替え

カテゴリー