TensorFlow基础概念和编程(第一讲)

TensorFlow基本概念

A machine learning platform for everyone to solve real problems

TensorFlow = Tensor + Flow;

Tensor  张量:代表的是一种多维数组的数据结构

Flow  流:张量之间通过计算而转换的过程

TensorFlow是一个通过计算图的形式表达计算的编程系统,每一个计算都是计算图上的一个点,节点之间的边描述了计算之间的关系。

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

计算图是一个有向图,由以下内容组成:

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

TensorFlow有两种边:

  • 常规边(实线):代表数据依赖关系。一个节点的运算输出成为另一个节点的输入,两个节点之间有tensor流动(值传递)
  • 特殊边(虚线):不携带值,表示两个节点之间的控制相关性。比如,happens-before关系,源节点必须在目的节点执行前完成执行

计算图实例

import tensorflow as tf
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)

内部会生成一个流图,不会显示,可以利用tensorboard显示。print输出的是“Tensor("Add_1:0", shape=(), dtype=float32)”,证明输出的不是一个确定的数据,而是一个张量的结构。为了能够输出我们想要看到的那种数据类型,想要加上一点代码:

import tensorflow as tf
#name虽然可以不填,但是为了方便,我们一般都直接写上
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)

#创建对话并显示运算结果
sess = tf.Session()
print(sess.run(node1))
print(sess.run(node3))

#关闭session
#如果下面不进行其他操作了,可以关闭session,可以把相关的资源释放出来,关闭之后就不能再调用session了。需要重新创建对话
sess.close()

#分别输出3.0和7.0

Tensor张量

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

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

  • 零阶张量表示标量,也就是一个数
  • 一阶张量为向量,也就是一维数组
  • n阶张量可以理解为一个n维数组
  • 张量并没有真正保存数字,它保存的是计算过程,前面的node打印出来就可以看出来

张量的属性:“Tensor("Add_1:0", shape=(), dtype=float32)”:

  • 这个“Add_1:0”其实是“node:src_output”的具体表现;node表示节点名称,src_output表示来自节点的第几个输出
  • 形状:张量的维度信息,shape=(),表示是标量
  • 类型:每一个张量会有一个唯一的类型
  • TensorFlow会对参与运算的所有张量进行类型的检查,发现类型不匹配时会报错

张量的形状:

形状维数例子

0

()0-D4
1(D0)1-D[2, 3]
2(D1,D1)2-D[[2],[3]]
3(D0,D1,D2)3-D[[[1],[2]],[[3]]]
N(D0,D1....Dn-1)n-Dn阶的张量

小插曲:直接用get_shape()函数获得...,观察的话太麻烦了...

获取张量中的向量

import tensorflow as tf
tens1 = tf.constant([[[1, 2], [3, 4]], [[5, 6], [7, 8]]], name="tens1")
print(tens1)

sess = tf.Session()
print(sess.run(tens1)[1,1,0])
sess.close()

#输出为Tensor("tens1_1:0", shape=(2, 2, 2), dtype=int32)
#7

张量的类型

TensorFlow支持14种不同的类型

实数:tf.float32, tf.float64

整数:tf.int8, tf.int16, tf.int32, tf.int64

布尔:tf.bool

复数:tf.complex64,tf.complex128

默认类型:不带小数点的数会被默认为int32,带小数点的会被默认为float32。

下面这段代码会报错,因为张量在执行的过程中会对类型进行严格的检查,如果不同类型是不能进行操作的

import tensorflow as tf
a = tf.costant([1, 2], name='a')
b = tf.constant([2.0, 3.0], name='b')
result = a + b

operation

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

看代码:(tensorboard的相关知识后面再进行补充)

import tensorflow as tf
#清除default graph和不断增加的节点
tf.reset_default_graph()
#定义变量A
a = tf.Variable(1, tf.int32, name='a')
b = tf.add(a, 1, name='b')
c = tf.multiply(a, 2, name='c')
d = tf.subtract(c, b, name='d')
#logdir改写自己机器上的合适路径
logdir = r'D:\picture'
#生成一个写日志的writer,并在当前的TensorFlow计算图写上日志
writer = tf.summary.FileWriter(logdir, tf.reset_default_graph())
writer.close()

TensorFlow运行模型--会话

会话拥有并管理TensorFlow程序运行时的所有资源,当所有计算完成之后需要关闭会话帮助系统回收资源。

会话的模式除了上面直接创建一个会话之后还有一种模式:

import tensorflow as tf
node1 = tf.constant(3.0, tf.float32, name="node1")
node2 = tf.constant(4.0, tf.float32, name="node2")
node3 = tf.add(node1, node2)

