最简单的Tensorflow实战入门教程 - 第二篇:tensor的定义及基本运算

Tensorflow中的Tensor就是张量的意思,在机器学习及神经网络中,会大量使用到张量运算,因此在tensorflow中,定义一个变量,实际上就是定义一个张量(tensor)

张量(tensor)的概念

因为很多人包括我自己都经常混用甚至混淆几个概念,因此我先简单科普一下“张量/矩阵/向量/标量”几个概念的关系和区别。

  • 0维(0阶)的张量就是标量,也就是一个数字,比如 1,3,100等等
  • 1维(1阶)的张量就是向量,比如[2,4],[3,5,6],[12,0,4,8] 等等。(作者注1)
  • 2维(2阶)的张量就是矩阵,比如2行2列的矩阵[[1,2,3],[4,5,6]],3行3列的矩阵[[1,1,1],[2,2,2],[3,3,3]]等等。(作者注2)
  • 更高维(阶)的张量,就没有特殊的名称了,不过有时候人们也会称更高维的张量为矩阵,比如3维矩阵,4维矩阵。这只不过是一种习惯罢了

了解了上面的内容,我们再来看一下tensorflow中是如何定义张量的,以及有关张量的基本运算。

Tensor的定义及运算

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的常用操作

下面介绍一些定义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.

 

你可能感兴趣的:(TensorFlow,神经网络,机器学习,Python)