本文记录使用tensorflow API过程中的遇到的一些坑
[size=large][color=blue]0、change log[/color][/size]
API的改变还是要关注的,比如0.11版本增加了对hadoop的支持:
[url]https://github.com/tensorflow/tensorflow/blob/master/RELEASE.md[/url]
[size=large][color=blue]1、调试[/color][/size]
print大法好:
tf.Print 可以在计算一个变量的同时,指定打印一组变量,参见:[url]https://www.tensorflow.org/versions/master/api_docs/python/control_flow_ops.html#Print[/url]
[b]tdb,tf的可视化工具[/b][url]https://github.com/ericjang/tdb[/url]
0.12版更改了summary的处理方式,示例参见:[url]http://stackoverflow.com/questions/41027247/tensorflow-0-12-0rc-tf-summary-scalar-error-using-placeholders[/url]
打开tensorboard:
关闭tensorboard 服务
[size=large][color=blue]2、内存泄露[/color][/size]
每次采用tf.assign 甚至 tf.train.Saver(), 都会在当前graph中新增一个operator, 如果在循环中持续使用,不仅仅会造成内存泄露,更会拖慢速度!!!(我的某个训练从170ms逐渐变为1000ms+!!)
调试方法,增加完所有操作后采用[b]sess.graph.finalize()[/b]来使得整个graph变为只读的
具体参见:
[list]
[*][url]https://github.com/tensorflow/tensorflow/issues/4151[/url]
[*][url]http://stackoverflow.com/documentation/tensorflow/3883/how-to-debug-a-memory-leak-in-tensorflow/13426/use-graph-finalize-to-catch-nodes-being-added-to-the-graph[/url]
[/list]
[color=red]注意:[/color]tf.train.Saver() 也算是往graph中添加node, 所以也必须放在finilize前
但是,,tf.train.Saver() 只会存储 在该Saver声明时已经存在的变量!!!
[size=large][color=blue]3、条件语句[/color][/size]
由于dropout, batchnorm等函数在训练、预测时的依赖不同,需要使用
tf.case 选择不同的执行路径,
tf.cond 相当于if
tf.case 相当于switch
示例及存在的问题参见:
[list]
[*][url]https://github.com/tensorflow/tensorflow/issues/4432[/url]
[*][url]http://stackoverflow.com/questions/37063952/confused-by-the-behavior-of-tf-cond/37064128#37064128[/url]
[/list]
[size=large][color=blue]4、稀疏矩阵和tf.nn.embedding_lookup_sparse[/color][/size]
这两个概念请单独理解,抛开tensorflow,如果你要表示一个稀疏矩阵要怎么表示?
是不是每个非零值有一个坐标和一个值,比如 (0,0):1.0
那么(0,0)就对应index中的一项, 1.0就对应value中的一项,
此外,这个矩阵还要有个大小,就对应shape项
再来说tf.nn.embedding_lookup_sparse,这个时候,矩阵的第一维已经是batch中样本的下标了,而第二维则是该特征对应的下标,,也就是(样本下标,特征下标)
需要注意的是,tensorflow中不允许样本没有也就是说batch_size为2的话,矩阵中至少要有两项:(0,x):1, (1,x):0 (实在没有就自己填个0吧)
[color=red]注意:[/color]tf.nn.embedding_lookup_sparse的结果并不是某一项,而是需要通过combiner对每个样本的所有特征进行聚合,比如样本0有两个非零特征:
(0,0):1, (0,3):2, combiner='sum',则对应的结果为 1+2=3
但是,当前的combiner只支持"mean", "sqrtn" and "sum", 如果需要max,min,可以考虑通过tf.nn.embedding_lookup + tf.segment_max的方式实现(未验证)
tf.segment_max:[url]https://www.tensorflow.org/versions/master/api_docs/python/math_ops.html#segment_max[/url]
[size=large][color=blue]5、共享变量,多GPU[/color][/size]
共享变量通过变量名实现,每个变量具有唯一的变量名,
变量名通过 tf.variable_scope控制,参见:
[list]
[*][url]https://www.tensorflow.org/versions/master/how_tos/variable_scope/index.html#sharing-variables[/url]
[*][url]http://stackoverflow.com/questions/35919020/whats-the-difference-of-name-scope-and-a-variable-scope-in-tensorflow[/url]
[/list]
多GPU(数据并行):
tf将变量-模型分别存储,在每个GPU上生成一个模型, 模型对应的参数(变量)存储在内存上, 每个GPU分别对半个mini-batch数据计算梯度(假设有两个GPU),再在CPU上完成梯度的平均及更新。
写起来挺别扭的,操作需要自己指定设备。。。不能自动运用多GPU,具体的例子参见:
[url]https://www.tensorflow.org/versions/master/tutorials/deep_cnn/index.html#training-a-model-using-multiple-gpu-cards[/url]
[size=large][color=blue]0、change log[/color][/size]
API的改变还是要关注的,比如0.11版本增加了对hadoop的支持:
[url]https://github.com/tensorflow/tensorflow/blob/master/RELEASE.md[/url]
[size=large][color=blue]1、调试[/color][/size]
print大法好:
tf.Print 可以在计算一个变量的同时,指定打印一组变量,参见:[url]https://www.tensorflow.org/versions/master/api_docs/python/control_flow_ops.html#Print[/url]
[b]tdb,tf的可视化工具[/b][url]https://github.com/ericjang/tdb[/url]
0.12版更改了summary的处理方式,示例参见:[url]http://stackoverflow.com/questions/41027247/tensorflow-0-12-0rc-tf-summary-scalar-error-using-placeholders[/url]
打开tensorboard:
sudo tensorboard --logdir=./tensorboard/ & # use & to non-block the shell
sleep 2
gnome-www-browser http://127.0.0.1:6006/
关闭tensorboard 服务
pgrep tensorboard |xargs sudo kill -9
[size=large][color=blue]2、内存泄露[/color][/size]
每次采用tf.assign 甚至 tf.train.Saver(), 都会在当前graph中新增一个operator, 如果在循环中持续使用,不仅仅会造成内存泄露,更会拖慢速度!!!(我的某个训练从170ms逐渐变为1000ms+!!)
调试方法,增加完所有操作后采用[b]sess.graph.finalize()[/b]来使得整个graph变为只读的
具体参见:
[list]
[*][url]https://github.com/tensorflow/tensorflow/issues/4151[/url]
[*][url]http://stackoverflow.com/documentation/tensorflow/3883/how-to-debug-a-memory-leak-in-tensorflow/13426/use-graph-finalize-to-catch-nodes-being-added-to-the-graph[/url]
[/list]
[color=red]注意:[/color]tf.train.Saver() 也算是往graph中添加node, 所以也必须放在finilize前
但是,,tf.train.Saver() 只会存储 在该Saver声明时已经存在的变量!!!
[size=large][color=blue]3、条件语句[/color][/size]
由于dropout, batchnorm等函数在训练、预测时的依赖不同,需要使用
tf.case 选择不同的执行路径,
tf.cond 相当于if
tf.case 相当于switch
示例及存在的问题参见:
[list]
[*][url]https://github.com/tensorflow/tensorflow/issues/4432[/url]
[*][url]http://stackoverflow.com/questions/37063952/confused-by-the-behavior-of-tf-cond/37064128#37064128[/url]
[/list]
[size=large][color=blue]4、稀疏矩阵和tf.nn.embedding_lookup_sparse[/color][/size]
这两个概念请单独理解,抛开tensorflow,如果你要表示一个稀疏矩阵要怎么表示?
是不是每个非零值有一个坐标和一个值,比如 (0,0):1.0
那么(0,0)就对应index中的一项, 1.0就对应value中的一项,
此外,这个矩阵还要有个大小,就对应shape项
再来说tf.nn.embedding_lookup_sparse,这个时候,矩阵的第一维已经是batch中样本的下标了,而第二维则是该特征对应的下标,,也就是(样本下标,特征下标)
需要注意的是,tensorflow中不允许样本没有也就是说batch_size为2的话,矩阵中至少要有两项:(0,x):1, (1,x):0 (实在没有就自己填个0吧)
[color=red]注意:[/color]tf.nn.embedding_lookup_sparse的结果并不是某一项,而是需要通过combiner对每个样本的所有特征进行聚合,比如样本0有两个非零特征:
(0,0):1, (0,3):2, combiner='sum',则对应的结果为 1+2=3
但是,当前的combiner只支持"mean", "sqrtn" and "sum", 如果需要max,min,可以考虑通过tf.nn.embedding_lookup + tf.segment_max的方式实现(未验证)
tf.segment_max:[url]https://www.tensorflow.org/versions/master/api_docs/python/math_ops.html#segment_max[/url]
[size=large][color=blue]5、共享变量,多GPU[/color][/size]
共享变量通过变量名实现,每个变量具有唯一的变量名,
变量名通过 tf.variable_scope控制,参见:
[list]
[*][url]https://www.tensorflow.org/versions/master/how_tos/variable_scope/index.html#sharing-variables[/url]
[*][url]http://stackoverflow.com/questions/35919020/whats-the-difference-of-name-scope-and-a-variable-scope-in-tensorflow[/url]
[/list]
多GPU(数据并行):
tf将变量-模型分别存储,在每个GPU上生成一个模型, 模型对应的参数(变量)存储在内存上, 每个GPU分别对半个mini-batch数据计算梯度(假设有两个GPU),再在CPU上完成梯度的平均及更新。
写起来挺别扭的,操作需要自己指定设备。。。不能自动运用多GPU,具体的例子参见:
[url]https://www.tensorflow.org/versions/master/tutorials/deep_cnn/index.html#training-a-model-using-multiple-gpu-cards[/url]