人工智能 Tensorflow 深度学习 笔记1 (入门入门入门)

人生苦短,我学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的输出结果。