TensorBoard的使用
TensorBoard可以方便地查看graph。
import tensorflow as tf
a = tf.constant(3)
b = tf.constant(2)
x = tf.add(a, b)
with tf.Session() as sess:
writer = tf.summary.FileWriter('./graphs', sess.graph)
sess.run(x)
writer.close()
可以给constant或者variable指定名字。
1.tf.constant的用法
a= tf.constant(value=2, dtype="float32", shape=[2, 2], name="const", verify_shape=False)
verify_shape=True时,检测shape和值是否一致,不一致会报错。
verify_shape=False时,会用最后一个元素将shape补全。
c= tf.constant(value=[2, 3], shape=[5, 3], name="const", verify_shape=False)
print c.eval()
[[2 3 3]
[3 3 3]
[3 3 3]
[3 3 3]
[3 3 3]]
broadcast
a = tf.constant([2, 2])
b = tf.constant([[0, 1], [2, 3]])
x = tf.add(a, b)
# x = a + b will make the same result
with tf.Session() as sess:
print x.eval()
输出的结果为
[[2 3]
[4 5]]
还有一些比较常用的函数tf.zeros(), tf.ones(), tf.zeros_like(), ones_like(), tf.fill()
tf.linspace(start, stop, num, name=None)
tf.range(start, limit=None, delta=1, dtype=None, name=’range’) (不包含limit)
tf.random_normal(shape, mean=0.0, stddev=1.0) normal distribution
tf.truncated_normal(shape, mean=0.0, stddev=1.0) truncated normal distribution
tf.random_shuffle() 沿着第一维度随机
tf.random_crop(value, size, seed=None, name=None) 随机从value中选取size大小的tensor
运算类型
在tensorflow中不要使用Python原始的类型,尽量用tensorflow的数据类型。
const在graph中存储,因此会使graph变大。
2.variable用法
tf.variable()是一个类,可以有很多method;tf.constant是一个op。
variable在使用前必须初始化。可以用init = tf.global_variables_initializer()初始化所有的变量,也可以对部分变量进行初始化:tf.variables_initializer。对单个变量初始化:W.initializer,也可以通过assign op来初始化。
注意:对于op,必须要在session中运行
可以用control dependency 控制依赖来确保变量初始化都已经进行了。
3.placeholder
可以在使用时加载数据,且不同的session可以用不同的数据。
4.注意可视化效果以及避免重复的加载
将op的定义与运行分开
Structuring Your TensorFlow Models
http://danijar.com/structuring-your-tensorflow-models/中讲述了如何使代码结构化。
一个模型封装为一个类,模型需要输入placeholder,提供training, evaluation和inference操作。
将不同的操作放在不同的函数中,提高了代码的可读性与重用性,但是每调用一次函数,graph中会多了相应的op,因此,我们只在第一次调用函数时,保证这些op加到了graph中。
class Model:
def __init__(self, data, target):
self.data = data
self.target = target
self._prediction = None
self._optimize = None
self._error = None
@property
def prediction(self):
if not self._prediction:
data_size = int(self.data.get_shape()[1])
target_size = int(self.target.get_shape()[1])
weight = tf.Variable(tf.truncated_normal([data_size, target_size]))
bias = tf.Variable(tf.constant(0.1, shape=[target_size]))
incoming = tf.matmul(self.data, weight) + bias
self._prediction = tf.nn.softmax(incoming)
return self._prediction
@property
def optimize(self):
if not self._optimize:
cross_entropy = -tf.reduce_sum(self.target, tf.log(self.prediction))
optimizer = tf.train.RMSPropOptimizer(0.03)
self._optimize = optimizer.minimize(cross_entropy)
return self._optimize
@property
def error(self):
if not self._error:
mistakes = tf.not_equal(
tf.argmax(self.target, 1), tf.argmax(self.prediction, 1))
self._error = tf.reduce_mean(tf.cast(mistakes, tf.float32))
return self._error
上面的代码中用到了@property,这是一个装饰器,负责把一个方法变成属性调用。
装饰器的具体使用在
但是仍有一些冗余的代码,因此这里对上述代码进行了修改,用了一个和@property相似的装饰器。
import functools
def lazy_property(function):
attribute = '_cache_' + function.__name__
@property
@functools.wraps(function)
def decorator(self):
if not hasattr(self, attribute):
setattr(self, attribute, function(self))
return getattr(self, attribute)
return decorator
class Model:
def __init__(self, data, target):
self.data = data
self.target = target
self.prediction
self.optimize
self.error
@lazy_property
def prediction(self):
data_size = int(self.data.get_shape()[1])
target_size = int(self.target.get_shape()[1])
weight = tf.Variable(tf.truncated_normal([data_size, target_size]))
bias = tf.Variable(tf.constant(0.1, shape=[target_size]))
incoming = tf.matmul(self.data, weight) + bias
return tf.nn.softmax(incoming)
@lazy_property
def optimize(self):
cross_entropy = -tf.reduce_sum(self.target, tf.log(self.prediction))
optimizer = tf.train.RMSPropOptimizer(0.03)
return optimizer.minimize(cross_entropy)
@lazy_property
def error(self):
mistakes = tf.not_equal(
tf.argmax(self.target, 1), tf.argmax(self.prediction, 1))
return tf.reduce_mean(tf.cast(mistakes, tf.float32))