我正在制作一个简单的conv2d +动态库(具有随机/固定连接的自定义循环层,仅输出最后一个时间步节点状态)。该存储库被编写为lambda层,以实现代码中所示的简单方程式。该模型可以由Keras构建。
我希望训练模型可以对具有给定批次大小的某些图像序列进行分类。 (例如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)
但是Keras说:“如果您的数据采用符号张量的形式,则应指定steps_per_epoch
参数(而不是batch_size
参数,因为期望符号张量会产生成批的输入数据)。
您能建议如何让Keras正确识别批次大小并进行培训吗? (请注意,Conv2d层是固定的,lambda层也是固定的,只有最后一个密集层需要训练。)
谢谢。
答案 0 :(得分:0)
该错误意味着Fit()使用的数据张量之一是符号张量。一个热标签函数返回一个符号张量。尝试类似的东西:
label_onehot = tf.Session()。run(K.one_hot(label,5))
我个人还没有直接在Keras上尝试过-如果它不适用于Keras,请尝试使用tf one hot函数而不是Keras one hot函数。
答案 1 :(得分:0)
使用此代码已解决...
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)
答案 2 :(得分:0)
尝试在张量上使用eval()或numpy()函数,以便将它们转换为numpy数组。
检查: this article