How to pass `None` Batch Size to tensorflow dynamic rnn? - tensorflow

I am trying to build a CNN+LSTM+CTC model for word recognition.
Initially I have an image, I am converting the features extracted using CNN on word image and building a sequence of features which I am passing as sequential data to RNN.
Follwing is how I am converting the features to sequential data:
[[a1,b1,c1],[a2,b2,c2],[a3,b3,c3]] -> [[a1,a2,a3],[b1,b2,b3],[c1,c2,c3]]
Where a,b,c are 3 features extracted using CNN.
Presently I can pass a constant batch_size to the model common.BATCH_SIZE, but what I want is to be able to pass variable batch_size to the model.
How can this be done ?
inputs = tf.placeholder(tf.float32, [common.BATCH_SIZE, common.OUTPUT_SHAPE[1], common.OUTPUT_SHAPE[0], 1])
# Here we use sparse_placeholder that will generate a
# SparseTensor required by ctc_loss op.
targets = tf.sparse_placeholder(tf.int32)
# 1d array of size [batch_size]
seq_len = tf.placeholder(tf.int32, [common.BATCH_SIZE])
model = tf.layers.conv2d(inputs, 64, (3,3),strides=(1, 1), padding='same', name='c1')
model = tf.layers.max_pooling2d(model, (3,3), strides=(2,2), padding='same', name='m1')
model = tf.layers.conv2d(model, 128,(3,3), strides=(1, 1), padding='same', name='c2')
model = tf.layers.max_pooling2d(model, (3,3),strides=(2,2), padding='same', name='m2')
model = tf.transpose(model, [3,0,1,2])
shape = model.get_shape().as_list()
model = tf.reshape(model, [shape[0],-1,shape[2]*shape[3]])
cell = tf.nn.rnn_cell.LSTMCell(common.num_hidden, state_is_tuple=True)
cell = tf.nn.rnn_cell.DropoutWrapper(cell, input_keep_prob=0.5, output_keep_prob=0.5)
stack = tf.nn.rnn_cell.MultiRNNCell([cell]*common.num_layers, state_is_tuple=True)
outputs, _ = tf.nn.dynamic_rnn(cell, model, seq_len, dtype=tf.float32,time_major=True)
UPDATE:
batch_size = tf.placeholder(tf.int32, None, name='batch_size')
inputs = tf.placeholder(tf.float32, [batch_size, common.OUTPUT_SHAPE[1], common.OUTPUT_SHAPE[0], 1])
# Here we use sparse_placeholder that will generate a
# SparseTensor required by ctc_loss op.
targets = tf.sparse_placeholder(tf.int32)
# 1d array of size [batch_size]
seq_len = tf.placeholder(tf.int32, [batch_size])
model = tf.layers.conv2d(inputs, 64, (3,3),strides=(1, 1), padding='same', name='c1')
model = tf.layers.max_pooling2d(model, (3,3), strides=(2,2), padding='same', name='m1')
model = tf.layers.conv2d(model, 128,(3,3), strides=(1, 1), padding='same', name='c2')
model = tf.layers.max_pooling2d(model, (3,3),strides=(2,2), padding='same', name='m2')
model = tf.transpose(model, [3,0,1,2])
shape = model.get_shape().as_list()
model = tf.reshape(model, [shape[0],-1,shape[2]*shape[3]])
cell = tf.nn.rnn_cell.LSTMCell(common.num_hidden, state_is_tuple=True)
cell = tf.nn.rnn_cell.DropoutWrapper(cell, input_keep_prob=0.5, output_keep_prob=0.5)
stack = tf.nn.rnn_cell.MultiRNNCell([cell]*common.num_layers, state_is_tuple=True)
outputs, _ = tf.nn.dynamic_rnn(cell, model, seq_len, dtype=tf.float32,time_major=True)
I am getting error as below:
Traceback (most recent call last):
File "lstm_and_ctc_ocr_train.py", line 203, in <module>
train()
File "lstm_and_ctc_ocr_train.py", line 77, in train
logits, inputs, targets, seq_len, batch_size = model.get_train_model()
File "/home/himanshu/learning-tf/tf/code/tensorflow_lstm_ctc_ocr/model.py", line 20, in get_train_model
inputs = tf.placeholder(tf.float32, [batch_size, common.OUTPUT_SHAPE[1], common.OUTPUT_SHAPE[0], 1])
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/ops/array_ops.py", line 1530, in placeholder
return gen_array_ops._placeholder(dtype=dtype, shape=shape, name=name)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/ops/gen_array_ops.py", line 1954, in _placeholder
name=name)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/op_def_library.py", line 705, in apply_op
attr_value.shape.CopyFrom(_MakeShape(value, key))
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/op_def_library.py", line 198, in _MakeShape
return tensor_shape.as_shape(v).as_proto()
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/tensor_shape.py", line 798, in as_shape
return TensorShape(shape)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/tensor_shape.py", line 434, in __init__
self._dims = [as_dimension(d) for d in dims_iter]
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/tensor_shape.py", line 376, in as_dimension
return Dimension(value)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/tensor_shape.py", line 32, in __init__
self._value = int(value)
TypeError: int() argument must be a string or a number, not 'Tensor'

