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-D | 4 |
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-D | n阶的张量 |
小插曲:直接用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中的杂乱的样本数量,仍是比较高效的一种方案。
还没有评论,来说两句吧...