keras中的可变长度输出

时间:2017-07-15 11:46:57

标签: deep-learning keras

我正在尝试使用bucketing在keras中创建一个自动编码器,其中输入和输出具有不同的时间步长。

./directory
|
+-- subdirectory1/
|   |
|   + fileA.md  
|
+-- subdirectory2/
    |
    + fileA.md  
    + ...

对于输入,没有问题,因为只要整个批次具有相同的长度,网络就可以接受不同长度的输入。但问题是输出大小是由RepeatVector长度决定的,并且没有简单的方法来改变它。

这样的问题有解决方案吗?

1 个答案:

答案 0 :(得分:0)

如果您的意思是"输入长度可变的"和"输出长度与输入相同",你可以这样做:

  

警告:此解决方案必须适用于批量大小= 1
  您将需要创建一个外部循环并将每个样本作为具有精确长度
的numpy数组传递   您不能在此解决方案中使用屏蔽,正确的输出取决于输入的正确长度

这是使用Keras + Tensorflow的工作代码:

进口:

from keras.layers import *
from keras.models import Model
import numpy as np
import keras.backend as K
from keras.utils.np_utils import to_categorical

要在Lambda图层中使用的自定义函数:

#this function gets the length from the original input 
#and stores it in the final output of the encoder
def storeLength(x):
    inputTensor = x[0]
    storeInto = x[1] #the final output

    length = K.shape(inputTensor)[1]
    length = K.cast(length,K.floatx())
    length = K.reshape(length,(1,1))

    #will put length as the first element in the final output
    return K.concatenate([length,storeInto])


#this function expands the length of the input in the decoder
def expandLength(x):
    #lenght is the first element in the encoded input
    length = K.cast(x[0,0],'int32') #or int64 if necessary

    #the remaining elements are the actual data to be decoded
    data = x[:,1:]

    #a tensor with shape (length,)
    length = K.ones_like(K.arange(0,length))

    #make both length tensor and data tensor 3D and with paired dimensions 
    length = K.cast(K.reshape(length,(1,-1,1)),K.floatx())
    data = K.reshape(data,(1,1,-1))

    #this automatically repeats the elements based on the paired shapes
    return data*length 

创建模型:

我假设输出等于输入,但由于您使用了嵌入,我制作了#34; num_classes"等于单词的数量。

对于此解决方案,我们使用分支,因此我必须使用功能API Model。以后会更好,因为您需要使用autoencoder.train_on_batch进行训练,然后只使用encoder.predict()进行编码,或者只使用decoder.predict()进行解码。

vocab_size = 100
embedding_size = 7
num_class=vocab_size
hidden_size = 3

#encoder
inputs = Input(batch_shape = (1,None))
outputs = Embedding(vocab_size, embedding_size)(inputs)
outputs = LSTM(units=hidden_size, return_sequences=False)(outputs)
outputs = Lambda(storeLength)([inputs,outputs])
encoder = Model(inputs,outputs)

#decoder
inputs = Input(batch_shape=(1,hidden_size+1))
outputs = Lambda(expandLength)(inputs)
outputs = LSTM(units=hidden_size, return_sequences=True)(outputs)
outputs = TimeDistributed(Dense(num_class, activation='softmax'))(outputs)
decoder = Model(inputs,outputs)

#autoencoder
inputs = Input(batch_shape=(1,None))
outputs = encoder(inputs)
outputs = decoder(outputs)
autoencoder = Model(inputs,outputs)

#see each model's shapes 
encoder.summary()
decoder.summary()
autoencoder.summary()

只是假数据和应该用于培训的方法的示例:

inputData = []
outputData = []
for i in range(7,10):
    inp = np.arange(i).reshape((1,i))
    inputData.append(inp)

    outputData.append(to_categorical(inp,num_class))

autoencoder.compile(loss='mse',optimizer='adam')

for epoch in range(1):
    for inputSample,outputSample in zip(inputData,outputData):

        print(inputSample.shape,outputSample.shape)
        autoencoder.train_on_batch(inputSample,outputSample)

for inputSample in inputData:
    print(autoencoder.predict(inputSample).shape)