ZeroPadding Dynamic для шага> 1 и доступ к фактической форме тензора измерения Нет в Керасе - PullRequest
0 голосов
/ 13 октября 2018

Я пытаюсь реализовать динамическое заполнение нулями, чтобы сохранить второе измерение постоянного тензора после прохождения сверточных слоев с шагом> 1, тензор ввода имеет следующую форму (batch_size, time_step, 50), мне нужноизмерение временного шага не будет изменено сверточными слоями.Я попытался использовать «тот же» отступ, однако, когда шаг> 1, это не работает, поэтому я создал собственный слой для ZeroPadding, он работает для тензоров с формой (None, 100,50), (None, 120,50), (Нет, 60,50), но не работает для динамических фигур типа (Нет, Нет, 50), я получаю следующую ошибку:

Traceback (most recent call last):
  File "keras-dinamic-padding-for-stride.py", line 120, in <module>
    model.add (ZeroPadding1D (dinamic_padding_stride = 2))
  File "/home/edresson/anaconda3/lib/python3.6/site-packages/keras/engine/sequential.py", line 181, in add
    output_tensor = layer (self.outputs [0])
  File "/home/edresson/anaconda3/lib/python3.6/site-packages/keras/engine/base_layer.py", line 457, in __call__
    output = self.call (inputs, ** kwargs)
  File "keras-dinamic-padding-for-stride.py", line 67, in call
    padding = int (inputs.shape [1] * self.dinamic_padding_stride)
TypeError: __int__ returned non-int (type NoneType)

Я добавил свой пользовательский класск примеру IMDB, чтобы было проще воспроизвести ошибки.Измените model.add (Embedding (max_features, embedding_dims, input_length = None)) на model.add (Embedding (max_features, embedding_dims, input_length = 400)) и динамическое заполнение будет работать, однако оно должно работать для измерения типа None.Код:

from __future__ import print_function

from keras.preprocessing import sequence
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation
from keras.layers import Embedding
from keras.layers import Conv1D, GlobalMaxPooling1D,Lambda
from keras.datasets import imdb


from keras.engine.topology import Layer,InputSpec
from keras.utils import conv_utils
import keras.backend as K

class ZeroPadding1D(Layer):
    """Zero-padding layer for 1D input (e.g. temporal sequence).

    # Arguments
        padding: int, or tuple of int (length 2), or dictionary.
            - If int:
            How many zeros to add at the beginning and end of
            the padding dimension (axis 1).
            - If tuple of int (length 2):
            How many zeros to add at the beginning and at the end of
            the padding dimension (`(left_pad, right_pad)`).
         dinamic_padding_stride: int
             - if used it totally ignores the padding parameter
             - is used to maintain the size of an input when
               passed through a convolutional layer, adding the
               fill with zeros dynamically. Note: the posterior
               convolutional layer should use padding = 'same'

    # Input shape
        3D tensor with shape `(batch, axis_to_pad, features)`

    # Output shape
        3D tensor with shape `(batch, padded_axis, features)`
    """

    def __init__(self, padding=1,dinamic_padding_stride=None, **kwargs):
        super(ZeroPadding1D, self).__init__(**kwargs)
        self.padding = conv_utils.normalize_tuple(padding, 2, 'padding')
        self.input_spec = InputSpec(ndim=3)
        self.dinamic_padding_stride = dinamic_padding_stride


    def compute_output_shape(self, input_shape):
        if input_shape[1] is not None:
            if self.dinamic_padding_stride is not None :
                padding =  input_shape[1] * self.dinamic_padding_stride - input_shape[1] 
                self.padding = (int(padding/2),int(padding/2))
            length = input_shape[1] + self.padding[0] + self.padding[1]
        else:
            length = None
        return (input_shape[0],
                length,
                input_shape[2])

    def call(self, inputs):
        if self.dinamic_padding_stride is not None:
            padding = int(inputs.shape[1] * self.dinamic_padding_stride)
            self.padding = (int(padding/2),int(padding/2)) 
        return K.temporal_padding(inputs, padding=self.padding)

    def get_config(self):
        config = {'padding': self.padding}
        base_config = super(ZeroPadding1D, self).get_config()
        return dict(list(base_config.items()) + list(config.items()))







# set parameters:
max_features = 5000
maxlen = 400
batch_size = 32
embedding_dims = 50
filters = 250
kernel_size = 3
hidden_dims = 250
epochs = 2

print('Loading data...')
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features)
print(len(x_train), 'train sequences')
print(len(x_test), 'test sequences')

print('Pad sequences (samples x time)')
x_train = sequence.pad_sequences(x_train, maxlen=maxlen)
x_test = sequence.pad_sequences(x_test, maxlen=maxlen)
print('x_train shape:', x_train.shape)
print('x_test shape:', x_test.shape)

print('Build model...')
model = Sequential()

# we start off with an efficient embedding layer which maps
# our vocab indices into embedding_dims dimensions
model.add(Embedding(max_features,
                    embedding_dims,
                    input_length=None))
model.add(Dropout(0.2))

# we add a Convolution1D, which will learn filters
# word group filters of size filter_length:
model.add(Conv1D(filters,
                 kernel_size,
                 padding='same',
                 activation='relu',
                 strides=1))
model.add(ZeroPadding1D(dinamic_padding_stride=2))
model.add(Conv1D(filters,
                 kernel_size,
                 padding='same',
                 activation='relu',
                 strides=2))
# we use max pooling:
model.add(GlobalMaxPooling1D())

# We add a vanilla hidden layer:
model.add(Dense(hidden_dims))
model.add(Dropout(0.2))
model.add(Activation('relu'))

# We project onto a single unit output layer, and squash it with a sigmoid:
model.add(Dense(1))
model.add(Activation('sigmoid'))

model.compile(loss='binary_crossentropy',
              optimizer='adam',
              metrics=['accuracy']) 
model.summary()
model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
validation_data=(x_test, y_test))

Я искал и увидел, что мне нужно использовать K.shape (входы), чтобы получить правильную форму во время выполнения вместо None, но я не мог заставить его работать с Keras,Кто-нибудь может мне помочь?

Если у вас есть другое решение для решения проблемы нулевого динамического заполнения, это очень приветствуется.

Заранее благодарю за внимание.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...