1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

RNN テキストマイニング

Last updated at Posted at 2020-05-09

Recurrent Neural Network(RNN)

時系列データを扱うためにニューラルネットワークを拡張したもの。文章構造を学習させる時によく使用される。

RNN LSTMを用いた文章分類

データの準備

wget https://archive.ics.uci.edu/ml/machine-learning-databases/00228/smsspamcollection.zip
unzip smsspamcollection.zip

分かち書き

日本語を扱ったテキストマイニングの場合は事前にMeCab等を使用して、分かち書きする必要があります。

文章のベクトル化

用意したテキストは文字だけでなく、ベクトル化しておきます。

トークン化

kerasのメソッドを使用することで、文章を数字に変換することができる。例えば、単語に重複なしで通し番号を振ることで、日本語を数字群(=ベクトル)に変換できる(ex. 青空文庫「吾輩は猫である」)。

  • fit_on_texts:引数として学習に使用するテキストのリストを取る
    • word_index:単語ごとに割り当てられたインデックス番号
    • word_counts:文章内の単語の出現回数
    • document_count:入力した文章の数
from keras.preprocessing.text import Tokenizer
sentences = ['吾輩 は 猫 で ある 。 名前 は まだ 無い 。 ', 'どこ で 生れ た か とんと 見当 が つか ぬ 。 ', '何 でも 薄暗い じめじめ し た 所 で ニャーニャー 泣い て いた事 だけ は 記憶 し て いる 。 ']
tokenizer = Tokenizer()
tokenizer.fit_on_texts(sentences)
print(tokenizer.word_index)
#{'。': 1, 'は': 2, 'で': 3, 'た': 4, 'し': 5, 'て': 6, '吾輩': 7, '猫': 8, 'ある': 9, '名前': 10, 'まだ': 11, '無い': 12, 'どこ': 13, '生れ': 14, 'か': 15, 'とんと': 16, '見当': 17, 'が': 18, 'つか': 19, 'ぬ': 20, '何': 21, 'でも': 22, '薄暗い': 23, 'じめじめ': 24, '所': 25, 'ニャーニャー': 26, '泣い': 27, 'いた事': 28, 'だけ': 29, '記憶': 30, 'いる': 31}
  • texts_to_sequences:引数としてベクトル化したいテキストを取る
    • 学習用のテキストに含まれない文字は削除される
    • Only words known by the tokenizer will be taken into account.
tokenized_sentences = tokenizer.texts_to_sequences(sentences)
print(tokenized_sentences)
#[[7, 2, 8, 3, 9, 1, 10, 2, 11, 12, 1], 
# [13, 3, 14, 4, 15, 16, 17, 18, 19, 20, 1], 
# [21, 22, 23, 24, 5, 4, 25, 3, 26, 27, 6, 28, 29, 2, 30, 5, 6, 31, 1]]
  • texts_to_matrix
    • NumPy.ndarrayを返す
      • この例のlen(tokenized_sentences[0])が32を示すことからも分かるように、fit_on_textsで振られたインデックスを元に処理を進めていく
      • インデックス0は予約番号なので、要素1つ目からが単語として意味のある値
    • binary, count, tfgdf, freqのいずれかの方法でベクトル化する
      • binaryは単語が出てきたら1,出てきていなかったら0を詰める。
      • countはその単語が文章中に何回登場するかを表現する

ex. binaryモード

tokenized_sentences = tokenizer.texts_to_matrix(sentences, "binary")
print(len(tokenized_sentences[0]))
#32 (学習に使用したテキストに登場する単語数に対応している)
print(tokenized_sentences[0])
#[0. 1. 1. 1. 0. 0. 0. 1. 1. 1. 1. 1. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]

1が詰まっているインデックスを取り出すと下の様になる。

print(np.where(tokenized_sentences[0]==1))
#(array([ 1,  2,  3,  7,  8,  9, 10, 11, 12]),)

これは、fit_on_textで計算したインデックス番号と対応していて、「。」「は」「で」「吾輩」「猫」「ある」「名前」「まだ」「無い」の単語がこの文章中には使用されていますよ、ということを表現していることになる。この考え方はtexts_to_matrixの他のモードでも同じ。

Padding

先にベクトル化した文章は、可変長であるためさらに扱いやすくするためにパディングと呼ばれる処理を行う。このパディングではベクトルの次元数を揃えるために、ゼロ埋めをする。例として100個の長さになるようにする。

from keras.preprocessing.sequence import pad_sequences
padding_sentences = pad_sequences(tokenized_sentences, maxlen=100)
print(padding_sentences)
#[[ 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
#   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
#   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
#   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  7  2  8  3  9  1 10
#   2 11 12  1]
#   ...

Train/Testデータ分割

from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=0,)
# x : トレーニングデータの中身
# y : テストデータの中身、正解ラベル
# test_size : 3割をテスト用のデータとして置く
# random_state : データを分割する際の乱数のシード値

分類結果を評価する

confusion matrix

Reference

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?