POS Tagging with Bidirectional LSTM



この記事では,双方向LSTMを用いて語句をマークする.双方向を使うことで、文章の冒頭と結尾の文脈をよく反映することができます.
パッケージをダウンロードしましょう

Packages

import nltk
import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.utils import to_categorical
from sklearn.model_selection import train_test_split
NLTKは、完了したタグと品目タグのデータをロードすることができる.
nltk.download('treebank')
tagged_sentences = nltk.corpus.treebank.tagged_sents()

Data Preprocessing


データはtagged_sentencesに格納されています.
長さと内容を印刷し、文全体の長さと内容をチェックします.
len(tagged_sentences)
print(tagged_sentences)

コイン画を完成させた単語は、対応する品行ラベルとともに表示されます.
この二つを分けるために、まず空いているテーブルを作って、それからファスナーで二つを分けて、それぞれテーブルの中に入れればいいです.
sentences = []
pos_tags = []

for tagged_sentence in tagged_sentences:
  sentence, tag_info = zip(*tagged_sentence)
  sentences.append(list(sentence))
  pos_tags.append(list(tag_info))
sentencesの出力結果:
pos_tagsの出力結果:

単語と語類のマークが分かれています.
今回はKERASTORK NIZで整数符号化しよう

Encoding


文データもラベルも整数符号化が必要なので,一度に関数を生成して行う.
def tokenize(samples):
  tokenizer = Tokenizer()
  tokenizer.fit_on_texts(samples)
  return tokenizer
誰もが相手にコインを送ります.
src_token = tokenize(sentences)
tar_token = tokenize(pos_tags)
それぞれの大きさを見てみましょう.
vocab_size = len(src_token.word_index) + 1
tag_size = len(tar_token.word_index) + 1
print(vocab_size)
print(tag_size)

11388個の単語セットと47個のラベルが存在します.
彼にコードをあげましょう.
記事はX_train内で、ラベルはy_train内です.
X_train = src_token.texts_to_sequences(sentences)
y_train = tar_token.texts_to_sequences(pos_tags)
印刷して確認します.
print(X_train[:2])
print(y_train[:2])

今からダウンを作ろう

Padding


ダウンジャケットを作る前にmax_lenを注文します.
グラフで全長を一度に確認してみましょう.
plt.hist([len(s) for s in X_train], bins=50)
plt.xlabel('length of samples')
plt.ylabel('number of samples')
plt.show()

最大長さは150くらいまででいいです.
セットしてダウンを作ってあげましょう
max_len = 150
X_train = pad_sequences(X_train, padding='post', maxlen = max_len)
y_train = pad_sequences(y_train, padding='post', maxlen = max_len)
すべての前処理が終了し、テストサンプルとトレーニングサンプルに分けるべきです.

Split Sample

X_train, X_test, y_train, y_test = train_test_split(X_train, y_train, test_size=.2, random_state=777)
この列は分かれやすい.test_size=0.2は、すべてのデータセットの20%をtest(検証)セットとして指定することを意味する.random_stateは、対応するint値を結合時に表示および混合し、スーパーパラメータを調整する際に、データセットが変更されるたびに変更されないように固定および調整する必要があります.勝手に数字をつけてもいいです.

One-hot Encoding


対応するタグ情報を1対1で符号化します.
y_train = to_categorical(y_train, num_classes=tag_size)
y_test = to_categorical(y_test, num_classes=tag_size)
モデルを作成します.

Build Model


Packages

from keras.models import Sequential
from keras.layers import Dense, LSTM, InputLayer, Bidirectional, TimeDistributed, Embedding
from tensorflow.keras.optimizers import Adam
今から模型を作りましょう
model = Sequential()
model.add(Embedding(vocab_size, 128, input_length=max_len, mask_zero=True))
model.add(Bidirectional(LSTM(256, return_sequences=True)))
model.add(TimeDistributed(Dense(tag_size, activation=('softmax'))))
model.compile(optimizer=Adam(0.001), loss='categorical_crossentropy', metrics=['acc'])
val_dataを追加して学習します.
history=model.fit(X_train, y_train, batch_size=128, epochs=10, validation_data=(X_test,y_test))
評価してみよう
model.evaluate(X_test,y_test)[1]

93%ぐらいです.
最後にtrainセットとvalセットをグラフで確認します.
epochs = range(1, len(history.history['acc']) + 1)
plt.plot(epochs, history.history['acc'])
plt.plot(epochs, history.history['val_acc'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epochs')
plt.legend(['train', 'test'], loc='lower right')
plt.show()

epochs = range(1, len(history.history['loss']) + 1)
plt.plot(epochs, history.history['loss'])
plt.plot(epochs, history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epochs')
plt.legend(['train', 'test'], loc='upper right')
plt.show()

ここで説明を終わります