LoginSignup
2
4

More than 5 years have passed since last update.

キーワードを使った文章のカテゴリー判定

Last updated at Posted at 2019-02-09

やりたいこと

文章があるカテゴリーに属するかを、キーワードから判定したい。例えば・・・
入力

  • キーワード:「アニメ」
  • 文章: 「家柄も人柄も良し!! 将来を期待された秀才が集う秀知院学園!! その生徒会で出会った、副会長・四宮かぐやと会長・白銀御行は互いに惹かれているはずだが…何もないまま半年が経過!! プライドが高く素直になれない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!

いけてますね!!

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4