【tensorflow】模块—基础—计算图、张量、session、constant、variable、placeholder、feed

Tensorflow基础

TensorFlowTM是一一个开放源代码软件库,用于进行高性能数值计算借助其灵活的架构,用户可以轻松地将计算工作部署到多种平台(CPU、GPU、TPU) 和设备(桌面设备、服务器集群、移动设备、边缘设备等).

TensorFIlowTM最初是由Google Brain团队(隶属于Google的AI部门)中的研究人员和工程师开发的,可为机器学习和深度学习提供强力支持.

TensorFlow的概念

TensorFlow = Tensor + F low

  • Tensor张量
    • 数据结构:多维数组
  • Flow流
    • 计算模型:张量之间通过计算而转换的过程

TensorF low是一个通过计算图的形式表述计算的编程系统

  • 每一个计算都是计算图上的一个节点
  • 节点之间的边描述了计算之间的关系

计算图(数据流图)的概念

计算图是- -个有向图,由以下内容构成:

  • 一组节点,每个节点都代表一个操作,是一种运算
  • -组有向边,每条边代表节点之间的关系(数据传递和控制依赖)

TensorF low有两种边:

  • 常规边(实线) :代表数据依赖关系。-个节点的运算输出成为另-个节点的输入,两个节点之间有tensor流动(值传递)
  • 特殊边(虚线) :不携带值,表示两个节点之间的控制相关性。比如,happens-before关系, 源节点必须在目的节点执行前完成执行
#一个简单的计算图
node1=tf.constant(3.0,tf.float32,name='node1')
node2=tf.constant(4.0,tf.float32,name='node2')
node3=tf.add(node1,node2)

print(node3)  #输出一个张量结构
#result:Tensor("Add:0", shape=(), dtype=float32)
#建立对话并显示结果
sess=tf.Session()
print("运行sess.run(node1)的结果",sess.run(node1))
#result:运行sess.run(node1)的结果 3.0

#更新变量并返回计算结果
print("运行sessrun(node3):",sess.run(node3))
#关闭session
sess.close()  #释放内存资源
#result:运行sessrun(node3): 7.0

张量的概念

在TensorFlow中, 所有的数据都通过张量的形式来表示

从功能的角度,张量可以简单理解为多维数组

  • 零阶张量表示标量(scalar) ,也就是一-个数;
  • 一阶张量为向量(vector) ,也就是一维数组;
  • n阶张量可以理解为- -个n维数组;

张量并没有真正保存数字,它保存的是计算过程

张量的属性

Tensor("Add:O", shape=(), dtype=float32)
  • 名字(name)

    'node:soc_ output”: node节点名称,src_ _output来自节点的第几个输出

    "Add:0"表示节点的名字交’Add’, 0 0 0来自节点的第 个输出

  • 形状(shape):可选的

    张量的维度信息,shape=(), 表示是标量

  • 类型(type):可选的

    每一个张量会有一个唯一的类型

    TensorF I ow会对参与运算的所有张量进行类型的检查,发现类型不匹配时会报错

张量的形状

三个术语描述张量的维度:阶(rank)、形状(shape)、、 维数(dimens ion number)

形状 维数 例子
0 () 0-D 4
1 ( D 0 D0 D0) 1-D [ 2 , 3 , 5 ] [2,3,5] [2,3,5]
2 ( D 0 , D 1 D0,D1 D0,D1) 2-D [ [ 2 , 3 ] , [ 3 , 4 ] ] [[2,3],[3,4]] [[2,3],[3,4]]
3 ( D 0 , D 1 , D 2 D0,D1,D2 D0,D1,D2) 3-D [ [ [ 7 ] ] , [ [ 3 ] ] , [ [ 2 ] ] , [ [ 4 ] ] ] [[[7]],[[3]],[[2]],[[4]]] [[[7]],[[3]],[[2]],[[4]]]
N ( D 0 , D 1 , . . . , D n − 1 D0,D1,...,Dn-1 D0,D1,...,Dn−1) n-D 形为 ( D 0 , 1 D 1... , D n − 1 ) (D0,1D1...,Dn-1) (D0,1D1...,Dn−1)的张量
tens1=tf.constant([[[1,2,2],[2,2,3]],
                 [[3,5,6],[5,4,3]],
                  [[7,0,1],[9,1,9]],
                  [[11,12,7],[1,3,14]]],name='tens1') #名字在可视化的时候可以显示