You should be able to pass batch_size to dynamic RNN as a placeholder. In my experience, the only headache you might experience is if you don't specify its shape in advance, so you should pass [] to make things work, something like this:
batchsize = tf.placeholder(tf.int32, [], name='batchsize')
and then feed its value during sess.run() in the usual way. This works well for me while training on a large batch size, but then generating with batch of 1.
But strictly speaking, you don't even need to specify batch size for dynamic_rnn specifically, do you? You need it if you use MultiRNNCell to get zero state, but I don't see you doing that in your code...
*** UPDATE:
As discussed in the comment, your problem seems to have nothing to do with dynamic_rnn and more to do with the fact that you are using a placeholder inputs to specify the shape of another placeholder seq_len. Here's the code that reproduces the same error:
import tensorflow as tf
a = tf.placeholder(tf.int32, None, name='a')
b = tf.placeholder(tf.int32, [a, 5], name='b')
c = b * 5
with tf.Session() as sess:
C = sess.run(c, feed_dict={a:1, b:[[1,2,3,4,5]]})
And here's the error:
TypeError: int() argument must be a string, a bytes-like object or a number, not 'Tensor'
Before getting to the headache of dynamic_rnn, I would recommend finding a way around this, either by changing your code or by asking a separate question on how to fudge it with placeholders.

Related

convLSTM2d w/ functional API

