やりたいこと
文章があるカテゴリーに属するかを、キーワードから判定したい。例えば・・・
入力
- キーワード:「アニメ」
- 文章:
「家柄も人柄も良し!! 将来を期待された秀才が集う秀知院学園!! その生徒会で出会った、副会長・四宮かぐやと会長・白銀御行は互いに惹かれているはずだが…何もないまま半年が経過!! プライドが高く素直になれない2人は、面倒臭いことに、”如何に相手に告白させるか”ばかりを考えるようになってしまった!?恋愛は成就するまでが楽しい!! 新感覚”頭脳戦”ラブコメ、開戦!!」
出力
- 判定結果:キーワード(アニメ)のカテゴリーに属する!といった具合です。
使った技術
- janome:日本語形態素解析ライブラリ。文章を単語へ分解。
- word2vec:単語を特徴ベクトルで表現する技術。
- fastText:word2vecの発展形。
コード
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
from janome.tokenizer import Tokenizer
import collections
import gensim
word2vec_model = gensim.models.KeyedVectors.load_word2vec_format('model.vec', binary=False)
t = Tokenizer()
def readText(fname, outLog):
"""
テキスト読み込み
"""
# ファイルをオープンする
test_data = open(fname, "r")
# すべての内容を読み込む
contents = test_data.read()
# すべての内容を表示する
if outLog:
print("readText() =>")
print(contents)
# ファイルをクローズする
test_data.close()
return contents
def text2words(text, outLog):
"""
テキストを、形態素解析で分解
"""
words = []
for token in t.tokenize(text):
words.append(token.base_form)
if outLog:
print("text2words() =>")
for word in words:
print(word+"/", end="")
print()
return words
def calcSimilarities(words, keyWord, outLog):
"""
単語とキーワードの類似度を算出
"""
similarities = []
similarity = 0
for word in words :
try:
similarity = word2vec_model.similarity(keyWord, word)
except :
continue
similarities.append(similarity)
if outLog:
print("calcSimilarities() =>")
for word, similarity in zip(words, similarities):
print(word, "&", keyWord, ">>>", similarity)
return similarities
def similarityIsEnoudh(similarities, threshold, outLog):
"""
キーワードと最類似語が、閾値以上に近いか判定
"""
if outLog:
print("similarityIsEnoudh() =>")
print("max similarity:", max(similarities))
print("threshold:", threshold)
if max(similarities) > threshold:
if outLog: print("...... max similarity > threshold!")
return True
else:
if outLog: print("...... threshold > max similarity")
return False
if __name__ == '__main__':
"""
・概要
テキストファイルの文章中に、
キーワードに近い意味の語が含まれるか否かを判定する。
・処理フロー
1. テキスト読み込み
2. 形態素解析
3. キーワードとの類似度判定
4. 最類似語で閾値判定
"""
#1. テキスト読み込み
inputText = readText("input.txt", True)
#2. 形態素解析
words = text2words(inputText, True)
#3. キーワードとの類似度判定
similarities =calcSimilarities(words, "アニメ", True)
#4. 最類似語で閾値判定
similarityIsEnoudh(similarities, 0.5, True)
結果
出力の一部を下記します。
頭脳 & アニメ >>> 0.37583873
戦 & アニメ >>> 0.2318813
” & アニメ >>> 0.22747964
ラブ & アニメ >>> 0.14948405
コメ & アニメ >>> 0.26953527
similarityIsEnoudh() =>
max similarity: 0.37583873
threshold: 0.5
...... threshold > max similarity
ダメでした。
”ラブコメ”と”アニメ”の類似度が高ければ、と期待しましたが、janomeの時点で”ラブ”&”コメ”にばらけてしまっています。janomeの辞書を更新すれば、可能かもしれません。
参考
以下サイトを特に参考にさせて頂きました。
- janomeの使い方 https://note.nkmk.me/python-janome-tutorial/
- word2vecで単語類似度算 https://qiita.com/yoppe/items/512c7c072d08c64afa7e
- かぐや様の紹介文 https://youngjump.jp/manga/kaguyasama/
感想
閾値も適当ですが、とりあえず動くものを作ってみました。辞書のことを考えると、時事ネタには弱いですが、一般的なカテゴリーならもっといい結果かもしれません。
おまけ
入力
- キーワード:「スポーツ」
- 文章:「ヤクルトは沖縄・浦添キャンプの9日、全体練習後に野球教室を行った。浦添市内の少年野球14チーム240人が参加し、ポジション別に分かれて指導を受けた。」
出力
- 判定結果
max similarity: 0.5154303
threshold: 0.5
...... max similarity > threshold!
いけてますね!!