#语句中包含[]{}()括号中间换行的不需要使用多行链接符
print(tens1)
#result:Tensor("tens1:0", shape=(4, 2, 3), dtype=int32)

print(tens1.get_shape())
#result:(4, 2, 3)

获取张量的元素

  • 阶为1的张量等价于向量;
  • 阶为2的张量等价于矩阵,通过t[i, j]获取元素;
  • 阶为3的张量,通过t[i, j, k]获取元素;
tens2 = tf. constant ([[[1, 2], [2, 3]], [[3,4], [5, 6]]])
sess = tf. Session()
print (sess. run(tens2)[1, 1,0])
sess. close()
#result:5

张量的类型

TensorF low支持14种不同的类型

  • 实数tf. float32,tf. float64
  • 整数tf. int8, tf. int16, tf. int32,tf. int64,tf. uint8
  • 布尔tf. bool
  • 复数tf. comp I ex64,tf. comp lex128

默认类型:

  • 不带小数点的数会被默认为int32
  • 带小数点的会被默认为f loat32

注意:TensorFlow会对参与运算的所有张量进行类型的检查,发现类型不匹配时会报错。张量对类型的要求很高,栗子

a = tf. constant([1, 2],name="a")    #整型
b = tf. constant([2.0, 3.0],name="b") #浮点型
result=a+ b

结果报错:

>ValueError: Tensor conversion requested dtype int32 for Tensor with dtype float32: 'Tensor("b:0", shape=(2,), dtype=float32)'

操作

  • 计算图中的节点是操作(Operation)
    • -次加法是一个操作
    • -次乘法也是一个操作
    • 构建一些变量的初始值也是一一个操作
  • 每个运算操作都有属性,它在构建图的时候需要确定下来
  • 操作可以和计算设备绑定,指定操作在某个设备上执行
  • 操作之间存在顺序关系,这些操作之间的依赖就是“边”
  • 如果操作A的输入是操作B执行的结果,那么这个操作A就依赖于操作B
#本例用到了TensorBoard,具体使用后面讲解

tf.reset_default_graph() #清除default graph 和不断增加的节点(对当前对话图进行重置,只能看到下面的)

#定义变量a
a = tf.Variable(1, name="a")
#定义操作b为a+1
b = tf.add(a, 1, name="b")
#定义操作c为*4
c = tf.multiply(b, 4, name="c")
#定义d为c-b
d = tf.subtract(c, b, name="d")

# # Logdir改为自己机器上的合适路径
# logdir='D:/1og'   
# #生成一个写日志的writer,并将当前的TensorFLow计算图写入日志。
# writer = tf. summary. FileWriter(logdir ,tf.get_ default_ _graph())
# writer . close()   

会话Session

会话拥有并管理TensorF low程序运行时的所有资源

当所有计算完成之后需要关闭会话帮助系统回收资源

#定义计算图
tens1 = tf.constant([1,2,3])

#创建一个会话
sess = tf.Session()
#使用这个创建好的会话来得到关心的运算的结果。比如可以调用sess. run(result)
print(sess.run(tens1))

#关闭会话使得本次运行由使用到的资源可以被释放
sess.close()

#result:[1 2 3]

需要明确调用Sess ion. close ()函数来关闭会话并释放资源

当程序因为异常退出时,关闭会话函数可能就不会被执行从而导致资源泄漏

所以可以进行如下操作:

会话典型模式1

#定义计算图
tens1 = tf.constant([1,2,3])

#创建一个会话
sess = tf.Session()
try:
    #使用这个创建好的会话来得到关心的运算的结果。比如可以调用sess. run(result)
    print(sess.run(tens1))
except:
    print("Exception!")
#关闭会话使得本次运行由使用到的资源可以被释放
finally:
    sess.close()

会话典型模式2

node1 = tf.constant(3.0,tf.float32 ,name="node1" )
node2 = tf.constant(4.0, tf.float32, name="node2" )
result = tf.add( node1, node2)

