TensorFlow™ 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。它灵活的架构让你可以在多种平台上展开计算,例如台式计算机中的一个或多个CPU(或GPU),服务器,移动设备等等。
TensorFlow 最初由Google大脑小组(隶属于Google机器智能研究机构)的研究员和工程师们开发出来,用于机器学习和深度神经网络方面的研究,但这个系统的通用性使其也可广泛用于其他计算领域。
当前TensorFlow最新的开源版本是 r0.9 。
数据流图用“结点”(nodes)和“线”(edges)的有向图来描述数学计算。“节点” 一般用来表示施加的数学操作,但也可以表示数据输入(feed in)的起点/输出(push out)的终点,或者是读取/写入持久变量(persistent variable)的终点。“线”表示“节点”之间的输入/输出关系。这些数据“线”可以输运“size可动态调整”的多维数据数组,即“张量”(tensor)。张量从图中流过的直观图像是这个工具取名为“Tensorflow”的原因。一旦输入端的所有张量准备好,节点将被分配到各种计算设备完成异步并行地执行运算。
TensorFlow 不是一个严格的“神经网络”库。只要可以将计算表示为一个数据流图,就可以使用Tensorflow来构建图,描写驱动计算的内部循环。Tensorflow提供了有用的工具来帮助你组装“子图”(常用于神经网络),当然用户也可以自己在Tensorflow基础上写自己的“上层库”。定义顺手好用的新复合操作和写一个python函数一样容易,而且也不用担心性能损耗。当然万一发现找不到想要的底层数据操作,也可以自己写一点c++代码来丰富底层的操作。
Tensorflow 可以在CPU和GPU上运行,比如说可以运行在台式机、服务器、手机移动设备等等。想要在没有特殊硬件的前提下,在你的笔记本上跑一下机器学习的新想法?Tensorflow也可以办到。准备将你的训练模型在多个CPU上规模化运算,又不想修改代码?Tensorflow也可以办到。想要将你的训练好的模型作为产品的一部分用到手机app里?Tensorflow可以办到这点。你改变主意了,想要将你的模型作为云端服务运行在自己的服务器上,或者运行在Docker容器里?Tensorfow也能办到。
过去如果要将科研中的机器学习想法用到产品中,需要大量的代码重写工作。那样的日子一去不复返了!在Google,科学家用Tensorflow尝试新的算法,产品团队则用Tensorflow来训练和使用计算模型,并直接提供给在线用户。使用Tensorflow可以让应用型研究者将想法迅速运用到产品中,也可以让学术性研究者更直接地彼此分享代码,从而提高科研产出率。
基于梯度的机器学习算法会受益于Tensorflow自动求微分的能力。作为Tensorflow用户,你只需要定义预测模型的结构,将这个结构和目标函数(objective function)结合在一起,并添加数据,Tensorflow将自动为你计算相关的微分导数。计算某个变量相对于其他变量的导数仅仅是通过扩展你的图来完成的,所以你能一直清楚看到究竟在发生什么。
Tensorflow 有一个合理的c++使用界面,也有一个易用的python使用界面来构建和执行你的graphs。你可以直接写python/c++程序,也可以用交互式的ipython界面来用Tensorflow尝试些想法,它可以帮你将笔记、代码、可视化等有条理地归置好。当然这仅仅是个起点——Tensorflow鼓励创造自己最喜欢的语言界面,比如Go,Java,Lua,Javascript,或者是R。
目前开源的版本暂时只看到对于python/C++的支持,并且python的API比C++的还是要更成熟易用。社区已经有针对Java和Ruby的支持。
比如说你有一个具有32个CPU内核、4个GPU显卡的工作站,想要将你工作站的计算潜能全发挥出来?由于Tensorflow 给予了线程、队列、异步操作等以最佳的支持,Tensorflow 让你可以将你手边硬件的计算潜能全部发挥出来。你可以自由地将Tensorflow图中的计算元素分配到不同设备上,Tensorflow可以帮你管理好这些不同副本。
TensorFlow支持二进制包和源码包等多种安装方式,支持在Linux、Mac OS X、Ubuntu等多个平台上进行安装,并且可以运行在docker之上,官网上有比较详细的安装文档。
TensorFlow最简单的安装方式是通过pip进行安装,如果条件不允许(例如无外网的条件下),需要通过源码进行安装,TensorFlow的源码编译依赖Python 2.7版本,以及Bazel进行编译。
整体来说TensorFlow的安装过程还是比较简单的。
Devices
一块可以用来运算并且拥有自己的地址空间的硬件,比如GPU和CPU。
eval
Tensor 的一个方法,返回 Tensor 的值。触发任意一个图计算都需要计算出这个值。只能在一个已经启动的会话的图中才能调用该 Tensor 值。
Feed
TensorFlow 的一个概念:把一个 Tensor 直接连接到一个会话图表中的任意节点。feed 不是在构建图(graph)的时候创建,而是在触发图的执行操作时去申请。一个 feed 临时替代一个带有 Tensor 值的节点。把feed数据作为run( )方法和eval( )方法的参数来初始化运算。方法运行结束后,替换的 feed 就会消失,而最初的节点定义仍然还在。可以通过tf.placeholder( )把特定的节点指定为 feed 节点来创建它们。
Fetch
TensorFlow中的一个概念:为了取回运算操作的输出结果。取回的申请发生在触发执行图操作的时候,而不是发生在建立图的时候。如果要取回一个或多个节点(node)的 Tensor 值,可以通过在 Session 对象上调用run( )方法并将待取回节点(node)的列表作为参数来执行图表(graph)。
Graph
把运算任务描述成一个直接的无环图形(DAG),图表中的节点(node)代表必须要实现的一些操作。图中的边代表数据或者可控的依赖。GratheDef 是系统中描述一个图表的协议(api),它由一个 NodeDefs 集合组成。一个GraphDef可以转化成一个更容易操作的图表对象。
IndexedSlices
在 Python API 中,TensorFlow 仅仅在第一维上对 Tensor 有所体现。如果一个 Tensor 有k维,那么一个 IndexedSlices 实例在逻辑上代表一个沿着这个 Tensor 第一维的(k-1)维切片的集合。切片的索引被连续储存在一个单独的一维向量中,而对应的切片则被拼接成一个单独的k维 Tensor。如果 sparsity 不是受限于第一维空间,请用 SparseTensor。
Node
图中的一个元素。 把启动一个特定操作的方式称为特定运算图表的一个节点,包括任何用来配置这个操作的属性的值。对于那些多形态的操作,这些属性包括能完全决定这个节点(Node)签名的充分信息。
operation
在 TensorFlow 的运行时中,它是一种类似 add 或 matmul 或 concat的运算。可以用how to add an op中的方法来向运行时添加新的操作。
在 Python 的API中,它是图中的一个节点。在tf.Operation类中列举出了这些操作。一个操作(Operation)的 type 属性决定这个节点(node)的操作类型,比如add和matmul。
Run
在一个运行的图中执行某种操作的行为。要求图必须运行在会话中。
在 Python 的 API 中,它是 Session 类的一个方法tf.Session.run。可以通过 Tensors 来订阅或获取run( )操作。
在C++的API中,它是tensorflow::Session类 的一个方法。
Session
启动图的第一步是创建一个 Session 对象。Session 提供在图中执行操作的一些方法。
在 Python API中,使用tf.Session。
在 C++ 的API中,tensorflow::Session是用来创建一个图并运行操作的类。
Shape
Tensor 的维度和它们的大小。
在一个已经启动的图中,它表示流动在节点(node)之间的 Tensor 的属性。一些操作对 shape 有比较强的要求,如果没有 Shape 属性则会报告错误。
在 Python API中,用创建图的 API 来说明 Tensor 的 Shape 属性。Tensor 的Shape 属性要么只有部分已知,要么全部未知。详见tf.TensroShape
在C++中,Shape 类用来表示 Tensor 的维度。tensorflow::TensorShape。
SparseTensor
在 Python API 中,它用来表示在 TensorFlow 中稀疏散落在任意地方的 Tensor 。SparseTensor 以字典-值格式来储存那些沿着索引的非空值。换言之,m个非空值,就包含一个长度为m的值向量和一个由m列索引(indices)组成的矩阵。为了提升效率,SparseTensor 需要将 indice(索引)按维度的增加来按序存储,比如行主序。如果稀疏值仅沿着第一维度,就用 IndexedSlices。
Tensor
Tensor是一种特定的多维数组。比如,一个浮点型的四维数组表示一小批由batch,height,width,channel组成的图片。
在一个运行的图(graph)中,它是一种流动在节点(node)之间的数据。 在 Python 中,Tensor 类表示添加到图的操作中的输入和输出,见tf.Tensor,这样的类不持有数据。
在C++中,Tensor是方法Session::Run( )的返回值,见tensorflow::Tensor,这样的 Tensor 持有数据。
TensorFlow 和 Numpy在描述N维数据方面是非常相似的,不同的是TensorFlow除了能定义N维数组,还能创建N维数组的方程,并能自动计算求导,做更多的事情。
numpy
tensorflow
对比两者之间的区别:
可见在tensorflow中许多基础的N-array操作都是类似的,这让很多接触过numpy进行数据分析的人员都能很自然的上手tensorflow。
以下借助TensorFlow我实现了一个简单的单变量线性回归程序:
Python
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
# 定义输入数据
X_data = np.linspace(-1, 1, 100)
noise = np.random.normal(0, 0.5, 100)
y_data = 5 * X_data + noise
# Plot 输入数据
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.scatter(X_data, y_data)
plt.ion()
plt.show()
# 定义数据大小
n_samples = 100
# 转换成向量
X_data = np.reshape(X_data, (n_samples, 1))
y_data = np.reshape(y_data, (n_samples, 1))
# 定义占位符
X = tf.placeholder(tf.float32, shape=(None, 1))
y = tf.placeholder(tf.float32, shape=(None, 1))
# 定义学习的变量
W = tf.get_variable("weight", (1, 1),
initializer=tf.random_normal_initializer())
b = tf.get_variable("bais", (1,),
initializer=tf.constant_initializer(0.0))
y_pred = tf.matmul(X, W) + b
loss = tf.reduce_mean(tf.reduce_sum(tf.square(y - y_pred)))
# 梯度下降
# 定义优化函数
opt = tf.train.GradientDescentOptimizer(0.001)
operation = opt.minimize(loss)
with tf.Session() as sess:
# 初始化变量
sess.run(tf.initialize_all_variables())
lines = None
for i in range(50):
_, loss_val = sess.run([operation, loss],
feed_dict={X: X_data, y: y_data})
if i % 5 == 0:
if lines:
ax.lines.remove(lines[0])
prediction_value = sess.run(y_pred, feed_dict={X: X_data})
lines = ax.plot(X_data, prediction_value, 'r-', lw=5)
plt.pause(0.1)
plt.pause(5)
通过简单的定义目标函数和选择优化算法,就可以开始训练我的模型了。
结果我并没有亲手实现梯度下降算法,就达到了训练样本的目的。开发人员可以只关注模型本身,剩下的事情 TensorFlow 帮你搞定的妥妥的!这只是小试牛刀,TensorFlow 可以训练更加复杂的模型:循环神经网络,卷积神经网络,递归神经网络等等。
TensorFlow 提供了一个内置的可视化工具叫做 TensorBoard。有了 TensorBoard 可以更方便 TensorFlow 程序的理解、调试与优化。你可以用 TensorBoard 来展现你的 TensorFlow 图像,绘制图像生成的定量指标图以及附加数据。
通过简单的改写,我就可以在上面的例子中使用TensorBoard了:
Python
import tensorflow as tf
import numpy as np
# 定义输入数据
X_data = np.linspace(-1, 1, 100)
noise = np.random.normal(0, 0.5, 100)
y_data = 5 * X_data + noise
# 定义数据大小
n_samples = 100
# 转换成向量
X_data = np.reshape(X_data, (n_samples, 1))
y_data = np.reshape(y_data, (n_samples, 1))
with tf.name_scope("input"):
# 定义占位符
X = tf.placeholder(tf.float32, shape=(None, 1))
y = tf.placeholder(tf.float32, shape=(None, 1))
# 定义学习的变量
with tf.name_scope("linear-regression"):
with tf.name_scope("Weight"):
W = tf.get_variable("weight", (1, 1),
initializer=tf.random_normal_initializer())
with tf.name_scope("bais"):
b = tf.get_variable("bais", (1,),
initializer=tf.constant_initializer(0.0))
with tf.name_scope("prediction"):
y_pred = tf.add(tf.matmul(X, W), b)
with tf.name_scope("loss"):
loss = tf.reduce_mean(tf.reduce_sum(tf.square(y - y_pred)))
tf.scalar_summary("loss", loss)
# 梯度下降
# 定义优化函数
with tf.name_scope("train"):
opt = tf.train.GradientDescentOptimizer(0.001)
operation = opt.minimize(loss)
with tf.Session() as sess:
merged = tf.merge_all_summaries()
writer = tf.train.SummaryWriter("logs/", sess.graph)
# 初始化变量
sess.run(tf.initialize_all_variables())
for i in range(50):
_, loss_val = sess.run([operation, loss],
feed_dict={X: X_data, y: y_data})
if i % 5 == 0:
result = sess.run(merged, feed_dict={X: X_data, y: y_data})
writer.add_summary(result, i)
再次执行上面的代码,会在logs/子目录下生成一个日志文件。通过在打开 TensorBoard 的时候指定日志目录加载这个日志文件,我们就可以通过浏览器访问 TensorBoard 了。
tensorboard --logdir=logs
通过 TensorBoard 我们可查看定义的模型:
同时我们也可以通过 TensorBoard 观察我们定义的损失量loss有没有按照预期的收敛,收敛的过程如何:
TensorBoard 是一个很好用的工具,官网文档有关于 TensorBoard 更为详尽的描述。
TensorFlow 作为一款机器学习的库,提供了类似 Numpy 数据结构,支持python,C++等多种语言,可以在cpu或者gpu上运行,安装简单,上手容易,社区活跃,文档目前还不够丰富,好在通俗易懂,但是目前的示例还比较少(特别是python以外的示例)。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。