#创建一个会话,并通过Python的上下文管理器来管理这个会话
with tf.Session() as sess:
    #使用这创建的会话来运行关心的结果
    print(sess.run(node3))
    
#不需要再次调用Session.close()函数,在上下文管理器结束的时候系统会默认关闭和释放资源

指定默认的会话

TensorFlow不会自动生成默认的会话,需要手动指定。当默认的会话被指定之后可以通过tf.Tensor.eval()函数来计算一个张量的取值。

import tensorflow as tf
node1 = tf.constant(3.0, tf.float32, name="node1")
node2 = tf.constant(4.0, tf.float32, name="node2")
node3 = tf.add(node1, node2)
sess = tf.Session()
#创建一个会话,设置这个会话作为默认的会话
with sess.as_default():
    #使用这创建的会话来运行关心的结果
    print(node3.eval())

交互环境下设置默认会话

在交互模式下,Python脚本或者jupyter编辑器下,通过设置默认会话来获取张量的取值更加方便。tf.InteractiveSession使用这个函数会自动将生成的会话注册为默认会话

import tensorflow as tf
node1 = tf.constant(3.0, tf.float32, name="node1")
node2 = tf.constant(4.0, tf.float32, name="node2")
node3 = tf.add(node1, node2)

#创建一个会话,设置这个会话作为默认的会话
sess = tf.InteractiveSession()
print(node3.eval())
sess.close()

tensorflow的基本运算

常量和变量

常量在运行过程中不会改变的单元,在TensorFlow中无需进行初始化操作,创建语句:

constant_name = tf.constant(value)

变量是在运行过程中值会改变的单元,在TensorFlow中须进行初始化操作。创建语句:

name_variable = tf.Variable(value.name)

个别变量的初始化:

init_op = name_variable.initializer()

所有变量的初始化:

init_op = tf.global_variables_initializer()

import tensorflow as tf
node1 = tf.Variable(3.0, tf.float32, name="node1")
node2 = tf.Variable(4.0, tf.float32, name="node2")
node3 = tf.add(node1, node2, name='add')

sess = tf.Session()

#变量初始化
init = tf.global_variables_initializer()
#必须要先运行初始化,如果没有这句话会报错,还是没有初始化
sess.run(init)
print(sess.run(node3))

变量的赋值

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

特殊的情况下需要人工赋值的,可用变量赋值语句:

update_op = tf.assign(variable_to_be_updateed, new_value)

#通过变量赋值输出1、2、3、4、5...10
import tensorflow as tf
value = tf.Variable(0, name='value')
one = tf.constant(1, name='one')
new_value = tf.add(value, one)
#将new_value赋值给value
update_value = tf.assign(value, new_value)

init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    #运行十次
    for _ in range(10):
        #run一下updatevalue
        sess.run(update_value)
        print(sess.run(value))

占位符 placeholder

tensorflow中的Variable变量类型,在定义时需要初始化,但有些变量定义时并不知道其数值,只有当真正开始运行程序的时候才由外部输入,比如训练数据,这时候需要占位符。tf.placeholder占位符,是TensorFlow中特有的一种数据结构,类似动态变量,函数的参数,或者C语言中格式化输出时的‘%’占位符。占位符的函数接口如下:

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

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

Feed提交数据和Fetch提取数据

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

import tensorflow as tf
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:
    #下面这句话和上面的初始化语句可以直接注掉,因为placeholder不是Variable,所以可以不应运行初始化
    sess.run(init)
    #通过feed_dict的参数传递,按字典格式
    result = sess.run(c, feed_dict={a:8.0, b:3.5})
    print(result)

多个操作可以通过一次Feed完成执行:看代码

import tensorflow as tf
import numpy as np
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.0], b:[3.5, 2.0, 4.0]})
    rc,rv = sess.run([c,d], feed_dict={a:[8.0, 2.0, 3.0], b:[3.5, 2.0, 4.0]})
    print(result)
    print(np.array(result).shape)
    print(result[0])

TensorBoard可视化初步

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

#在TensorBoard中查看图结构
import tensorflow as tf
#清除default_graph和不断增加的节点
tf.reset_default_graph()

#logdir改成自己机器上的合适路径
logdir = 'D:\picture'

#定义一个简单的计算图,实现向量加法的操作
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

在Anaconda Prompt中先进入日志存放的目录(非常重要!!!),然后返回至上一层,继续敲命令。

命令:tensorboard --logdir=path,Google浏览器,其他浏览器不太好,一般我们画的都是图示,所以要到graph中去找。

单变量线性回归--TensorFlow实战

简单的线性回归:这里就不介绍了...

