私はIMDB exampleに基づいてBLSTMを実行していますが、私のバージョンは分類ではなく、ラベルのシーケンス予測です。簡単にするため、POSタギングモデルとして扱うことができます。入力は単語の文、出力はタグです。この例で使用される構文は、model.add
を使用せず、シーケンスを開始する点で、他のほとんどのKerasの例と構文が少し異なります。このわずかに異なる構文でマスクレイヤーを追加する方法を理解できません。ケラス用マスキングBLSTM
モデルを実行してテストしたところ、うまく動作しましたが、パディングである0の精度を予測して評価しています。ここでは、コードです:
from __future__ import print_function
import numpy as np
from keras.preprocessing import sequence
from keras.models import Model
from keras.layers.core import Masking
from keras.layers import TimeDistributed, Dense
from keras.layers import Dropout, Embedding, LSTM, Input, merge
from prep_nn import prep_scan
from keras.utils import np_utils, generic_utils
np.random.seed(1337) # for reproducibility
nb_words = 20000 # max. size of vocab
nb_classes = 10 # number of labels
hidden = 500 # 500 gives best results so far
batch_size = 10 # create and update net after 10 lines
val_split = .1
epochs = 15
# input for X is multi-dimensional numpy array with IDs,
# one line per array. input y is multi-dimensional numpy array with
# binary arrays for each value of each label.
# maxlen is length of longest line
print('Loading data...')
(X_train, y_train), (X_test, y_test) = prep_scan(
nb_words=nb_words, test_len=75)
print(len(X_train), 'train sequences')
print(int(len(X_train)*val_split), 'validation sequences')
print(len(X_test), 'heldout sequences')
# this is the placeholder tensor for the input sequences
sequence = Input(shape=(maxlen,), dtype='int32')
# this embedding layer will transform the sequences of integers
# into vectors
embedded = Embedding(nb_words, output_dim=hidden,
input_length=maxlen)(sequence)
# apply forwards LSTM
forwards = LSTM(output_dim=hidden, return_sequences=True)(embedded)
# apply backwards LSTM
backwards = LSTM(output_dim=hidden, return_sequences=True,
go_backwards=True)(embedded)
# concatenate the outputs of the 2 LSTMs
merged = merge([forwards, backwards], mode='concat', concat_axis=-1)
after_dp = Dropout(0.15)(merged)
# TimeDistributed for sequence
# change activation to sigmoid?
output = TimeDistributed(
Dense(output_dim=nb_classes,
activation='softmax'))(after_dp)
model = Model(input=sequence, output=output)
# try using different optimizers and different optimizer configs
# loss=binary_crossentropy, optimizer=rmsprop
model.compile(loss='categorical_crossentropy',
metrics=['accuracy'], optimizer='adam')
print('Train...')
model.fit(X_train, y_train,
batch_size=batch_size,
nb_epoch=epochs,
shuffle=True,
validation_split=val_split)
UPDATE:
私はこのPRを合併し、それは埋め込み層にmask_zero=True
と協力してしまいました。しかし、私はモデルのひどいパフォーマンスを見て、出力でマスキングする必要があるのを見て、今実現しています。他の人はmodel.fit
行の代わりにsample_weightを使用するように提案しています。 0を無視するにはどうすればいいですか?
UPDATE 2:
だから私はthisを読み、1と0の行列としてsample_weight
を考え出しました。私はそれが動作している可能性があると思ったが、私の精度は%50前後で止まってしまった。そして、パッディングされた部分を予測しようとしているが、sample_weightを使用する前の問題と同様に、
現在のコード:
from __future__ import print_function
import numpy as np
from keras.preprocessing import sequence
from keras.models import Model
from keras.layers.core import Masking
from keras.layers import TimeDistributed, Dense
from keras.layers import Dropout, Embedding, LSTM, Input, merge
from prep_nn import prep_scan
from keras.utils import np_utils, generic_utils
import itertools
from itertools import chain
from sklearn.preprocessing import LabelBinarizer
import sklearn
import pandas as pd
np.random.seed(1337) # for reproducibility
nb_words = 20000 # max. size of vocab
nb_classes = 10 # number of labels
hidden = 500 # 500 gives best results so far
batch_size = 10 # create and update net after 10 lines
val_split = .1
epochs = 10
# input for X is multi-dimensional numpy array with syll IDs,
# one line per array. input y is multi-dimensional numpy array with
# binary arrays for each value of each label.
# maxlen is length of longest line
print('Loading data...')
(X_train, y_train), (X_test, y_test), maxlen, sylls_ids, tags_ids, weights = prep_scan(nb_words=nb_words, test_len=75)
print(len(X_train), 'train sequences')
print(int(len(X_train) * val_split), 'validation sequences')
print(len(X_test), 'heldout sequences')
# this is the placeholder tensor for the input sequences
sequence = Input(shape=(maxlen,), dtype='int32')
# this embedding layer will transform the sequences of integers
# into vectors of size 256
embedded = Embedding(nb_words, output_dim=hidden,
input_length=maxlen, mask_zero=True)(sequence)
# apply forwards LSTM
forwards = LSTM(output_dim=hidden, return_sequences=True)(embedded)
# apply backwards LSTM
backwards = LSTM(output_dim=hidden, return_sequences=True,
go_backwards=True)(embedded)
# concatenate the outputs of the 2 LSTMs
merged = merge([forwards, backwards], mode='concat', concat_axis=-1)
# after_dp = Dropout(0.)(merged)
# TimeDistributed for sequence
# change activation to sigmoid?
output = TimeDistributed(
Dense(output_dim=nb_classes,
activation='softmax'))(merged)
model = Model(input=sequence, output=output)
# try using different optimizers and different optimizer configs
# loss=binary_crossentropy, optimizer=rmsprop
model.compile(loss='categorical_crossentropy',
metrics=['accuracy'], optimizer='adam',
sample_weight_mode='temporal')
print('Train...')
model.fit(X_train, y_train,
batch_size=batch_size,
nb_epoch=epochs,
shuffle=True,
validation_split=val_split,
sample_weight=weights)
これは古い質問ですが、これを解決しましたか?私は同じ段階です...私は[精度は 'sample_weight'を考慮していません(https://github.com/fchollet/keras/issues/1642)と私のテストによると、マスキング(実際にマスキングを使用すると、私はまだ動かないほどの精度の値が得られます)。おそらく機能的APIを使用して、精度で2番目の出力を構築することになります。 – jdehesa
この問題を再検討し、現在のKerasコードに関して簡潔にしていただければ幸いです。 – Seanny123