#创建一个会话,并通过Python中的上下文管理器来管理这个会话
with tf.Session() as sess:
    #使用这创建好的会话来计算关心的结果
    print(sess.run(result))
    
#不需要再调用Session.cLose()函数来关闭会话
#当上下文退出时会话关闭和资源释放也自动完成了

指定默认的会话

TensorFlow不会自动生成默认的会话,需要手动指定

当默认的会话被指定之后可以通过tf.Tensor.eval函数来计算一个张量的取值

node1=tf.constant(4.0,tf.float32,name='node1')
node2 = tf.constant(4.0,tf.float32, name= "node2")
result = tf .add(node1, node2)

sess = tf .Session()
with sess.as_default():  #as_default设置为默认会话
    print(result.eval())  #.eval()获取张量结构中的值,是内置函数
 

下面代码也可以完成相同的功能

sess=tf.Session()

#下面两个命令具有相同的功能
print(sess.run(result))
print(result.eval(session=sess))  

交互式环境下设置默认会话

在交互式环境下,Python脚本或者Jupyter编辑器下,通过设置默认会话来获取张量的取值更加方便。

tf. Interact iveSession使用这个函数会自动将生成的会话注册为默认会话

node1=tf.constant(4.0,tf.float32,name='node1')
node2 = tf.constant(4.0,tf.float32, name= "node2")
result = tf .add(node1, node2)

sess = tf. InteractiveSession()   #这也是一个默认会话
print(result.eval())       #默认会话,里面不需要加会话参数了
sess.close()

常量constant

在运行过程中值不会改变的单元,在TensorF low中无须进行初始化操作

创建语句:constant_ name = tf. constant (value)

a = tf.constant(1.0, name='a')
b = tf.constant(2.5, name='b')
c = tf.add(a, b, name='c')

sess = tf .Session( )
c_value = sess.run(c) 
print(c_value)
sess. close( )

变量 variable

变量初始化

在运行过程中值会改变的单元,在TensorF low中须进行初始化操作

创建语句:name_variable = tf. Variable (value,name)#注意V是大写

个别变量初始化:init_op = name_variable. initializer ()

所有变量初始化:init_op = tf.global_variables_initializer()

#变量
node1  =tf.Variable(5.0,tf.float32,name='node1')
node2  = tf.Variable(4.0,tf.float32, name= "node2")
result = tf.add(node1, node2,name='add')

sess = tf .Session( )
#变量初始化
init=tf.global_variables_initializer() 
sess.run(init)      #将前面所定义的变量初始化
 #如果不执行sess.run(init),前面的都是静态图:node1,node2,result,init;系统会报错
 
print(sess.run(result))

注意:

以上代码在Session对话变量后,增加了一个init初始化变量,并调用会话的run命令对参数进行初始化。

变量的赋值

  • 与传统编程语言不同,TensorFlow中的变量定义后,一般无需人工赋值,系统会根据算法模型,训练优化过程中自动调整变量对应的数值
  • 后面在将机器学习模型训练时会更能体会,比如权重We i ght变量w,经过多次迭代,会自动调

epoch = tf.Variable(O,name=' epoch' ,trainable=False)这个变量不参加训练

  • 特殊情况需要人工更新的,可用变量赋值语句

update_ op = tf.assign(variable_ _to_ be_ updated, new_ value)(需要被更新的变量,新值)

栗子:

#通过变量赋值输出1、2、3...10

value = tf .Variable(0, name="value")
one = tf . constant(1)
new_value = tf .add(value, one)
update_value = tf.assign(value, new_value)

init = tf.global_variables_initializer()  #所有变量初始化

with tf .Session() as sess:    #打开Session会话
    sess. run(init)            #运行变量初始化
    for _ in range(10): 
        sess. run(update_value )   #运行 update_value操作(更新value的值)
        print(sess . run(value))   #打印运行结果

作业题

如何通过Tensor Flow的变量赋值计算:1+2+3+…+10=?

#如何计算1+2+3+。。+10
value=tf.Variable(0,name='value')    #动态变量value,设初始值为0
one=tf.constant(1)                   #常量为1
new_value=tf.add(value,one,name='new_value')   #变量+1
update_value=tf.assign(value,new_value)        #将变量+1赋值给value

