TensorFlow中的模板()
我试图使用make_template()来避免在我的模型中传递重用标志。 但似乎make_template()在python类中使用时无法正确工作。 我粘贴]我的模型代码和我得到的错误。 在MNIST数据集上训练是一个简单的MLP。
由于代码有点长,这里的主要部分是_weights()函数。 我尝试使用make_template()来封装它,然后使用get_variables()在其中创建并重新使用整个模型中的权重。 _weights()由_create_dense_layer()使用,并由_create_model()用来创建图形。 train()函数接受我从数据读取器获得的张量。
模型
class MLP(object): def __init__(self, hidden=[], biases=False, activation=tf.nn.relu): self.graph = tf.get_default_graph() self.hidden = hidden self.activation = activation self.biases = biases self.n_features = 784 self.n_classes = 10 self.bsize = 100 self.l2 = 0.1 def _real_weights(self, shape): initializer=tf.truncated_normal_initializer(stddev=0.1) weights = tf.get_variable('weights', shape, initializer=initializer) return weights # use make_template to make variable reuse transparent _weights = tf.make_template('_weights', _real_weights) def _real_biases(self, shape): initializer=tf.constant_initializer(0.0) return tf.get_variable('biases', shape, initializer=initializer) # use make_template to make variable reuse transparent _biases = tf.make_template('_biases', _real_biases) def _create_dense_layer(self, name, inputs, n_in, n_out, activation=True): with tf.variable_scope(name): weights = self._weights([n_in, n_out]) layer = tf.matmul(inputs, weights) if self.biases: biases = self._biases([n_out]) layer = layer + biases if activation: layer = self.activation(layer) return layer def _create_model(self, inputs): n_in = self.n_features for i in range(len(self.hidden)): n_out = self.hidden[i] name = 'hidden%d' % (i) inputs = self._create_dense_layer(name, inputs, n_in, n_out) n_in = n_out output = self._create_dense_layer('output', inputs, n_in, self.n_classes, activation=False) return output def _create_loss_op(self, logits, labels): cent = tf.nn.softmax_cross_entropy_with_logits(logits, labels) weights = self.graph.get_collection('weights') l2 = (self.l2 / self.bsize) * tf.reduce_sum([tf.reduce_sum(tf.square(w)) for w in weights]) return tf.reduce_mean(cent, name='loss') + l2 def _create_train_op(self, loss): optimizer = tf.train.AdamOptimizer() return optimizer.minimize(loss) def _create_accuracy_op(self, logits, labels): predictions = tf.nn.softmax(logits) errors = tf.equal(tf.argmax(predictions, 1), tf.argmax(labels, 1)) return tf.reduce_mean(tf.cast(errors, tf.float32)) def train(self, images, labels): logits = model._create_model(images) loss = model._create_loss_op(logits, labels) return model._create_train_op(loss) def accuracy(self, images, labels): logits = model._create_model(images) return model._create_accuracy_op(logits, labels) def predict(self, images): return model._create_model(images)
错误:
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) in () 25 model = MLP(hidden=[128]) 26 # define ops ---> 27 train = model.train(images, labels) 28 accuracy = model.accuracy(eval_images, eval_labels) 29 # load test data and create a prediction op in train(self, images, labels) 60 61 def train(self, images, labels): ---> 62 logits = model._create_model(images) 63 loss = model._create_loss_op(logits, labels) 64 return model._create_train_op(loss) in _create_model(self, inputs) 39 n_out = self.hidden[i] 40 name = 'hidden%d' % (i) ---> 41 inputs = self._create_dense_layer(name, inputs, n_in, n_out) 42 n_in = n_out 43 output = self._create_dense_layer('output', inputs, n_in, self.n_classes, activation=False) in _create_dense_layer(self, name, inputs, n_in, n_out, activation) 25 def _create_dense_layer(self, name, inputs, n_in, n_out, activation=True): 26 with tf.variable_scope(name): ---> 27 weights = self._weights([n_in, n_out]) 28 layer = tf.matmul(inputs, weights) 29 if self.biases: /usr/local/lib/python3.5/site-packages/tensorflow/python/ops/template.py in __call__(self, *args, **kwargs) 265 self._unique_name, self._name) as vs: 266 self._var_scope = vs --> 267 return self._call_func(args, kwargs, check_for_new_variables=False) 268 269 @property /usr/local/lib/python3.5/site-packages/tensorflow/python/ops/template.py in _call_func(self, args, kwargs, check_for_new_variables) 206 ops.get_collection(ops.GraphKeys.TRAINABLE_VARIABLES)) 207 --> 208 result = self._func(*args, **kwargs) 209 if check_for_new_variables: 210 trainable_variables = ops.get_collection( TypeError: _real_weights() missing 1 required positional argument: 'shape' originally defined at: File "", line 1, in class MLP(object): File "", line 17, in MLP _weights = tf.make_template('_weights', _real_weights)
此代码存在多个问题,例如train
的model
参考, accuracy
和predict
方法。 我认为这是由于从自然栖息地切割代码。
你提到的TypeError
的原因,
TypeError: _real_weights() missing 1 required positional argument: 'shape'
最有可能来自_real_weights
本身是MLP
类的实例方法,而不是常规函数或静态方法。 因此,函数的第一个参数始终是在调用时指向类实例的self
引用(C类语言中this
指针的显式版本),如函数声明中所示:
def _real_weights(self, shape):
initializer=tf.truncated_normal_initializer(stddev=0.1)
weights = tf.get_variable('weights', shape, initializer=initializer)
return weights
请注意,即使您不使用参数,在这种情况下仍然需要。 因此在创建函数的模板时使用
tf.make_template('_weights', self._real_weights)
你基本上认为你创建的_weights
模板应该有两个位置参数: self
和weights
(就像_real_weights
方法一样)。 因此,当您将从模板创建的函数调用为
weights = self._weights([n_in, n_out])
您将数组传递给self
参数,而未指定(必需的) shape
参。
从看起来你会在这里有两个选择:你可以让_real_weights
成为MLP
类之外的常规函数,这样
def _real_weights(shape):
initializer=tf.truncated_normal_initializer(stddev=0.1)
weights = tf.get_variable('weights', shape, initializer=initializer)
return weights
class MLP():
# etc.
这可能不是你想要的,因为你已经为模型创建了一个类 - 或者你可以明确地将它作为MLP
类的一个静态方法,这样
class MLP():
@staticmethod
def _real_weights(shape):
initializer=tf.truncated_normal_initializer(stddev=0.1)
weights = tf.get_variable('weights', shape, initializer=initializer)
return weights
由于定义的静态方法不能对类实例进行操作,因此可以(并且必须)省略self
引用。
然后,您将创建模板
tf.make_template('_weights', _real_weights)
在第一种情况下
tf.make_template('_weights', MLP._real_weights)
在第二种情况下,显式指定类MLP
作为静态方法的名称范围。 无论哪种方式, _real_weights
函数/方法和_weights
模板现在都只有一个参数,即要创建的变量的形状。