- Published on
Character-Aware Neural Language Models
- Authors
- Name
- Minato Sato
- @minatosatou
この記事は自然言語処理 Advent Calendar 2017の11日目の記事になります。
AAAI 2016で発表されたCharacter-Aware Neural Language Modelsという論文を読んだので紹介します。
言語モデル
言語モデルとは
そもそも言語モデル(language model)とは、ある単語の系列が与えられたときに、次に来る単語を予測することをモデリングしているものです。例えばある単語の系列
が与えられたときに、単語が出現する確率は
と表されます。言語モデルは、この確率について頻出する単語の系列が与えられたときに高くなるように学習します。
パープレキシティ
言語モデルの評価には、パープレキシティ(perplexity)が使われることが多いです。
100%単語の出現を予測することができればとなり、 パープレキシティは1.0になります。逆に予測ができなければできないほどパープレキシティは1よりも大きくなります。モデルとデータの量にもよりますが、数十から百強程度が適正範囲かもしれません。
Character-Aware Neural Language Models
概要
入力が文字レベルだけの言語モデル作ったよ。出力は相変わらず単語レベルだよ。文字レベルの入力をCNNしてHighwayして出てきた出力をLSTMなRNN-LM(Recurrent neural network language model)に食わせるよ。英語のPenn Treebankにおいては、既存モデルよりパラメータ数60%少ないけど同等の性能だったよ。
モデル
入力は文字埋め込み(character embeddings)の系列を文書の長さ分だけ用意したテンソル(i.e. shape=(文書の長さ, 単語の長さ, 文字埋め込みの次元数))。各単語ごとにTemporal Conv(i.e. One-dimensional Conv)とTemporal Max-poolingを行い(i.e. shape=(文書の長さ, フィルタ枚数))、Highwayし、最後にLSTMに流し込む(i.e. output shape=(文書の長さ, 単語の語彙サイズ))。
実験結果
English Penn Treebank
考察
Kerasによる実装
モデル構築
from keras.layers import Conv2D
from keras.layers import MaxPooling2D
from keras.layers import Highway
from keras.layers import Input
from keras.layers import Embedding
from keras.layers import TimeDistributed
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Reshape
from keras.layers import Concatenate
from keras.layers import LSTM
from keras.layers import BatchNormalization
from keras.models import Model
def build_lstm_char_cnn(batch_size = 20,
word_length = 10,
sentence_length = 100,
word_vocab_size = 10000,
char_vocab_size = 100,
char_embedding_dim = 128,
lstm_size = 650,
dropout_ratio = 0.5):
filsters = [50, 100, 150, 200, 200, 200, 200]
filster_sizes = [1, 2, 3, 4, 5, 6, 7]
x = Input(batch_shape=(batch_size, sentence_length, word_length))
char_embeddings = TimeDistributed(Embedding(char_vocab_size, char_embedding_dim))(x)
output = []
for f, f_size in zip(filsters, filster_sizes):
h = Conv2D(f, (1, f_size), activation='tanh')(char_embeddings)
h = MaxPooling2D(pool_size=(1, word_length-f_size+1))(h)
h = Reshape((sentence_length, f))(h)
output.append(h)
h = Concatenate()(output)
h = BatchNormalization()(h)
h = TimeDistributed(Highway(activation='relu'))(h)
h = TimeDistributed(Highway(activation='relu'))(h)
h = LSTM(lstm_size, activation='tanh', recurrent_activation='sigmoid', return_sequences=True)(h)
h = LSTM(lstm_size, activation='tanh', recurrent_activation='sigmoid', return_sequences=True)(h)
h = Dropout(dropout_ratio)(h)
output = TimeDistributed(Dense(word_vocab_size, activation='softmax'))(h)
return Model(x, output)
実験結果
パープレキシティの推移は後日載せますが、とりあえず学習した結果得られたword(char sequence) embeddingsについて各クエリに最も近い5語を表示してみました。論文の実験結果に近づいた!
----------------
searching for most similar 5 words to "while" ...
['where', 'whenever', 'chile', 'wheels', 'when']
----------------
searching for most similar 5 words to "his" ...
['its', 'this', 'hhs', 'eric', 'the']
----------------
searching for most similar 5 words to "you" ...
['boy', 'nobody', 'do', 'we', 'dog']
----------------
searching for most similar 5 words to "richard" ...
['gerard', 'bernard', 'leonard', 'sanford', 'maynard']
----------------
searching for most similar 5 words to "trading" ...
['engaging', 'heading', 'riding', 'reading', 'sliding']
----------------
input word does not appear in vocabulary data
calculating word embedding of "computer-aided" ... done!
searching for most similar 5 words to "computer-aided" ...
['computer-guided', 'computerized', 'competitive', 'prosecuted', 'high-priced']
----------------
input word does not appear in vocabulary data
calculating word embedding of "misinformed" ... done!
searching for most similar 5 words to "misinformed" ...
['informed', 'performed', 'confirmed', 'emphasized', 'speculated']
----------------
input word does not appear in vocabulary data
calculating word embedding of "looooook" ... done!
searching for most similar 5 words to "looooook" ...
['look', 'outlook', 'cook', 'book', 'took']
----------------