res=tf.Variable(0,name='res')       #变量,用作结果和,初始值为0
temp_value=tf.add(res,value)        # res+value ,加法操作
update_res_value=tf.assign(res,temp_value)  #将 res+value  重新赋值给res


init=tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)
    for _ in range(10):
        sess.run(update_value)     #变量value更新一次
        sess.run(update_res_value) #和res更新一次
        print(sess.run(res))

1+2+3+4+…+n

# 我还看不明白
import tensorflow.compat.v1 as tf
value = tf.Variable(0,name="value")
sum = tf.Variable(0,name="sum")
one = tf.constant(1)
tf.disable_v2_behavior()
n = tf.placeholder(tf.int32,name='n') 

new_value = tf.add(value,one)
update_value = tf.assign(value,new_value)
new_sum = tf.add(sum,value)
update_sum = tf.assign(sum,new_sum)
    
init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)
    number = int(input("请输入数字: "))
    for i in range(number):
        sess.run(update_value)
        sess.run(update_sum)
    result = sess.run(sum,feed_dict={n:number})
    print(result)

占位符placeholder

  • TensorF low中的Var iable变量类型,在定义时需要初始化,但有些变量比如训练数据,这时候需要用到占位符

  • *tf. placeholder占位符,是TensorF I ow中特有的一种数据结构,类似动态变量,函数的参数、或者C语言或者Python语言中格式化输出时的“%”占位符

  • TensorF low占位符P laceholder,先定义一种数据,其参数为数据的Type和Shape

    占位符Placeho lder的函数接口如下:

    tf.placeholder(dtype, shape=None, name=None)

    x = tf.placeholder(tf.float32, [2,3], name='tx')
    #此代码生成一个2x3的二维数组,矩阵中每个元素的类型都是tf. float32,内部对应的符号名称是tx
    

Feed 提交数据

如果构建了-个包含placeholder操作的计算图,当在session中调用run方法时,placeholder占用的变量必须通过feed_dict 参数传递进去,否则报错

placeholder不需要做变量初始化

a=tf.placeholder(tf.float32,name='a')
b=tf.placeholder(tf.float32, name='b')
c=tf.multiply(a,b,name='c')

init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)    #变量初始化,在这里,没有用到变量,注释掉这行,也不会报错
    #通过feed_dict的参数传值,按字典格式
    result = sess.run(c,feed_dict={a:8.0, b:3.5})
    print(result)

多个操作可以通过一次feed完成执行

a=tf.placeholder(tf.float32,name='a')
b=tf.placeholder(tf.float32, name='b')
c=tf.multiply(a,b,name='c')
d=tf.subtract(a,b,name='d')

init = tf.global_variables_initializer()

with tf.Session() as sess:
    #sess.run(init)
    #通过feed_ dict的参数传值,按字典格式
    result = sess.run([c,d], feed_dict={a:[8.0, 2.0, 3.5], b:[1.5, 2.0, 4.0]})
    #[c,d]将两个操作放入一个列表
    #{a:[8.0, 2.0, 3.5], b:[1.5, 2.0, 4.0]},a & b对应的不再是数值而是向量
    print(result)
    #取结果中的第一个
    print(result[0])
>[array([12.,  4., 14.], dtype=float32), array([ 6.5,  0. , -0.5], dtype=float32)]
>[12.  4. 14.]

一次返回多个值分别赋给多个变量

a=tf.placeholder(tf.float32,name='a')
b=tf.placeholder(tf.float32, name='b')
c=tf.multiply(a,b,name='c')
d=tf.subtract(a,b,name='d')

init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)
    #返回的两个值分别赋值给两个变量
    rc,rd = sess.run([c,d], feed_dict={a:[8.0, 2.0, 3.5], b:[1.5, 2.0, 4.0]})
    print("value of c=",rc,'value of d=',rd)

结果是

>value of c= [12.  4. 14.] value of d= [ 6.5  0.  -0.5]

TensorBoard: TensorFlow可视化工具

  • TensorBoard是TensorF low的可视化工具
  • 通过TensorF low程序运行过程中输出的日志文件可视化TensorFIow程序的运行状态
  • TensorBoard和TensorF low程序跑在不同的进程中

