Tensorflow中的Tensor就是张量的意思,在机器学习及神经网络中,会大量使用到张量运算,因此在tensorflow中,定义一个变量,实际上就是定义一个张量(tensor)
因为很多人包括我自己都经常混用甚至混淆几个概念,因此我先简单科普一下“张量/矩阵/向量/标量”几个概念的关系和区别。
了解了上面的内容,我们再来看一下tensorflow中是如何定义张量的,以及有关张量的基本运算。
Tensorflow的程序,可以认为是由两个部分组成的,分别是:构建计算图(Building the computational graph)和 运行计算图(Running the computational graph) (作者注3),
我们用一个最简单的例子进行说明,先看几行代码(因为是实战教程,因此我会用代码进行讲解,注释中的内容非常重要,请一定认真阅读哦:):
## 在python中加载tensorflow库
import tensorflow as tf
## 可以把下面这段理解为“构建计算图”部分
x = tf.Variable([[1.0,2.0]]) ## 这里定义了一个行向量X,浮点型
w = tf.Variable([[3.0],[5.0]]) ## 这里定义了一个列向量y,浮点型
y = tf.matmul(x,w) ## 通过tensorflow的matmul方法计算两个向量的乘积
## 下面这段代码可以理解为“运行计算图”部分
init_op = tf.global_variables_initializer() ## 把上面所定义的变量进行初始化,返回op操作句柄
with tf.Session() as sess: ## 定义一个会话,通过这个session来执行图计算
sess.run(init_op) ## 启动运算
print(sess.run(y)) ## 正式运算并打印y的值
TensorFlow用图来表示计算任务,在代码的第一部分,定义了两个向量以及这两个向量的乘积运算,这就是这个代码的计算任务,也就是“计算图”。
各个变量必须要先通过global_variables_initializer()进行初始化(作者注4),并在会话(Session)里执行计算。
sess.run(y),就是根据图中的定义执行y的计算,并返回计算后的张量。也可以通过y.eval()来代替。在tensorflow中,无法直接打印张量的值,必须要通过sess.run()或者tensor.eval()来返回张量的值。直接打印,返回的实际上是这个张量的类型。
我们把上面的程序少做修改,打印一些东西,以便于我们更进一步理解。
## 在python中加载tensorflow库
import tensorflow as tf
## 可以把下面这段理解为“构建计算图”部分
x = tf.Variable([[1.0,2.0]]) ## 这里定义了一个行向量X,浮点型
w = tf.Variable([[3.0],[5.0]]) ## 这里定义了一个列向量y,浮点型
y = tf.matmul(x,w) ## 通过tensorflow的matmul方法计算两个向量的乘积
print("Print y before run:",y)
## print("Print w before run:",sess.run(y)) 在进行变量初始化和启动session之前,这么打印是会报错的
## 下面这段代码可以理解为“运行计算图”部分
init_op = tf.global_variables_initializer() ## 把上面所定义的变量进行初始化,返回op操作句柄
with tf.Session() as sess: ## 定义一个会话,通过这个session来执行图计算
sess.run(init_op) ## 启动运算
print("Print x after run:",x.eval())
print("Print w after run:",sess.run(w))
print("Print y after run:",sess.run(y))
print("Wrong way to print value of y:",y) ## 这种打印方式,你只能得到张量的类型说明
这段代码的运行结果如下:
Print y before run: Tensor("MatMul:0", shape=(1, 1), dtype=float32)
Print x after run: [[1. 2.]]
Print w after run: [[3.]
[5.]]
Print y after run: [[13.]]
Wrong way to print value of y: Tensor("MatMul:0", shape=(1, 1), dtype=float32)
在用一个简单的程序帮助我们理解一下tensorflow的“构建计算图”和“运行计算图”的特性。这个程序实际上就是一个循环,在循环内每次执行一次x = x+1并打印。
import tensorflow as tf
x = tf.Variable(0) ## 定义一个变量x,赋值为0
x = tf.assign_add(x,tf.constant(1)) ## x + 1 再赋值给x, 相当于x = x + 1
with tf.Session() as sess:
sess.run(tf.global_variables_initializer()) ## 直接通过这种方式初始化变量也是可以的
for _ in range(5):
print(sess.run(x)) ## 运行x的赋值计算,并打印
这个程序将输出如下结果:
1
2
3
4
5
假设我们把上面的程序稍微修改一下,会输出什么结果呢?这个作为大家的训练题吧,自己先思考一下,然后运用一下试试:
import tensorflow as tf
x = tf.Variable(0) ## 定义一个变量x,赋值为0
for _ in range(5):
x = tf.assign_add(x, tf.constant(1)) ## x + 1 再赋值给x, 相当于x = x + 1
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print(sess.run(x)) ## 运行x的赋值计算,并打印
相信大家对tensorflow的“构建计算图”和“运行计算图”有了初步的了解。这与我们所熟悉的传统的编程逻辑还是有一定的差别的。理解了它,其实也并不太难。
下面介绍一些定义tensor的常用操作,请直接看代码注释了解其含义。
## 定义一个2行3列,元素全为0的整形张量变量,初始值为:[[0,0,0],[0,0,0]]
tensor1 = tf.zeros([2,3], int32)
## 定义了一个3行3列,元素全为1的整形张量变量,初始值为:[[1,1,1],[1,1,1],[1,1,1]]
tensor2 = tf.ones([3,3], int32)
## 参照tensor2的形状,定义一个元素全为0的张量变量,初始值为:[[0,0,0],[0,0,0],[0,0,0]]
tensor3 = tf.zeros_like(tensor2)
## 参照tensor1的形状,定义一个元素全为0的张量变量,初始值为:[[1,1,1],[1,1,1]]
tensor4 = tf.ones_like(tensor1)
## 定义一个张量变量,以3.0开始,6.0结束,等间隔的4个元素,其初始值为:[3.0, 4.0, 5.0, 6.0]
tensor5 = tf.linespace(3.0, 6.0, 4)
## 定义一个张量变量,其元素大于等于3.0,小于6.0,间隔1.4,其初始值为:[3.0, 4.4, 5.8]
tensor5 = tf.range(3.0, 6.0, 1.4)
## 定义一个其值符合高斯分布(正太分布)随机数的2行3列的张量变量,均值是-1,标准差为2
## 其中均值如果不指定,则默认为0,标准差如果不指定,则默认为1
tensor6 = tf.random_normal([5,3], mean=-1, stddev=2)
## 定义一个常量张量[[1,2],[3,4]]
tensor_c1 = tf.constant([[1,2],[3,4]])
## 定义一个元素值全为3的,2行3列的常量张量 [[3,3,3],[3,3,3]]
tensor_c2 = tf.constant(3,shape=[2,3])
## 随机洗牌操作,经过random_shuffle洗牌之后,将随机打乱1,2,3,4的顺序,再赋值给tensor7
c = tensor_c1 = tf.constant([1,2,3,4])
tensor7 = tf.random_shuffle(tensor_c1)
非常棒!我们已经可以使用tensorflow的框架编写程序了! 后面我们将继续深入,采用tensorflow来实现线性回归和、逻辑回归,及复杂的神经网络模型架构。
我的其他Tensorflow教程,持续补充更新中...
最简单的Tensorflow实战入门教程 - 第一篇:Tensorflow的安装
最简单的Tensorflow实战入门教程 - 第二篇:tensor的定义及基本运算
作者注:
1、很不幸,有时候我们也把向量叫做数组,真是让人晕头转向,关于它们的区别可参看我的另一篇文章:https://blog.csdn.net/kevindree/article/details/88380730
2、其实1行n列的矩阵也叫做行向量,n行1列的矩阵也叫做列向量,因此在tensorflow中定义向量的时候,建议采用矩阵的形式进行定义,而不建议采用秩为1的数组的定义形式。比如定义一个行向量,建议定义为 [[1,2,3,4,5]],不建议定义为[1,2,3,4,5],原因同注1
3、Tensorflow有一种Eager execution模式,在这种模式下运算可以即时执行,与传统的编程思维逻辑更为接近。在刚刚发布的2.0Alpha版本中,Eager execution模式是默认模式,看来这也是tensorflow演进的趋势。我争取在后面的篇章中专门讲解一下Eager execution模式。
4、Tensorflow早期的版本是通过tf.initialize_all_variables()对变量进行初始化的,在新版本中,这个方法一i纪念馆被舍弃并替换成global_variables_initializer()。官方描述:tf.initialize_all_variables(): THIS FUNCTION IS DEPRECATED. It will be removed after 2017-03-02. Instructions for updating: Use tf.global_variables_initializer instead.