使用TensorFlow进行算法设计与训练的核心步骤

  • 准备数据
  • 构建模型
  • 训练模型
  • 进行预测

看例子:随机生成一个近似采样随机分布,使得w=2.0, b=1,并加入一个噪声,噪声的最大振幅为0.4;

#在jupyter中,使用matplotlib显示图像需要设置为inline模式,否则不会显示图像
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf

#设置随机数种子,为了得到相同的随机数
np.random.seed(5)

#直接采用等差数列的方式,生成100个点,每个点的取值在-1,1之间
x_data = np.linspace(-1, 1, 100)
#y = 2*x + 1 + 噪声,其中噪声的纬度应与x_data一致
#实参前面加上*就相当于拆包,单个*表示将元组拆成一个个单独的实参
y_data = 2 * x_data + 1.0 + np.random.randn(*x_data.shape) * 0.4
#画出随机生成数据的散点图
plt.scatter(x_data, y_data)
#画出我们想要的线性函数
plt.plot(x_data, 1.0 + 2.0 * x_data, color='red', linewidth=3)

构建模型:

定义训练数据的占位符,x是特征值,y是标签值

x = tf.placeholder("float", name='x')

y = tf.placeholder("float", name='y')

定义模型函数:

def model(x, w, b):

    return tf.multiply(x, w) + b

创建变量:

  • TensorFlow变量的声明函数是tf.Variable
  • tf.Variable的作用是保存和更新参数
  • 变量的初始值可以是随机数、常数、或是通过其他变量的初始值计算得到
#构建变量的初始值
w = tf.Variable(1.0, name="w0")
b = tf.Variable(0.0, name="b0")
#pred是预测值,前向计算
pred = model(x, w, b)
#在jupyter中,使用matplotlib显示图像需要设置为inline模式,否则不会显示图像
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf

#设置随机数种子,为了得到相同的随机数
np.random.seed(5)
#直接采用等差数列的方式,生成100个点,每个点的取值在-1,1之间
x_data = np.linspace(-1, 1, 100)
#y = 2*x + 1 + 噪声,其中噪声的纬度应与x_data一致
#实参前面加上*就相当于拆包,单个*表示将元组拆成一个个单独的实参
y_data = 2 * x_data + 1.0 + np.random.randn(*x_data.shape) * 0.4
#画出随机生成数据的散点图
plt.scatter(x_data, y_data)
#画出我们想要的线性函数
plt.plot(x_data, 1.0 + 2.0 * x_data, color='red', linewidth=3)

x = tf.placeholder("float", name='x')
y = tf.placeholder("float", name='y')
def model(x, w, b):
    return tf.multiply(x, w) + b
   #return tf.multiply(x, w) + b
#构建变量的初始值
w = tf.Variable(1.0, name="w")
b = tf.Variable(0.0, name="b")
#pred是预测值,前向计算
pred = model(x, w, b)
#迭代次数
train_epochs = 10

#学习率
learning_rate = 0.05
#定义损失函数,均方差(MSE)
loss_function = tf.reduce_mean(tf.square(y-pred))
#定义优化器,选用梯度下降优化器
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss_function)
sess = tf.Session()
init = tf.global_variables_initializer()

sess.run(init)
for epoch in range(train_epochs):
    #zip函数会将两个一维数组合并为一个一维数组,这样数组中的每个变量都相当于一个元组
    for xs,ys in zip(x_data, y_data):
        loss = sess.run([optimizer, loss_function], feed_dict={x:xs, y:ys})
        
    b0temp = b.eval(session=sess)
    w0temp = w.eval(session=sess)
    plt.plot(x_data, w0temp * x_data + b0temp)
#进行训练
x_test = 3.2
target = 2 * x_test + 1
print(target)

#通过模型预测的结果
result = sess.run(pred, feed_dict={x:x_test})
print(result)

#最终的输出结果为7.4和7.385617

随机梯度下降法

在梯度下降法中,批量指的是用于单次迭代中计算梯度的样本总数。假定批量是指整个数据集,数据集通常包括很大样本,此外数据集通常包含很多特征。因此一个批量可能是相当巨大。如果是超大批量,则迭代次数可能要花费很多时间。

随机梯度下降法(SGD):每次迭代只使用一个样本,如果进行足够的迭代,SGD也可以发挥作用。“随机”这一术语表示构成各个批量的样本都是随机选择的。

小批量随机梯度下降法(小批量SGD):是介于全批量迭代和SGD之间的折中方案。小批量通常包括10-1000个随机样本。小批量SGD可以减少SGD中的杂乱的样本数量,仍是比较高效的一种方案。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值