I have an autoencoder for image compression, where the encoded tensor has the shape: (batch_size, 12, 64, 48).
batch_size is the number of images being fed in a batch,
12 is the number of channels of this last encoder layer, which has a
64x48 width/height.
I want to input this to a ConvLSTM2D layer, and i would like the output of the ConvLSTM2D to have the same dimension as the input of the ConvLSTM2D.
The intention is to see image reconstruction on a video sequence, rather than unordered images from a dataset.
Placing a ConvLSTM2d between an encoder/decoder in a autoencoder architecture has been difficult, especially because most examples use the Sequential API, and i want to use the functional API in Keras.
I tried reshaping the input but the error persists
import tensorflow as tf
import tensorflow.keras.backend as K
def LSTM_layer(input):
input = tf.keras.backend.expand_dims(input, axis=-1)
lstm1 = tf.keras.layers.ConvLSTM2D(filters=12, kernel_size=(3, 3), strides=(1, 1), data_format="channels_first",
input_shape=(None, 12, 64, 48),
padding='same', return_sequences=True)(input)
return lstm1
def build_model(input_shape):
#create an input with input_shape as the size
input_ = tf.keras.Input(shape=input_shape, name="input_node")
lstm_features = LSTM_layer(input_)
model = tf.keras.Model(inputs=input_, outputs=[lstm_features])
return model
def main():
input_shape = (12, 64, 48) #this is the size of the tensor which is outputted by my encoder, with channels_first assumed
model = build_model(input_shape)
if __name__ == '__main__':
main()
Unfortunately, this is throwing this error:
Traceback (most recent call last):
File "lstm.py", line 29, in <module>
main()
File "lstm.py", line 26, in main
model = build_model(input_shape)
File "lstm.py", line 20, in build_model
model = tf.keras.Model(inputs=input_, outputs=[lstm_features])
File "/home/hallab/.local/lib/python3.5/site-packages/tensorflow/python/keras/engine/training.py", line 121, in __init__
super(Model, self).__init__(*args, **kwargs)
File "/home/hallab/.local/lib/python3.5/site-packages/tensorflow/python/keras/engine/network.py", line 80, in __init__
self._init_graph_network(*args, **kwargs)
File "/home/hallab/.local/lib/python3.5/site-packages/tensorflow/python/training/checkpointable/base.py", line 474, in _method_wrapper
method(self, *args, **kwargs)
File "/home/hallab/.local/lib/python3.5/site-packages/tensorflow/python/keras/engine/network.py", line 224, in _init_graph_network
'(thus holding past layer metadata). Found: ' + str(x))
ValueError: Output tensors to a Model must be the output of a TensorFlow `Layer` (thus holding past layer metadata). Found: Tensor("conv_lst_m2d/transpose_1:0", shape=(?, 12, 12, 48, 1), dtype=float32)
Most posts about this error instruct to wrap the operation in a lambda.. but i am not implementing a custom operation here, this should be a keras tf layer... right?
Also, in my implementation, i want the output tensor from the LSTM unit to be the same as the input, can i get some feedback about that as well?
Thank you.
You could use Lambda to wrap the output form K.expand_dims before input it to next layer like this:
import tensorflow as tf
import tensorflow.keras.backend as K
from tensorflow.keras.layers import Lambda
def expand_dims(x):
return K.expand_dims(x, 1)
def expand_dims_output_shape(input_shape):
return (input_shape[0], 1, input_shape[1])
def LSTM_layer(input_):
lstm1 = Lambda(expand_dims, expand_dims_output_shape)(input_)
lstm1 = tf.keras.layers.ConvLSTM2D(filters=12, kernel_size=(3, 3), strides=(1, 1), data_format="channels_first", padding='same', return_sequences=False)(lstm1)
return lstm1

Save the Keras model error: AttributeError: 'numpy.dtype' object has no attribute 'item'

