Как исправить «символические тензоры», используйте «steps_per_epoch», но не ошибку «batch_size» в простой сети conv2d + жидкого состояния - PullRequest
1 голос
/ 21 мая 2019

Я делаю простой динамический резервуар conv2d + (настраиваемый рекуррентный слой со случайными / фиксированными соединениями, который выводит только последние состояния узла временного шага). Резервуар записан в виде лямбда-слоя для реализации простого уравнения, как показано в коде. Модель может быть построена Керасом.

Я надеюсь, что модель будет обучена для классификации некоторых последовательностей изображений с заданным размером пакета. (например, batch_size = 2) Таким образом, в идеале Keras должен распределять пакеты размером 2x3x8x8x1, поскольку набор данных имеет размер 10x3x8x8x1. Слой Conv2d с распределением по времени должен возвращать 2x3x6x6x3. Последующий настроенный выравнивающий слой должен сгладить не временные размеры и вернуть 2x3x108. Резервный слой с 108 узлами должен возвращать 2x108. И последний считывающий слой должен вернуть 2x5.

import keras
from keras.layers import Dense, Convolution2D, Activation, Lambda
from keras.layers.wrappers import TimeDistributed
from keras.models import Sequential

from keras import backend as K
import tensorflow as tf

import numpy as np

# Flatten the non-time dimensions
def flatten_tstep(x_in): # Input shape (None, 3, 6, 6, 3), Output shape (None, 3, 108)
    shape = K.shape( x_in ) # tensor shape
    x_out = K.reshape( x_in, [shape[0], shape[1], K.prod(shape[1:])] )
    return x_out

def flatten_tstep_shape( x_shape ) :
    n_batch, n_tsteps, n_rows, n_cols, n_filters = x_shape
    output_shape = ( n_batch, n_tsteps, n_rows * n_cols * n_filters ) # Flatten 
    return output_shape

# Simple Reservior
# Use a single batch as an example, the input (size 3x108) is of 3 time steps to the 108 nodes in the reserivor.
# The states of the nodes are stat_neuron (size 1x108)
# For t in range(3)
#   stat_neuron = stat_neuron * decay_coefficient + input[t, :] + recurrent_connection_matrix * stat_neuron
# End
# This layer effectively returns the states of the node in the last time step
def ag_reservior(x_in): # Input shape (None, 3, 108), Output shape (None, 108)
    shape = K.shape( x_in ) # tensor shape
    stat_neuron = K.zeros([shape[0], shape[2]]) # initialize Neuron states    
    t_step = tf.constant(0) # Initialize time counter, shifted by 1
    t_max = tf.subtract(shape[1], tf.constant(1)) # Maximum time steps, shifted by 1
    x = x_in
    def cond(t_step, t_max, stat_neuron, x):
        return tf.less(t_step, t_max)
    def body(t_step, t_max, stat_neuron, x):
        global RC_MATRIX, C_DECAY # Connection matrix, decay constant
        temp = tf.scalar_mul(C_DECAY, stat_neuron) #  stat_neuron * decay_coefficient    
        temp = tf.add(temp, x[:, t_step, :]) # stat_neuron * decay_coefficient + input[t, :]
        temp = tf.add(temp, tf.einsum('ij,bj->bi', RC_MATRIX, stat_neuron)) # out[batch,i]=sum_j RC_MATRIX[i,j]*stat_neuron[batch,j]
        return [tf.add(t_step, 1), t_max, temp, x]
    res = tf.while_loop(cond, body, [t_step, t_max, stat_neuron, x])
    return res[2]

def ag_reservior_shape( x_shape ) :
    in_batch, in_tsteps, in_nodes = x_shape
    output_shape = ( in_batch, in_nodes )
    return output_shape

#%% Parameters

n_sample = 10; # number of samples;
n_tstep = 3; # number of time steps per sample
n_row = 8; # number of rows per frame
n_col = 8; # number of columns per frame
n_channel = 1; # number of channel

RC_MATRIX = K.random_normal([108, 108]) # Reservior layer node recurrent connection matrix, note there are 108 nodes
C_DECAY = K.constant(0.9) # Recurrent layer node time-to-time decay coefficient

data = K.random_normal([n_sample, n_tstep, n_row, n_col, 1]) # Some random dataset
# data = np.random.randn(n_sample, n_tstep, n_row, n_col, 1)
label = np.random.randint(5, size=n_sample) # Some random dataset labels
label_onehot = K.one_hot(label, 5)

x_train = data
y_train = label_onehot

x_test = data
y_test = label_onehot

#%% Model

model=Sequential();

# Convolution Kernels: Input shape (batch_size, 3, 8, 8, 1), Output shape (batch_size, 3, 6, 6, 3)
model.add(TimeDistributed(Convolution2D(3, (3, 3), strides=1, padding='valid', use_bias=False, 
                                        kernel_initializer='random_uniform', trainable=False), input_shape = (n_tstep, n_row, n_col, n_channel)))

# Flatten non-time dimensions: Input shape (batch_size, 3, 6, 6, 3), Output shape (batch_size, 3, 108)
model.add(Lambda(flatten_tstep, output_shape = flatten_tstep_shape))

# Reservior: Input shape (batch_size 3, 108), Output shape (batch_size, 108)
model.add(Lambda(ag_reservior, output_shape = ag_reservior_shape))

# Reservior Read-out: Input shape (batch_size, 108), Output shape (batch_size, 5)
model.add(Dense(5, use_bias=False))
model.add(Activation('softmax'))

