文章を指定してTF-IDFに変換しディープラーニングで判定

f:id:hanamichi_sukusuku:20210218141308p:plain

f:id:hanamichi_sukusuku:20210218141335p:plain

実行結果

 

f:id:hanamichi_sukusuku:20210218141433p:plain

このプログラムではMLPを利用して文章を指定しどんなジャンルの文章なのか判定するプログラム。

インポートしているtfidfモジュールは下記のリンクで作成したものを使用する。

TF-IDFの手法でモジュール作成 - hanamichi_sukusukuのブログ

 

独自テキストの定義、TF-IDFの辞書を読み込む

text1 = """
野球を観るのは楽しいものです。
試合だけでなくインタビューも楽しみです。
"""
text2 = """
常にiPhoneiPadを持っているので、
二口あるモバイルバッテリがあると便利。
"""
text3 = """
幸せな結婚の秘訣は何でしょうか。
夫には敬意を、妻には愛情を示すことが大切。
"""

# TF-IDFの辞書を読み込む --- (*2)
tfidf.load_dic("text/genre-tdidf.dic")

""" """は中身の改行をそのままの状態で扱うことができる。改行文字\nで表記した場合と同じ。

 

tfidf.laod_dic()は作成したtfidfモジュールのload_dic()関数である。この関数では引数で渡したパスから保存した単語辞書や単語の出現頻度を格納してあるデータをtfidfモジュール内で読み込み、グローバル変数として使用できるようにするもの。これによりtfidfモジュールから単語辞書、全文章での単語の出現頻度、livedoorニュースコーパスの文章をIDで表現したデータの3つが使用できるようになる。

 

モデル定義

nb_classes = 4
dt_count = len(tfidf.dt_dic)
model = Sequential()
model.add(Dense(512, activation='relu', input_shape=(dt_count,)))
model.add(Dropout(0.2))
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(nb_classes, activation='softmax'))
model.compile(
  loss='categorical_crossentropy',
  optimizer=RMSprop(),
  metrics=['accuracy'])
model.load_weights('./text/genre-model.hdf5')

dt_countはMLPの入力レイヤーでの入力数を格納している。tfidf.dt_dicはlivedoorニュースコーパスを使用した4ジャンルの文章全体での単語の出現頻度が格納されているデータ。一つの文章はこのdt_dicにある単語数で表現されるのでこの要素数が入力数になる。具体的には文章中の単語を辞書のidで表現し、その出現頻度と希少性を掛け合わせたTF-IDFのデータを使い、モデルに学習させるので入力数としては辞書の単語数(要素数)を使用する。

 

model.load_weights()で重みデータを読み込んでいる。この重みデータはlivedoorニュースコーパスのテキストを事前にMLPで学習し、その時の重みデータを保存したもの。

 

関数の呼び出し

if __name__ == '__main__':
check_genre(text1)
check_genre(text2)
check_genre(text3)

 

check_genre()関数

def check_genre(text):
 # ラベルの定義
  LABELS = ["スポーツ", "IT", "映画", "ライフ"]
 # TF-IDFのベクトルに変換 -- (*5)
  data = tfidf.calc_text(text) 
 # MLPで予測 --- (*6)
  pre = model.predict(np.array([data]))[0]
  n = pre.argmax()
  print(LABELS[n], "(", pre[n], ")")
  return LABELS[n], float(pre[n]), int(n)

この関数では引数で受け取ったテキストをモデルに学習させ予測結果を出力するためのもの。

tfidf.calc_text()でtfidfモジュール内の単語辞書を更新せずにTF-IDFベクトルに変換する。(単語辞書の要素数で表現されたTF-IDFベクトルデータ)

model.predict()で結果を予測。

argmax()で予測結果から最も値が大きいインデックス番号を返す。

LABELSに定義している要素のインデックスとラベルデータのインデックスは対応しているので予測したラベルと確率を出力。

 

・このプログラムでは学習ずみの単語しかベクトル化できない。今回作成したモジュールでは、livedoorニュースコーパスに出てこない、未知語を見つけると単語をなかったことにする処理にしてあるため学習したことない単語が多く出てくるほど、判定結果が悪くなる。そこで、未知語が出てきたら覚えておいて、改めて学習をやり直すなど、工夫が必要になる。