I have tried to save my Keras model in pycharm where I got the error, this is how I created the model:
main_input = Input(shape=(X_train.shape[1],), dtype=X_train.dtype,
name='main_input')
xx = Embedding(output_dim=512, input_dim=3000, input_length=len(X))
(main_input)
xx= SpatialDropout1D(0.4)(xx)
lstm_out = LSTM(64)(xx)
#lstm_out = Dense(3,activation='softmax')(lstm_out)
from keras.layers import Input, Embedding, LSTM, Dense
from keras.models import Model
auxiliary_input = Input(shape=(Z_train.shape[1],), name='aux_input')
auxB= Input(shape=(hasB_train.shape[1],), name='aux_B')
auxM = Input(shape=(hasM_train.shape[1],), name='aux_M')
auxBM_input = keras.layers.concatenate([ auxB, auxM])
auxiliary_output = Dense(3, activation='softmax', name='aux_output') (lstm_out)
auxBM_output = Dense(3, activation='softmax', name='auxBM_output') (auxBM_input)
x = keras.layers.concatenate([lstm_out, auxiliary_input, auxBM_input])
x = Dense(64, activation='relu')(x)
x = Dense(64, activation='relu')(x)
x = Dense(64, activation='relu')(x)
main_output = Dense(3, activation='sigmoid', name='main_output')(x)
model = Model(inputs=[main_input, auxiliary_input, auxB, auxM], outputs= [main_output, auxiliary_output, auxBM_output])
model.compile(optimizer='rmsprop', loss='categorical_crossentropy' ,metrics = ['accuracy'], loss_weights=[4, 1, 10])
model.summary()
when I run the this code model.save('model.h5'), I receive the below error:
Traceback (most recent call last): File
"C:/.../ENV/newDataset/combined3.py", line 209, in
model.save('blah.h5') File "C:\ProgramData\Anaconda2\envs\Building_Deep_Learning_Keras\lib\site-packages\keras\engine\network.py",
line 1085, in save
save_model(self, filepath, overwrite, include_optimizer) File "C:\ProgramData\Anaconda2\envs\Building_Deep_Learning_Keras\lib\site-packages\keras\engine\saving.py",
line 117, in save_model
}, default=get_json_type).encode('utf8') File "C:\ProgramData\Anaconda2\envs\Building_Deep_Learning_Keras\lib\json__init__.py",
line 237, in dumps
**kw).encode(obj) File "C:\ProgramData\Anaconda2\envs\Building_Deep_Learning_Keras\lib\json\encoder.py",
line 198, in encode
chunks = self.iterencode(o, _one_shot=True) File "C:\ProgramData\Anaconda2\envs\Building_Deep_Learning_Keras\lib\json\encoder.py",
line 256, in iterencode
return _iterencode(o, 0) File "C:\ProgramData\Anaconda2\envs\Building_Deep_Learning_Keras\lib\site-packages\keras\engine\saving.py",
line 84, in get_json_type
return obj.item() AttributeError: 'numpy.dtype' object has no attribute 'item'
I have no problem, if I run the below code:
model = Sequential()
model.add(Embedding(max_fatures, embed_dim,input_length = X.shape[1]))
model.add(SpatialDropout1D(0.4))
model.add(LSTM(lstm_out, dropout=0.2, recurrent_dropout=0.2))
model.add(Dense(3,activation='softmax'))
model.compile(loss = 'categorical_crossentropy', optimizer='adam',metrics = ['accuracy'])
X_train, X_test, Y_train, Y_test = train_test_split(X,Y,train_size=0.8, random_state = 42)
model.fit(X_train, Y_train, epochs = 1, batch_size=32,shuffle=True)
model.save('test.h5')
I believe you are having this issue because of how Keras handles the dtype argument when you are creating a Functional Model. Keras expects the dtype to be just a simple string and not a numpy.dtype object, and therefore, it will have difficulty saving the model when you pass a numpy object into this argument.
To adjust, I would use one of the strings to describe the data input type, as suggested at https://keras.io/backend/.
I had a similar issue, and when I changed the dtype argument to what Keras was expecting (a string), I was able to save the model without any additional problem.
To fix your issue, I would suggest, changing the dtype=X_train.dtype argument to dtype=X_train.dtype.name, as this would produce the string form of the dtype, which can be handled by Keras.

Generate a series of tensors using RNN

I am building a rnn and I use tf.nn.dynamic_rnn to yield the output and state.
The code is as follows (tf version 1.3):
import tensorflow as tf
def lstm_cell():
return tf.contrib.rnn.DropoutWrapper(tf.contrib.rnn.BasicLSTMCell(128), output_keep_prob=0.7)
cell= tf.contrib.rnn.MultiRNNCell([lstm_cell() for _ in range(3)])
initial_state= cell.zero_state(1, tf.float32)
layer = tf.placeholder(tf.float32, [1,1,36])
outputs, state=tf.nn.dynamic_rnn(cell=cell, inputs=layer, initial_state=initial_state)
Since the input tensor is always of batch size =1, the initial_state and state also have a batch size 1.
layer is an input of batch_size=1 as well, and for each cell there are 36 nodes(size of the embedded sequence). Each layer has lstm_size 128.
The problem comes when I loop the rnn cell.
rnn_outputs_sequence=outputs
for i in range(1, num_pics, 1):
outputs, state=tf.nn.dynamic_rnn(cell=cell, inputs=outputs, initial_state=state)
rnn_outputs_sequence=tf.concat((rnn_outputs_sequence, outputs),axis=1)
rnn_outputs_sequence is expected to have shape [1, num_pics, 36].However, this triggers an error:
Trying to share variable rnn/multi_rnn_cell/cell_0/basic_lstm_cell/kernel, but specified shape (256, 512) and found shape (164, 512).
I cannot figure out this shape [164, 512].
Can anyone help me with this out?
Thanks.
import tensorflow as tf
def lstm_cell():
return tf.contrib.rnn.DropoutWrapper(tf.contrib.rnn.BasicLSTMCell(128), output_keep_prob=0.7)
cell= tf.contrib.rnn.MultiRNNCell([lstm_cell() for _ in range(2)])
initial_state= cell.zero_state(1, tf.float32)
layer = tf.placeholder(tf.float32, [1,1,36])
outputs, state=tf.nn.dynamic_rnn(cell=cell, inputs=layer, initial_state=initial_state)
outputs = tf.reshape(outputs, shape=[1, -1])
outputs = tf.layers.dense(outputs, 36,\
kernel_initializer=tf.contrib.layers.xavier_initializer(uniform=False))
outputs = tf.reshape(outputs, shape=[1, 1, -1])
rnn_outputs_sequence=outputs
print(outputs)
for i in range(1, 16, 1):
outputs, state=tf.nn.dynamic_rnn(cell=cell, inputs=outputs, initial_state=state)
outputs = tf.reshape(outputs, shape=[1, -1])
outputs = tf.layers.dense(outputs, 36,\
kernel_initializer=tf.contrib.layers.xavier_initializer(uniform=False))
outputs = tf.reshape(outputs, shape=[1, 1, -1])
print(outputs)
rnn_outputs_sequence=tf.concat((rnn_outputs_sequence, outputs),axis=1)
print(rnn_outputs_sequence)

