人生苦短,我学Python。高中时我利用百度人工智能SDK折腾了一个基于PHP的人脸识别项目,以解决当下老人小孩走丢问题,后因想法和技术各方面都不成熟以及高中党时间的朝七晚九,这个项目以烂尾告终。当时在某当买了本《Python基础教程》,看了几页,算了算了。。
18年五月,我在人工智能全球大赛总决赛现场充当观众,最后中国的深醒公司以深醒机器视觉技术应用夺冠,回家又翻开那本Python书,瞬间头大,合上扔一边,不急不急。
这个假期,在专业老师的推荐下,我总算学上了Python,目的是为进一步学习人工智能Tensorflow神经网络,前几天开始学习Tensorflow,踩了不少坑,故整理了这几天的学习笔记,方便后面回来查看。
”人生苦短,我学Python“这句话的意思是说,python能够提高开发效率,让你短暂人生能够除了工作之外,还有更多的时间休息、娱乐或者其它事情。
-1)Ubuntu 安装
略
官方推荐Ubuntu16.04,在这之前我已经装好了Ubuntu18.04系统,买新不买旧,所以推荐18.04咯。
0) Python 环境搭建
略略
Python最新版本为3.7,但百度告诉我TensorFlow不支持这个版本,用双不用单,这里我用Python3.6,集成开发工具:Pycharm,Jupyter Notebook也是一个比较漂亮和简洁的编辑器。
1) TensorFlow 安装
略略略
官方安装教程:https://tensorflow.google.cn/install
2)Tensorflow入门
Tensorflow是由谷歌大脑(Google Brain)团队于2015年11月开发的第二代开源的机器学习系统,用于进行高性能数值计算,为机器学习和深度学习提供强力支持,并且其灵活的数值计算核心广泛应用于自然语言处理、语音识别、图像处理等多个领域。借助其灵活的架构,用户可以轻松地将计算工作部署到多种平台(CPU、GPU、TPU)和设备(桌面设备、服务器集群、移动设备、边缘设备等)。。
2_1:Tensorflow的核心概念——计算图模型
Q:为什么Tensorflow要使用图模型?图模型有什么优势?
A1:图模型的最大好处是节约系统开销,提高资源的利用率,可以更加高效的进行运算。因为我们在图的执行阶段,只需要运行我们需要的op,这样就大大的提高了资源的利用率;
A2:这种结构有利于我们提取中间某些节点的结果,方便以后利用中间的节点去进行其它运算;
A3:这种结构对分布式运算更加友好,运算的过程可以分配给多个CPU或是GPU同时进行,提高运算效率;
A4:最后,因为图模型把运算分解成了很多个子环节,所以这种结构也让我们的求导变得更加方便。
代码开始
代码 tf_1_1:
图的构建阶段,也称为图的定义阶段。
import tensorflow as tf # 导入 tensorflow 模块,并另起名为 tf
# 定义两个常量op,m1和m2,均为1*2矩阵
m1 = tf.constant([3,5])
m2 = tf.constant([2,4])
result = tf.add(m1,m2) # 矩阵加法
print(result)
#运行结果
Tensor("Add:0", shape=(2,), dtype=int32)
# 结果可知,其并没有输出矩阵相加的结果,而是输出了一个包含三个属性的Tensor。
代码 tf_1_2(接 tf_1_1):
在会话(session)中执行图模型中定义好的运算。
sess = tf.Session() # 通过“tf.session()”启动默认图模型
print(sess.run(result)) # 调用run()方法启动、运行图模型,传入上述参数result,执行矩阵的加法,并打印出相加的结果
sess.close() # 关闭会话
#运行结果
Tensor("Add:0", shape=(2,), dtype=int32) # 代码 tf_1_1
[5 9]
代码 tf_1_3(替 tf_1_2):
(推荐)可以把session写成“with”代码块形式,这样就无需调用close释放资源,而是自动地关闭会话。
with tf.Session() as sess: # 通过“tf.session()”启动默认图模型
res = sess.run(result)
print(res)
代码 tf_1_4:
此外,还可以使用with…device语句来指定GPU或CPU等计算资源分布式执行图的运算过程。
import tensorflow as tf
with tf.Session() as sess:
with tf.device("/gpu:2"):
m1 = tf.constant([3,5])
m2 = tf.constant([2,4])
result = tf.add(m1,m2)
print(result)
# 上述程序中的“tf.device(“/gpu:2”)”是指定了第二个GPU资源来运行下面的op。依次类推,
# 我们还可以通过“/gpu:3”、“/gpu:4”、“/gpu:5”…来指定第N个GPU执行操作
代码 tf_1_5:
Tensorflow中还提供了默认会话的机制,通过调用函数as_default()生成默认会话。
import tensorflow as tf
# 通过调用函数as_default()生成默认会话
m1 = tf.constant([3,5])
m2 = tf.constant([2,4])
result = tf.add(m1,m2)
sess = tf.Session()
with sess.as_default():
# 在启动默认会话后,可以通过调用eval()函数,直接输出变量的内容。
print(result.eval())
代码 tf_1_6:
交互式环境中经常会使用的InteractiveSession()方法,其创建sess对象后,可以直接输出运算结果。
import tensorflow as tf
m1 = tf.constant([3,5])
m2 = tf.constant([2,4])
result = tf.add(m1,m2)
sess = tf.InteractiveSession()
print(result.eval())
2_2:Tensor介绍
Tensor(张量)是Tensorflow中最重要的数据结构,用来表示Tensorflow程序中的所有数据。实际上,我们可以把Tensor理解成N维矩阵(N维数组)。
其中零维张量表示的是一个标量,也就是一个数,比如 [1];
一维张量表示的是一个向量 (vector),也可以看作是一个一维数组,[1, 2, 3];
二维张量表示的是一个矩阵(matrix),[[1, 2, 3],[4, 5, 6],[7, 8, 9]];
同理,N维张量也就是N维矩阵。
代码 tf_1_7:
在计算图模型中,操作间所传递的数据都可以看做是Tensor。
import tensorflow as tf
a = tf.constant([[2.0,3.0]] ,name="a")
b = tf.constant([[1.0],[4.0]] ,name="b")
result = tf.matmul(a,b,name="mul")
print(result)
#运行结果
Tensor("mul:0", shape=(1, 1), dtype=float32)
构建图的运算过程输出的结果是一个Tensor,且其主要由三个属性构成:Name、Shape和Type。
Name代表的是张量的名字,也是张量的唯一标识符,我们可以在每个op上添加name属性来对节点进行命名,Name的值表示的是该张量来自于第几个输出结果(编号从0开始)。
上例中的“mul:0” 说明是第一个结果的输出。
Shape代表的是张量的维度,上例中shape的输出结果(1,1)说明该张量result是一个二维数组,且每个维度数组的长度是1。
最后一个属性表示的是张量的类型,每个张量都会有唯一的类型,需要注意的是要保证参与运算的张量类型相一致,否则会出现类型不匹配的错误。。
2_3:常量、变量及占位符
代码 tf_1_8:
Tensorflow中对常量的初始化,不管是对数值、向量还是对矩阵的初始化,都是通过调用constant()函数实现的。
import tensorflow as tf
a = tf.constant([2.0,3.0],name="a",shape=(2,0),dtype="float64",verify_shape="true")
print(a)
#运行结果
Tensor("a:0", shape=(2, 0), dtype=float64)
# 函数constant有五个参数,分别为value,name,dtype,shape和verify_shape。其中value为必选参数,其它均为可选参数
# Value为常量的具体值,可以是一个数字,一维向量或是多维矩阵。
# Name是常量的名字,用于区别其它常量。
# Dtype是常量的类型,具体类型可参见图2-2。
# Shape是指常量的维度,我们可以自行定义常量的维度。
# verify_shape是验证shape是否正确,默认值为关闭状态(False)。也就是说当该参数true状态时,就会检测我们所写的参数shape是否与value的真实shape一致,若不一致就会报TypeError错误。
Tensorflow还提供了一些常见常量的初始化,如:tf.zeros、tf.ones、tf.fill、tf.linspace、tf.range等,均可以快速初始化一些常量。
代码 tf_1_9:
想要快速初始化N维全0的矩阵,可以利用tf.zeros进行初始化.
import tensorflow as tf
a = tf.zeros([2,2],tf.float32)
b = tf.zeros_like(a,optimize=True)
with tf.Session() as sess:
print(sess.run(a))
print(sess.run(b))
#运行结果
[[0. 0.]
[0. 0.]]
[[0. 0.]
[0. 0.]]
代码 tf_1_10:
Tensorflow还可以生成一些随机的张量,方便快速初始化一些随机值。如:tf.random_normal()、tf.truncated_normal()、tf.random_uniform()、tf.random_shuffle()等。
以tf.random_normal()为例,来看一下随机张量的具体用法:
import tensorflow as tf
random_num = tf.random_normal([2,3], mean=-1, stddev=4,
dtype=tf.float32,seed=None,name='rnum')
with tf.Session() as sess:
print(sess.run(random_num))
#运行结果
[[-1.7708042 0.6734474 -1.8801564]
[ 4.3843718 -8.059027 4.9946556]]
# 随机张量random_normal()有shape、mean、stddev、dtype、seed、name六个属性。
# shape是指张量的形状,如上述程序是生成一个2行3列的tensor;
# mean是指正态分布的均值;
# stddev是指正太分布的标准差;
# dtype是指生成tensor的数据类型;
# seed是分发创建的一个随机种子;
# 而name是给生成的随机张量命名。
代码 tf_1_11:
变量variable()的作用是保存和更新参数。执行图模型时,一定要对变量进行初始化,经过初始化后的变量才能拿来使用。
import tensorflow as tf
# 变量的使用包括创建、初始化、保存、加载等操作。
A = tf.Variable(3, name="number")
B = tf.Variable([1, 3], name="vector")
C = tf.Variable([[0, 1], [2,3]], name="matrix")
D = tf.Variable(tf.zeros([100]), name="zero")
E = tf.Variable(tf.random_normal([2, 3], mean=1, stddev=2, dtype=tf.float32))
# 可以把函数variable()理解为构造函数,构造函数的使用需要初始值,而这个初始值是一个任何形状、类型的Tensor。
# 变量初始化的三种方式:
# 初始化全部变量:
init = tf.global_variable_initializer()
with tf.Session() as sess:
sess.run(init)
# 初始化变量的子集:
init_subset = tf.variable_initializer([b, c], name="init_subset")
with tf.Session() as sess:
sess.run(init_subset)
# 初始化单个变量:
init_var = tf.Variable(tf.zeros([2, 5]))
with tf.Session() as sess:
sess.run(init_var.initializer)
# global_variables_initializer()方法是不管全局有多少个变量,全部进行初始化,是最简单也是最常用的一种方式;
# variables_initializer()是初始化变量的子集,相比于全部初始化化的方式更加节约内存;
# Variable()是初始化单个变量,函数的参数便是要初始化的变量内容。
代码 tf_1_12:
变量的保存是通过tf.train.Saver()方法创建一个Saver管理器,来保存计算图模型中的所有变量。
import tensorflow as tf
var1 = tf.Variable([1, 3], name="v1")
var2 = tf.Variable([2, 4], name="v2")
# 对全部变量进行初始化
init = tf.initialize_all_variables()
# 调用Sever()存储器方法
saver = tf.train.Saver()
# 执行图模型
with tf.Session() as sess:
sess.run(init)
# 设置存储路径
save_path = saver.save(sess,"tf_1_12_test/save.ckpt")
# 我们的存储文件save.ckpt是一个二进制文件,Saver存储器提供了向该二进制文件保存变量和恢复变量的方法。
# 保存变量的方法就是程序中的save()方法,保存的内容是从变量名到tensor值的映射关系。
代码 tf_1_13:
用和保存变量相同的Saver对象来恢复变量,不需要事先对变量进行初始化。
import tensorflow as tf
var1 = tf.Variable([0, 0], name="v1")
var2 = tf.Variable([0, 0], name="v2")
saver = tf.train.Saver()
module_file = tf.train.latest_checkpoint('tf_1_12_test/')
with tf.Session() as sess:
saver.restore(sess, module_file)
print("Model restored.")
# 变量的获取是通过restore()方法,该方法有两个参数,分别是session和获取变量文件的位置。
# 我们还可以通过latest_checkpoint()方法,获取到该目录下最近一次保存的模型。
代码 tf_1_14:
placeholder是一个数据初始化的容器,它与变量最大的不同在于placeholder定义的是一个模板,这样我们就可以session运行阶段,利用feed_dict的字典结构给placeholder填充具体的内容,而无需每次都提前定义好变量的值。
import tensorflow as tf
a = tf.placeholder(tf.float32,shape=[2],name=None)
b = tf.constant([6,4],tf.float32)
c = tf.add(a, b)
with tf.Session() as sess:
print(sess.run(c,feed_dict={a:[10,10]}))
# Placeholder()方法有dtype,shape和name三个参数构成。
# dtype是必填参数,代表传入value的数据类型;
# shape是选填参数,代表传入value的维度;
# name也是选填参数,代表传入value的名字。
# 我们可以把这三个参数看作为形参,在使用时传入具体的常量值。
# placeholder不同于常量的地方,它不可以直接拿来使用,而是需要用户传递常数值。
代码 tf_1_15:
Fetch的含义是指可以在一个会话中同时运行多个op, 这就方便我们在实际的建模过程中,输出一些中间的op,取回多个tensor。
import tensorflow as tf
a = tf.constant(5)
b = tf.constant(6)
c = tf.constant(4)
add = tf.add(b, c)
mul = tf.multiply(a, add)
with tf.Session() as sess:
result = sess.run([mul, add])
print(result)
# 利用session的run()方法同时取回多个tensor值,方便我们查看运行过程中每一步op的输出结果。