# Check model
model.summary()

#%% Training
opt = keras.optimizers.rmsprop(lr = 0.01, decay = 1e-6)
model.compile(loss='categorical_crossentropy', optimizer = opt, metrics = ['acc'])
history = model.fit(x_train, y_train, epochs = 50, validation_data = (x_test, y_test), batch_size = 2)

Однако Керас сказал: «Если ваши данные представлены в виде символических тензоров, вы должны указать аргумент steps_per_epoch (вместо аргумента batch_size, поскольку ожидается, что символические тензоры будут генерировать пакеты входных данных)».

Не могли бы вы посоветовать, как позволить Keras правильно распознать размер партии и перейти к обучению? (Обратите внимание, что слой Conv2d фиксирован, лямбда-слои также фиксированы, только последний плотный слой нуждается в обучении.)

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 27 мая 2019

Это решается с помощью этого кода ...

import keras
from keras.datasets import mnist
from keras.layers import Convolution2D, Dense, Flatten, Activation, Lambda
from keras.layers.wrappers import TimeDistributed
from keras.models import Sequential
import scipy.io

from keras import backend as K
import tensorflow as tf

import numpy as np
import matplotlib.pyplot as plt 

# Simple Reservior
# Use a single batch as an example, the input (size 3x108) is of 3 time steps to the 108 nodes in the reserivor.
# The states of the nodes are stat_neuron (size 1x108)
# For t in range(3)
#   stat_neuron = stat_neuron * decay_coefficient + input[t, :] + recurrent_connection_matrix * stat_neuron
# End
# This layer effectively returns the states of the node in the last time step
def ag_reservior(x_in): # Input shape (None, 3, 108), Output shape (None, 108)
    shape = K.shape( x_in ) # tensor shape
    stat_neuron = K.zeros([shape[0], shape[2]]) # initialize Neuron states    
    t_step = tf.constant(0) # Initialize time counter, shifted by 1
    t_max = shape[1] # Maximum time steps, shifted by 1
    x = x_in
    def cond(t_step, t_max, stat_neuron, x):
        return tf.less(t_step, t_max)
    def body(t_step, t_max, stat_neuron, x):
        global RC_MATRIX, C_DECAY # Connection matrix, decay constant
        temp = tf.scalar_mul(C_DECAY, stat_neuron) #  stat_neuron * decay_coefficient    
        temp = tf.add(temp, x[:, t_step, :]) # stat_neuron * decay_coefficient + input[t, :]
        temp = tf.add(temp, tf.einsum('ij,bj->bi', RC_MATRIX, stat_neuron)) # out[batch,i]=sum_j RC_MATRIX[i,j]*stat_neuron[batch,j]
        return [tf.add(t_step, 1), t_max, temp, x]
    res = tf.while_loop(cond, body, [t_step, t_max, stat_neuron, x])
    return res[2]

def ag_reservior_shape( x_shape ) :
    in_batch, in_tsteps, in_nodes = x_shape
    output_shape = ( in_batch, in_nodes )
    return output_shape

#%% Parameters

n_neurons = 4096; # number of neurons in the reservoir (same with the last dim of the flatten layer);

RC_MATRIX = K.random_normal([n_neurons, n_neurons], mean=0, stddev=1/n_neurons) # Reservior layer node recurrent connection matrix
C_DECAY = K.constant(0.5) # Diffusive memristor time-to-time decay coefficient

# Load training data from the .mat file
mat_contents = scipy.io.loadmat('mnist_sequence_kerasimport.mat')
x_train = mat_contents['xs_train']
x_test = mat_contents['xs_test']
y_train = mat_contents['ys_train']
y_test = mat_contents['ys_test']
# Reshape x_train, x_test into 5D array
x_train = x_train.reshape(x_train.shape[0], x_train.shape[1], x_train.shape[2], x_train.shape[3], 1)
x_test = x_test.reshape(x_test.shape[0], x_test.shape[1], x_test.shape[2], x_test.shape[3], 1)

#%% Model

model=Sequential();

# Convolution Kernels: Input shape (batch_size, 3, 8, 8, 1), Output shape (batch_size, 3, 8, 8, 64)
model.add(TimeDistributed(Convolution2D(64, (3, 3), strides=1, padding='same', use_bias=False, 
                                        kernel_initializer='random_uniform', trainable=False), input_shape = (x_train.shape[1:])))

model.add(TimeDistributed(Flatten()))

# Reservior: Input shape (batch_size 3, 108), Output shape (batch_size, 108)
model.add(Lambda(ag_reservior, output_shape = ag_reservior_shape))

# Reservior Read-out: Input shape (batch_size, 108), Output shape (batch_size, 5)
model.add(Dense(6, use_bias=False))
model.add(Activation('softmax'))

# Check model
model.summary()

#%% Training
opt = keras.optimizers.rmsprop(lr = 0.01, decay = 1e-6)
model.compile(loss='categorical_crossentropy', optimizer = opt, metrics = ['acc'])
history = model.fit(x_train, y_train, epochs = 2, validation_data = (x_test, y_test), batch_size = 50)
0 голосов
/ 23 мая 2019

Эта ошибка означает, что один из ваших тензоров данных, который используется Fit (), является символическим тензором.Функция горячей метки возвращает символический тензор.Попробуйте что-то вроде:

label_onehot = tf.Session (). Run (K.one_hot (label, 5))

Я лично не пробовал это с Keras напрямую - если это не такне работайте с Keras, попробуйте использовать горячую функцию tf one вместо горячей функции Keras one.

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