What's the equivalent of this Keras code in TensorFlow?

The code is as below and runs perfectly:
import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Dropout
xData = np.array([[5, 3, 7], [1, 2, 6], [8, 7, 6]], dtype=np.float32)
yTrainData = np.array([[1], [0], [1]], dtype=np.float32)
model = Sequential()
model.add(Dense(64, input_dim=3, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='rmsprop', metrics=['accuracy'])
model.fit(xData, yTrainData, epochs=10, batch_size=128, verbose=2)
xTestData = np.array([[2, 8, 1], [3, 1, 9]], dtype=np.float32)
resultAry = model.predict(xTestData)
print("Cal result: %s" % resultAry)
I can't work out the code in TensowFlow, something I've written is like this:
import tensorflow as tf
import numpy as np
xData = np.array([[5, 3, 7], [1, 2, 6], [8, 7, 6]], dtype=np.float32)
yTrainData = np.array([[1], [0], [1]], dtype=np.float32)
x = tf.placeholder(tf.float32)
yTrain = tf.placeholder(tf.float32)
w = tf.Variable(tf.ones([64]), dtype=tf.float32)
b = tf.Variable(tf.zeros([1]), dtype=tf.float32)
y = tf.nn.relu(w * x + b)
w1 = tf.Variable(tf.ones([3]), dtype=tf.float32)
b1 = tf.Variable(0, dtype=tf.float32)
y1 = tf.reduce_mean(tf.nn.sigmoid(w1 * y + b1))
loss = tf.abs(y1 - tf.reduce_mean(yTrain))
optimizer = tf.train.AdadeltaOptimizer(0.1)
train = optimizer.minimize(loss)
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
for i in range(10):
for j in range(3):
result = sess.run([loss, y1, yTrain, x, w, b, train], feed_dict={x: xData[j], yTrain: yTrainData[j]})
if i % 10 == 0:
print("i: %d, j: %d, loss: %10.10f, y1: %f, yTrain: %s, x: %s" % (i, j, float(result[0]), float(result[1]), yTrainData[j], xData[j]))
result = sess.run([y1, loss], feed_dict={x: [1, 6, 0], yTrain: 0})
print(result)
But I will got the following error while running,
Traceback (most recent call last):
File "C:\Python36\lib\site-packages\tensorflow\python\client\session.py", line 1327, in _do_call
return fn(*args)
File "C:\Python36\lib\site-packages\tensorflow\python\client\session.py", line 1306, in _run_fn
status, run_metadata)
File "C:\Python36\lib\contextlib.py", line 88, in __exit__
next(self.gen)
File "C:\Python36\lib\site-packages\tensorflow\python\framework\errors_impl.py", line 466, in raise_exception_on_not_ok_status
pywrap_tensorflow.TF_GetCode(status))
tensorflow.python.framework.errors_impl.InvalidArgumentError: Incompatible shapes: [64] vs. [3]
[[Node: mul = Mul[T=DT_FLOAT, _device="/job:localhost/replica:0/task:0/cpu:0"](Variable/read, _arg_Placeholder_0_0)]]
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "testidc.py", line 36, in <module>
result = sess.run([loss, y1, yTrain, x, w, b, train], feed_dict={x: xData[j], yTrain: yTrainData[j]})
File "C:\Python36\lib\site-packages\tensorflow\python\client\session.py", line 895, in run
run_metadata_ptr)
File "C:\Python36\lib\site-packages\tensorflow\python\client\session.py", line 1124, in _run
feed_dict_tensor, options, run_metadata)
File "C:\Python36\lib\site-packages\tensorflow\python\client\session.py", line 1321, in _do_run
options, run_metadata)
File "C:\Python36\lib\site-packages\tensorflow\python\client\session.py", line 1340, in _do_call
raise type(e)(node_def, op, message)
tensorflow.python.framework.errors_impl.InvalidArgumentError: Incompatible shapes: [64] vs. [3]
[[Node: mul = Mul[T=DT_FLOAT, _device="/job:localhost/replica:0/task:0/cpu:0"](Variable/read, _arg_Placeholder_0_0)]]
Caused by op 'mul', defined at:
File "testidc.py", line 15, in <module>
y = tf.nn.relu(w * x + b)
File "C:\Python36\lib\site-packages\tensorflow\python\ops\variables.py", line 705, in _run_op
return getattr(ops.Tensor, operator)(a._AsTensor(), *args)
File "C:\Python36\lib\site-packages\tensorflow\python\ops\math_ops.py", line 865, in binary_op_wrapper
return func(x, y, name=name)
File "C:\Python36\lib\site-packages\tensorflow\python\ops\math_ops.py", line 1088, in _mul_dispatch
return gen_math_ops._mul(x, y, name=name)
File "C:\Python36\lib\site-packages\tensorflow\python\ops\gen_math_ops.py", line 1449, in _mul
result = _op_def_lib.apply_op("Mul", x=x, y=y, name=name)
File "C:\Python36\lib\site-packages\tensorflow\python\framework\op_def_library.py", line 767, in apply_op
op_def=op_def)
File "C:\Python36\lib\site-packages\tensorflow\python\framework\ops.py", line 2630, in create_op
original_op=self._default_original_op, op_def=op_def)
File "C:\Python36\lib\site-packages\tensorflow\python\framework\ops.py", line 1204, in __init__
self._traceback = self._graph._extract_stack() # pylint: disable=protected-access
InvalidArgumentError (see above for traceback): Incompatible shapes: [64] vs. [3]
[[Node: mul = Mul[T=DT_FLOAT, _device="/job:localhost/replica:0/task:0/cpu:0"](Variable/read, _arg_Placeholder_0_0)]]
The main reason is the shape of W, must be the same as x in TensowFlow, but in Keras, the hidden Dense layer could have more nodes than the input(such as 64 in the example).
I need help for the equivalent TensorFlow code instead of the Keras one. Thanks.
This is an example that uses the tf.estimator.Estimator framework:
import tensorflow as tf
import numpy as np
# The model
def model(features):
dense = tf.layers.dense(inputs=features['x'], units=64, activation=tf.nn.relu)
dropout = tf.layers.dropout(dense, 0.2)
logits = tf.layers.dense(inputs=dropout, units=1, activation=tf.nn.sigmoid)
return logits
# Stuff needed to use the tf.estimator.Estimator framework
def model_fn(features, labels, mode):
logits = model(features)
predictions = {
'classes': tf.argmax(input=logits, axis=1),
'probabilities': tf.nn.softmax(logits)
}
if mode == tf.estimator.ModeKeys.PREDICT:
return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions)
loss = tf.losses.softmax_cross_entropy(onehot_labels=labels, logits=logits)
# Configure the training op
if mode == tf.estimator.ModeKeys.TRAIN:
optimizer = tf.train.RMSPropOptimizer(learning_rate=1e-4)
train_op = optimizer.minimize(loss, tf.train.get_or_create_global_step())
else:
train_op = None
accuracy = tf.metrics.accuracy(
tf.argmax(labels, axis=1), predictions['classes'])
metrics = {'accuracy': accuracy}
# Create a tensor named train_accuracy for logging purposes
tf.identity(accuracy[1], name='train_accuracy')
tf.summary.scalar('train_accuracy', accuracy[1])
return tf.estimator.EstimatorSpec(
mode=mode,
predictions=predictions,
loss=loss,
train_op=train_op,
eval_metric_ops=metrics)
# Setting up input for the model
def input_fn(mode, batch_size):
# function that processes your input and returns two tensors "samples" and "labels"
# that the estimator will use to fetch input batches.
# See https://www.tensorflow.org/get_started/input_fn for how to write this function.
return samples, labels
# Using the model
def main():
# Create the Estimator
classifier = tf.estimator.Estimator(
model_fn=model_fn, model_dir='some_dir')
# Train the model
# NOTE: I use this to make it compatible with your example, but you should
# defnitely set up your own input_fn above
train_input_fn = tf.estimator.inputs.numpy_input_fn(
x={"x": np.array([[5, 3, 7], [1, 2, 6], [8, 7, 6]], dtype=np.float32)},
y=np.array([[1], [0], [1]]),
num_epochs=10,
batch_size=128,
shuffle=False)
classifier.train(
input_fn=train_input_fn,
steps=20000, # change as needed
)
# Predict on new data
predict_input_fn = tf.estimator.inputs.numpy_input_fn(
x={"x": np.array([[5, 3, 7], [1, 2, 6], [8, 7, 6]], dtype=np.float32)},
num_epochs=1,
batch_size=1,
shuffle=False)
predictions_iterator = classifier.predict(
input_fn=predict_input_fn)
print('Predictions results:')
for pred in predictions_iterator:
print(pred)
There is quite bit going on here, so I'll try to explain the blocks one by one.
The model
The model is defined as a composition of tf.layers in a separate model function. This is done to keep the actual model_fn (which is required by the Estimator framework) independent of the model architecture.
The function takes a features parameter, which is the output of a call to input_fn (see below). In this example, since we're using tf.estimator.inputs.numpy_input_fn, features is a dictionary with item x:input_tensor. We use the input tensor as input for our model graph.
model_fn
This function is required by the framework and is used to generate a specification for your Estimator that is dependent on the mode the estimato is being used for. Typically, an estimator used for prediction will have less operations than when it's used for training (you don't have the loss, optimizer, etc). This function takes care of adding all that is necessary to your model graph for the three possible modes of operation (prediction, evaluation, training).
Breaking it down to logical pieces, we have:
Prediction: we only need the model graph, the predictions and the corresponding predicted labels (we could skip the labels, but having it here is handy).
Evaluation: we need everything for prediction plus: a loss function, some metric to evaluate on and optionally some summaries to visualize the metrics in Tensorboard.
Training: we need everything for evaluation plus: a training operation from an optimizer (in your sample, RMSProp)
input_fn
This is where we provide the input to our estimator.
Have a look at Building Input Functions with tf.estimator for a guide on how your custom input_fn should look like. For the example, we'll use the numpy_input_fn function from the framework.
Note that usually one input_fn handles all operation modes according to a mode parameter. Since we're using numpy_input_fn, we need two different instances of it for training and prediction to provide the data as needed.
main
Here we actually train and use the estimator.
Firstly, we get an Estimator instance with the model_fn we specified, then we call train() and wait for the training to be over.
Once that is done, calling predict() returns an iterable that you can use to get the prediction results for all the samples in the dataset you're predicting.
This is a couple of months old but it's worth noting that there is absolutely no reason to not use keras with tensorflow. It's even part of the tensorflow library now!
So if you want full control of your tensors but still want to use keras' layers, you can easily achieve that by using keras as-is:
x = tf.placeholder(tf.float32, [None, 1024])
y = keras.layers.Dense(512, activation='relu')(x)
For more on that, keras' creator made a pretty cool post about it.

