Reputation: 57
I have been trying to use tf.optimizer.AdagradDA with a Linear Classifier. Here is my code:
def input_fn():
features_in = { "random_var": tf.convert_to_tensor(np.random.randn(100)) }
labels_in = tf.convert_to_tensor(np.random.choice([0, 1], size=(100,), p=[1./2, 1./2]))
dataset = tf.data.Dataset.from_tensors((features_in, labels_in))
dataset.repeat(2)
dataset.batch(1)
iterator = dataset.make_one_shot_iterator()
features, labels = iterator.get_next()
return features, labels
def main():
global_step_tensor = tf.Variable(0, trainable=False, name='global_step')
optimizer = tf.train.AdagradDAOptimizer(learning_rate=0.001, global_step=global_step_tensor)
columns = [tf.feature_column.numeric_column('random_var')]
model = tf.estimator.LinearClassifier(optimizer=optimizer, feature_columns=columns)
model.train(input_fn=input_fn)
When I'm running the code I'm getting one of the following errors:
ValueError: Tensor("Identity_1:0", shape=(), dtype=int32) must be from the same graph as Tensor("linear/linear_model/random_var/weights/part_0:0", shape=(1, 1), dtype=float32_ref).
ValueError: Tensor("Identity_1:0", shape=(), dtype=int32) must be from the same graph as Tensor("linear/head/AdagradDA/update_linear/linear_model/random_var/weights/part_0/Cast_2/x:0", shape=(), dtype=float32)
ValueError: Tensor("Identity_1:0", shape=(), dtype=int32) must be from the same graph as Tensor("linear/linear/linear_model/random_var/weights/part_0/AdagradDA_1:0", shape=(1, 1), dtype=float32_ref).
When I run the same code with a FtrlOptimizer or a AdagradOptimize the code runs properly. So I'm guessing, the issue has to be related with the global_step_tensor
instanciation.
Here are the things that I have tried so far:
with tf.Session() as sess:
LinearClassifier
constructorUpvotes: 1
Views: 472
Reputation: 713
Caveat: This works in TensorFlow 1.10.0 (and possible later). Apparently it does not work in TensorFlow 1.9.0 (and possibly earlier). See comment below by ZakJ.
You need to change the way you construct your optimizer object as follows:
optimizer = lambda: tf.train.AdagradDAOptimizer(learning_rate=0.001,global_step=tf.train.get_global_step())
1) Notice the lambda. This will create a callable, as opposed to a Tensorflow operation
, which is what AdagradDAOptimizer
would return on its own (without the lambda).
2) You can use tf.train.get_global_step()
directly and don't have to define a global step tensor.
I'm not quite sure why you need to create a callable by adding the lambda in this case. But I guess whenever you want to use an optimizer that needs global_step
(or you want to pass it, for example for learning rate decay) you need to set the optimizer to a callable (hence the need for lambda) instead of a Tensorflow operation
.
This is also what the learning rate decay example does in the docs here.
This is the complete code I successfully ran on TensorFlow 1.10.0:
import tensorflow as tf
import numpy as np
def input_fn():
features_in = { "random_var": tf.convert_to_tensor(np.random.randn(100)) }
labels_in = tf.convert_to_tensor(np.random.choice([0, 1], size=(100,), p=[1./2, 1./2]))
dataset = tf.data.Dataset.from_tensors((features_in, labels_in))
dataset.repeat(2)
dataset.batch(1)
iterator = dataset.make_one_shot_iterator()
features, labels = iterator.get_next()
return features, labels
def main():
optimizer = lambda: tf.train.AdagradDAOptimizer(learning_rate=0.001,global_step=tf.train.get_global_step())
columns = [tf.feature_column.numeric_column('random_var')]
model = tf.estimator.LinearClassifier(optimizer=optimizer, feature_columns=columns)
model.train(input_fn=input_fn)
Upvotes: 1