案例:在TensorBoard中查看图的结构

#清除default graph和不断增加的节点
tf.reset_default_graph()
#logdir改为自己机器上的合适路径
logdir='D:/1og'

#定义一个简单的计算图,实现向量加法的操作
input1 = tf .constant([1.0, 2.0,3.0],name="input1")
input2 = tf .Variable(tf.random_uniform([3]), name="input2")
output = tf .add_n([input1, input2],name="add")

#生成一个写日志的writer,并将当前的TensorFlow计算图写入日志。
writer = tf.summary.FileWriter(logdir,tf.get_default_graph())
#(日志的路径,得到图的信息)
writer.close( )

启动TensorBoard

TensorBoard不需要额外安装,在TensorF I ow安装时已自动完成

在Anaconda Prompt中先进入日志存放的目录(非常重要! ! ! )

再运行TensorBoard,并将日志的地址指向程序日志输出的地址

命令: tensorboard --logdir=/path/log

启动服务的端口默认为6006;使用-- port参数可以改编启动服务的端口teng

机器学习相关术语

训练

训练模型表示通过有标签样本来学习(确定) 所有权重和偏差的理想值

在监督式学习中,机器学习算法通过以下方式构建模型:

  • 检查多个样本并尝试找出可最大限度地减少损失的模型
  • 这-过程称为经验风险最小化

损失

  • 损失是对糟糕预测的惩罚:损失是一个数值,表示对于单个样本而言模型预测的准确程度

  • 如果模型的预测完全准确,则损失为零,否则损失会较大

  • 训练模型的目标是从所有样本中找到一-组平均损失“较小”的权重和偏差

定义损失函数

L 1 L_1 L1​损失:基于模型预测的值与标签的实际值之差的绝对值

平方损失:一种常见的损失函数,又称为L2损失

均方误差(MSE)指的是每个样本的平均平方损失

M S E = 1 N ∑ ( x , y ) ∈ D ( y − p r e d i c t i o n ( x ) ) 2 MSE=\frac{1}{N}\sum_{(x,y)\in D}(y-prediction(x))^2 MSE=N1​(x,y)∈D∑​(y−prediction(x))2

模型训练与降低损失

训练模型的迭代方法

推理:执行预测 特征 模型-预测函数 计算损失 标签 计算参数更新

模型训练要点

  • 首先对权重w和偏差b进行初始猜测
  • 然后反复调整这些猜测
  • 直到获得损失可能最低的权重和偏差为止

收敛(训练停止)

在学习优化过程中,机器学习系统将根据所有标签去重新评估所有特征,为损失函数生成一-个新值,而该值又产生新的参数值。

通常,您可以不断迭代,直到总体损失不再变化或至少变化极其缓慢为止。这时候,我们可以说该模型已收敛

梯度下降法

梯度:一个向量(矢量),表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向( 此梯度的方向)变化最快,变化率最大。
【tensorflow】模块—基础—计算图、张量、session、constant、variable、placeholder、feed

学习率

沿着负梯度方向进行下一步探索,前进多少合适?

用梯度乘以一个称为学习速率(有时也称为步长)的标量,以确定下一-个点的位置

例如:如果梯度大小为 2.5 2.5 2.5, 学习速率为 0.01 0. 01 0.01,则梯度下降法算法会选择距离前一;个点 0.025 0.025 0.025的位置作为下一个点

超参数

  • 在机器学习中,超参数是在开始学习过程之.前设置值的参数,而不是通过训练得到的参数数据

  • 通常情况下,需要对超参数进行优化,选择- -组好的超参数,可以提高学习的性能和效果

  • 超参数是编程人员在机器学习算法中用于调整的旋钮

  • 典型超参数:学习率、神经网络的隐含层数量…
    ————————————————————————————————

tensorflow的套路

  1. 变量,常数修改成tensorflow支持运算的格式—张量
  2. 变量初始化、常量初始化
  3. 创建会话Session,使常量、变量、运算操作有执行区域(占据内存)
  4. Session中执行操作
上一篇:码农雷林鹏:php常量


下一篇:类的连接之重写(2)