Doc2Vec実装 livedoor JUMAN

Doc2Vec実装

 
livedoor newsコーパスの文章の類似度を比較します。
 
 
 
 
JUMANを用いて訓練データを作成

 
# import
import sys
from os import listdir, path
from pyknp import Juman, Jumanpp
from gensim import models
from gensim.models.doc2vec import Doc2Vec, TaggedDocument
import re
from tqdm import notebook
from tqdm.notebook import tqdm as tq
import csv
 
 
# 記事ファイルをダウンロードしたディレクトリから取得する関数
def corpus_files(dir_path):
filepath = [path.join(dir_path, x) for x in listdir(dir_path)]
dirs = [x for x in filepath if path.isdir(x) == True]
docs_path = [path.join(x, y)
for x in dirs for y in listdir(x) if not x.startswith('LICENSE')]
return docs_path
 
# 記事コンテンツをパスから取得する関数
def read_document(file_path):
with open(file_path, 'r', encoding='utf-8') as f:
return f.read()
 
# 取得した記事コンテンツの前処理
def edit_docment(document):
docs =
for x in document:
doc =
# 行ごとに分割
for text in x.split('\n'):
text = text.replace(' ', '') # 半角スペースを消去
text = re.sub('\w*@\w*', '', text) # @...などのドメイン名を削除
text = re.sub('#\w*', '', text) # ハッシュタグを削除
doc.append(text)
del doc[:2] #1,2行目に書いたあるURLと時間は関係ないので取り除きます。
doc = [s for s in doc if s != ''] #\n\nなどの場合、空文字リストが出現するのを防ぐ
docs.append(doc)
return docs
 
# JUMAN++を使って記事を単語リストに変換する関数
def split_jumanpp(doc):
words =
for sentence in tq(doc):
result = Jumanpp().analysis(sentence)
words += [mrph.midasi for mrph in result.mrph_list()]
return words
 
# 記事コンテンツを単語に分割して、Doc2Vecの入力に使うTaggedDocumentに変換し訓練用データを作る
def doc_to_sentence(doc, name):
words = split_jumanpp(doc)
return TaggedDocument(words=words, tags=[name])
 
 
# 記事のパスリストから、記事コンテンツに変換し、単語分割して、センテンスのジェネレーターを返す関数
def corpus_to_sentences(corpus_path):
document = [read_document(x) for x in corpus_path]
docs = edit_docment(document)
sentences =
for idx, (doc, name) in enumerate(zip(docs, corpus_path)):
print('*前処理中 {}/{}'.format(idx, len(docs)))
sentences.append(doc_to_sentence(doc, name))
return sentences
 
 
*ポイント
・JUMANは\n(改行文字)までしか分かち書きしてくれない
→\nでsplit。一行ごとに入力。
 
・'半角空白'があるとValueError
→replace
 
・@***, #***はError
正規表現を用いて削除
 
・各documentの1・2行目はそれぞれ、URLと日付であり、これら半角文字がJUMANに悪影響を及ぼす可能性があった
→1・2行目は全documentで削除
 
・例えば、\n\nなどでは、splitすると''空文字のみの入力になってしまい、Errorがでた
→最後に、空文字のみのリストは削除
 
 
 
dir_path = './livedoor/text'
corpus_path = corpus_files(dir_path)
 
# 訓練データの作成(分かち書き
sentences = corpus_to_sentences(corpus_path)
 
# 訓練データ(リスト)の保存
with open('livedoor_juman_trainig.pkl', 'wb') as f:
pickle.dump(sentences, f)
→10時間程度かかった
 
livedoor_juman_training.pkl」が完成
 
 
 
 
Doc2Vecパラメータを渡して、学習させる

 
# 訓練データの読み込み
with open('livedoor_juman_trainig.pkl', 'rb') as f:
sentences = pickle.load(f)
 
model = models.Doc2Vec(sentences, dm=0, vector_size=300, window=15, alpha=.025,
min_alpha=.025, min_count=1, sample=1e-6)
 
model.save('livedoor_juman')
model = Doc2Vec.load('livedoor_juman')
学習は一瞬
 
 
 
Doc2Vec実践

 
# タグの整理
doc =
for words, tags in sentences:
for tag in tags:
doc.append(tag)
 
 
# 文章ベクトルの表示
print(model.docvecs[doc[7375]])
 
 
# 文章の類似度
model.docvecs.similarity(doc[1], doc[2])
 
 
# 任意の文章との類似度を計算
 
text = """バーレーンの首都マナマ(マナーマとも)で現在開催されている
ユネスコ(国際連合教育科学文化機関)の第42回世界遺産委員会は日本の推薦していた
世界遺産に登録することを決定した。文化庁が同日発表した。
日本国内の文化財世界遺産登録は昨年に登録された福岡県の
「『神宿る島』宗像・沖ノ島と関連遺産群」に次いで18件目。
2013年の「富士山-信仰の対象と芸術の源泉」の文化遺産登録から6年連続となった。"""
 
words = []
result = Jumanpp().analysis(text)
words += [mrph.midasi for mrph in result.mrph_list()]
 
docs_vec = [model.infer_vector(words)]
 
model.docvecs.most_similar(docs_vec)
 
 
# 類似する単語を表示
model.wv.most_similar('東京', topn=10)