20

私は、シーケンス内の次の要素を予測するKerasを使用してLSTMでいくつかのバニラパターン認識を行うことをしようとしています。Kerasで可変長入力LSTMを作成するにはどうすればよいですか?

私のデータは次のようになります。トレーニングシーケンスのラベルはリストの最後の要素である

My data

X_train['Sequence'][n][-1]

Sequence列はシーケンスの要素の可変数を持つことができるので、私はRNNを使用するのに最適なモデルであると信じます。以下はKerasでLSTMを構築するための私の試みです:

# Build the model 

# A few arbitrary constants... 
max_features = 20000 
out_size = 128 

# The max length should be the length of the longest sequence (minus one to account for the label) 
max_length = X_train['Sequence'].apply(len).max() - 1 

# Normal LSTM model construction with sigmoid activation 
model = Sequential() 
model.add(Embedding(max_features, out_size, input_length=max_length, dropout=0.2)) 
model.add(LSTM(128, dropout_W=0.2, dropout_U=0.2)) 
model.add(Dense(1)) 
model.add(Activation('sigmoid')) 

# try using different optimizers and different optimizer configs 
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) 

そして、ここでは、私は私のモデルを訓練しようと方法は次のとおりです。

# Train the model 
for seq in X_train['Sequence']: 
    print("Length of training is {0}".format(len(seq[:-1]))) 
    print("Training set is {0}".format(seq[:-1])) 
    model.fit(np.array([seq[:-1]]), [seq[-1]]) 

は私の出力は次のとおりです。ただし

Length of training is 13 
Training set is [1, 3, 13, 87, 1053, 28576, 2141733, 508147108, 402135275365, 1073376057490373, 9700385489355970183, 298434346895322960005291, 31479360095907908092817694945] 

、私は次のエラーが表示されます。

Exception: Error when checking model input: expected embedding_input_1 to have shape (None, 347) but got array with shape (1, 13) 

I私の訓練のステップが正しく設定されていると信じて、私のモデル構築が間違っていなければならない。 347はmax_lengthです。

どのように私が正しくKerasに可変長の入力LSTMを構築することができますか?私はデータをパッドしたくないと思う。関連性があるかどうかはわかりませんが、私はTheanoバックエンドを使用しています。

+1

私はinput_shapeを指定し、任意の長さのためにどれを使用していないことで、この作業を取得するために管理。 – Benjamin

+1

おそらく私自身の質問があなたの役に立つかもしれません:http://stackoverflow.com/questions/38265922/recurrent-convolutional-blstm-neural-network-arbitrary-sequence-lengths – Benjamin

答えて

11

私は、埋め込み手順については明らかではないと思います。しかし、ここでも可変長入力LSTMを実装する方法があります。 LSTMを構築するときにタイムパンディメンションを指定しないでください。

import keras.backend as K 
from keras.layers import LSTM, Input 

I = Input(shape=(None, 200)) # unknown timespan, fixed feature size 
lstm = LSTM(20) 
f = K.function(inputs=[I], outputs=[lstm(I)]) 

import numpy as np 
data1 = np.random.random(size=(1, 100, 200)) # batch_size = 1, timespan = 100 
print f([data1])[0].shape 
# (1, 20) 

data2 = np.random.random(size=(1, 314, 200)) # batch_size = 1, timespan = 314 
print f([data2])[0].shape 
# (1, 20) 
+2

それはどのように機能を取得するかを示していますが、あなたはそれを訓練し、予測のために使用しますか? – Seanny123

1

訓練と分類の配列にトリックは、マスキングやステートフルネットワークを使用して分類するとトレーニングです。ここで私はそれが可変長の列がゼロかで始まるかどうかを分類して作られた例です。

import numpy as np 
np.random.seed(1) 

import tensorflow as tf 
tf.set_random_seed(1) 

from keras import models 
from keras.layers import Dense, Masking, LSTM 

import matplotlib.pyplot as plt 


def stateful_model(): 
    hidden_units = 256 

    model = models.Sequential() 
    model.add(LSTM(hidden_units, batch_input_shape=(1, 1, 1), return_sequences=False, stateful=True)) 
    model.add(Dense(1, activation='relu', name='output')) 

    model.compile(loss='binary_crossentropy', optimizer='rmsprop') 

    return model 


def train_rnn(x_train, y_train, max_len, mask): 
    epochs = 10 
    batch_size = 200 

    vec_dims = 1 
    hidden_units = 256 
    in_shape = (max_len, vec_dims) 

    model = models.Sequential() 

    model.add(Masking(mask, name="in_layer", input_shape=in_shape,)) 
    model.add(LSTM(hidden_units, return_sequences=False)) 
    model.add(Dense(1, activation='relu', name='output')) 

    model.compile(loss='binary_crossentropy', optimizer='rmsprop') 

    model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, 
       validation_split=0.05) 

    return model 