Cannot convert partially known tensor in TensorFlow/TFLearn

I'm a beginner to TensorFlow and still trying to figure out how it works, so I'm not sure if the error is a problem with my architecture or something more basic -- here I'm trying to train a siamese neural network (we feed a left and right input into left and right NN with identical weights, and try to map it to feature vectors that have small distance if the inputs are similar and large distance if the inputs are different).
The error I get occurs at the regression step:
File "siamese.py", line 59, in <module>
network = regression(y_pred, optimizer='adam',
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/tflearn/models/dnn.py", line 63, in __init__
best_val_accuracy=best_val_accuracy)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/tflearn/helpers/trainer.py", line 120, in __init__
clip_gradients)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/tflearn/helpers/trainer.py", line 646, in initialize_training_ops
ema_num_updates=self.training_steps)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/tflearn/summaries.py", line 236, in add_loss_summaries
loss_averages_op = loss_averages.apply([loss] + other_losses)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/tensorflow/python/training/moving_averages.py", line 292, in apply
colocate_with_primary=(var.op.type == "Variable"))
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/tensorflow/python/training/slot_creator.py", line 106, in create_zeros_slot
val = array_ops.zeros(primary.get_shape().as_list(), dtype=dtype)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/tensorflow/python/ops/array_ops.py", line 1071, in zeros
shape = ops.convert_to_tensor(shape, dtype=dtypes.int32, name="shape")
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/tensorflow/python/framework/ops.py", line 628, in convert_to_tensor
ret = conversion_func(value, dtype=dtype, name=name, as_ref=as_ref)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/tensorflow/python/framework/constant_op.py", line 198, in _tensor_shape_tensor_conversion_function
"Cannot convert a partially known TensorShape to a Tensor: %s" % s)
ValueError: Cannot convert a partially known TensorShape to a Tensor: (?,)
I don't know how to resolve this problem if the first dimension needs to be None for the batch size (correct me if I'm wrong).
Relevant parts of the code are below:
BATCH_SIZE=100
def contrastive_loss(y_pred, y_true, margin=1.0):
return tf.mul(1-y_true, tf.square(y_pred)) + tf.mul(y_true, tf.square(tf.maximum((margin-y_pred),0)))
## Load dataset
f = h5py.File('./data/paired_training_data.hdf','r')
X1 = f["train_X1"]
X2 = f["train_X2"]
Y = f["train_Y_paired"]
## Inputs: 1 example (phoneme pair), dropout probability
inp_sound1 = input_data(shape=[None, 1, N_MFCC_CHANNELS, N_IN_CHANNELS])
networkL = conv_1d(inp_sound1, reuse=None, scope="conv1d")
networkL = max_pool_1x6(networkL)
networkL = fully_connected(networkL, n_units=N_FULLY_CONN, activation='relu', scope="fc1")
networkL = dropout(networkL, .5) # unshared?
networkL = fully_connected(networkL, n_units=N_FULLY_CONN, activation='relu', scope="fc2")
inp_sound2 = input_data(shape=[None, 1, N_MFCC_CHANNELS, N_IN_CHANNELS])
networkR = conv_1d(inp_sound2, reuse=True, scope="conv1d")
networkR = max_pool_1x6(networkR)
networkR = fully_connected(networkR, n_units=N_FULLY_CONN, activation='relu', reuse=True, scope="fc1")
networkR = dropout(networkR, .5)
networkR = fully_connected(networkR, n_units=N_FULLY_CONN, activation='relu', reuse=True, scope="fc2")
l2_loss = tf.reduce_sum(tf.square(tf.sub(networkL, networkR)), 1)
y_pred = tf.sqrt(l2_loss)
#y_true = input_data(shape=[None])
## Training
network = regression(y_pred, optimizer='adam',
loss=contrastive_loss, learning_rate=0.0001, to_one_hot=False)
model = tflearn.DNN(network, tensorboard_verbose=0)
model.fit([X1, X2], Y, n_epoch=10, batch_size=BATCH_SIZE, show_metric=True, validation_set=0.1)
Any help -- especially with understanding how to debug these issues on my own in the future -- would be greatly appreciated!
It looks like TensorFlow cannot infer the shape of your contrastive_loss. Try to call set_shape in your contrastive_loss function if you know its output shape in advance:
def contrastive_loss(y_pred, y_true, margin=1.0):
loss = tf.mul(1-y_true, tf.square(y_pred)) + tf.mul(y_true, tf.square(tf.maximum((margin-y_pred),0)))
loss.set_shape([...])
return loss