def gen_train_sig_cls_pair(t_stops, num_examples, mask): 
    x = [] 
    y = [] 
    max_t = int(np.max(t_stops)) 

    for t_stop in t_stops: 
     one_indices = np.random.choice(a=num_examples, size=num_examples // 2, replace=False) 

     sig = np.zeros((num_examples, max_t), dtype=np.int8) 
     sig[one_indices, 0] = 1 
     sig[:, t_stop:] = mask 
     x.append(sig) 

     cls = np.zeros(num_examples, dtype=np.bool) 
     cls[one_indices] = 1 
     y.append(cls) 

    return np.concatenate(x, axis=0), np.concatenate(y, axis=0) 


def gen_test_sig_cls_pair(t_stops, num_examples): 
    x = [] 
    y = [] 

    for t_stop in t_stops: 
     one_indices = np.random.choice(a=num_examples, size=num_examples // 2, replace=False) 

     sig = np.zeros((num_examples, t_stop), dtype=np.bool) 
     sig[one_indices, 0] = 1 
     x.extend(list(sig)) 

     cls = np.zeros((num_examples, t_stop), dtype=np.bool) 
     cls[one_indices] = 1 
     y.extend(list(cls)) 

    return x, y 


if __name__ == '__main__': 
    noise_mag = 0.01 
    mask_val = -10 
    signal_lengths = (10, 15, 20) 

    x_in, y_in = gen_train_sig_cls_pair(signal_lengths, 10, mask_val) 

    mod = train_rnn(x_in[:, :, None], y_in, int(np.max(signal_lengths)), mask_val) 

    testing_dat, expected = gen_test_sig_cls_pair(signal_lengths, 3) 

    state_mod = stateful_model() 
    state_mod.set_weights(mod.get_weights()) 

    res = [] 
    for s_i in range(len(testing_dat)): 
     seq_in = list(testing_dat[s_i]) 
     seq_len = len(seq_in) 

     for t_i in range(seq_len): 
      res.extend(state_mod.predict(np.array([[[seq_in[t_i]]]]))) 

     state_mod.reset_states() 

    fig, axes = plt.subplots(2) 
    axes[0].plot(np.concatenate(testing_dat), label="input") 

    axes[1].plot(res, "ro", label="result", alpha=0.2) 
    axes[1].plot(np.concatenate(expected, axis=0), "bo", label="expected", alpha=0.2) 
    axes[1].legend(bbox_to_anchor=(1.1, 1)) 

    plt.show() 
0

他の要因とは対照的に、各要素は、その前のシーケンスにどのように強く依存すなわち、リカレントネットワークはあなたの順序のためにどのように適用されないことを確認。 (あなたには当然のことではありませんが)あなたの入力に何か悪い価値をつけたいのでなければ、一度に1つのタイムステップを処理するステートフルモデルが可変長シーケンスの唯一の選択肢ですIMHO 。あなたはエンコーディングの代替的なアプローチを取って気にしない場合:しかし、とんでもない損失で

1, 2, 4, 5, 8, 10 predicts 11, expecting 16 
1, 2, 1, 5, 5, 1, 11, 16 predicts 7, expecting 7 

import numpy as np 
import keras.models as kem 
import keras.layers as kel 
import keras.callbacks as kec 
import sklearn.preprocessing as skprep 

X_train, max_features = {'Sequence': [[1, 2, 4, 5, 8, 10, 16], [1, 2, 1, 5, 5, 1, 11, 16, 7]]}, 16 

num_mem_units = 64 
size_batch = 1 
num_timesteps = 1 
num_features = 1 
num_targets = 1 
num_epochs = 1500 

model = kem.Sequential() 
model.add(kel.LSTM(num_mem_units, stateful=True, batch_input_shape=(size_batch, num_timesteps, num_features), 
    return_sequences=True)) 
model.add(kel.Dense(num_targets, activation='sigmoid')) 
model.summary() 
model.compile(loss='binary_crossentropy', optimizer='adam') 

range_act = (0, 1) # sigmoid 
range_features = np.array([0, max_features]).reshape(-1, 1) 
normalizer = skprep.MinMaxScaler(feature_range=range_act) 
normalizer.fit(range_features) 

reset_state = kec.LambdaCallback(on_epoch_end=lambda *_ : model.reset_states()) 

# training 
for seq in X_train['Sequence']: 
    X = seq[:-1] 
    y = seq[1:] # predict next element 
    X_norm = normalizer.transform(np.array(X).reshape(-1, 1)).reshape(-1, num_timesteps, num_features) 
    y_norm = normalizer.transform(np.array(y).reshape(-1, 1)).reshape(-1, num_timesteps, num_targets) 
    model.fit(X_norm, y_norm, epochs=num_epochs, batch_size=size_batch, shuffle=False, 
     callbacks=[reset_state]) 

# prediction 
for seq in X_train['Sequence']: 
    model.reset_states() 
    for istep in range(len(seq)-1): # input up to not incl last 
     val = seq[istep] 
     X = np.array([val]).reshape(-1, 1) 
     X_norm = normalizer.transform(X).reshape(-1, num_timesteps, num_features) 
     y_norm = model.predict(X_norm) 
    yhat = int(normalizer.inverse_transform(y_norm[0])[0, 0]) 
    y = seq[-1] # last 
    put = '{0} predicts {1:d}, expecting {2:d}'.format(', '.join(str(val) for val in seq[:-1]), yhat, y) 
    print(put) 

のようなSTHを生成します。

関連する問題