【Python与机器学习 7-4】TensorFlow框架及使用 - Go语言中文社区

【Python与机器学习 7-4】TensorFlow框架及使用


TensorFlow安装

普通版本

pip install tensorflow

GPU版本

pip install tensorflow-gpu
其它步骤参考https://www.tensorflow.org/install

TensorFlow中的三种模式

首先我们看一下TensorFlow,把它分开就是Tensor和Flow。
这个Tensor为多维或高维矩阵,TensorFlow的框架里数据都是以tensor的形式存储的。Flow 数据根据制定的计算图进行流转。

计算模式—计算图(Computation Graph)

什么是计算图

TensorFlow是一个通过计算图的形式表示计算的编程系统,TensorFlow中的所有计算都会被转化为计算图上的节点,节点之间的边描述了计算之间的依赖关系。
如下图就是一个加法计算图,圆圈就是tensor,箭头就是Flow。
这里写图片描述

TF程序的两个阶段

TensorFlow不是像我们之前写Python的代码一样,想到什么写什么,而是要提前把所有的计算定义好,把规则制定好,也就是画好计算图。画好完整的图以后才能执行计算。
即TF程序通常分两个阶段:
1. 定义计算图中所有的计算;
2. 执行计算

获取TF自动维护的默认计算图

TF程序自动维护一个默认的计算图,可通过tf.get_default_graph函数获取

tf.get_default_graph
或者a.graph(如果没有特殊声明,a.graph返回其所属的计算图,即默认的计算图)

资源共享

TensorFlow中不同计算图上的张量和运算不共享,那么我们需要共享时应该如何操作呢?
一个计算图中可以通过collection管理不同类别的资源
①将资源加入集合中

tf.add_to_collection

②获取集合里的所有资源

tf.get_collectoin

数据模式—张量(Tensor)

张量是什么

Tensor是TF管理数据的形式,可简单地理解为多维数组。
张量主要保存三个属性:名字(name)、维度(shape)、类型(dtype)

张量是得到数据的过程,并未保存数据

TF中的张量并没有真正保存数据,而是如何得到这些数据的过程

举个例子就明白了:

a = tf.constant([1.0, 2.0], name='a') #定义一个常量,命名为a
b = tf.constant([2.0, 3.0], name='b') #定义一个常量,命名为b
result = tf.add(a, b, name='add') #定义一个计算模式,命名为add

print(result) #结果是Tensor("add:0", shape=(2,), dtype=float32),而不是求和后的值,这就表明我们只是定义了计算模式,还未运行

tf.Session().run(result) #加了这一步就会得到运行结果array([3., 5.], dtype=float32)

张量的用途

  1. 作为中间计算结果的引用,提高程序的可读性
  2. 通过张量获得计算结果,即真实的数据

方法为

tf.Session().run()

运行模式—会话(Session)

通过上面计算模式所举的例子我们就发现,Tensor只是定义了数据,真正的运行需要通过会话session。
Session用于管理TF程序运行时的所有资源。

会话的两种模式

1.明确调用会话生成函数和关闭会话函数

# 创建一个会话
sess = tf.Session()
print(sess.run(result)) #通过创建的会话才能输出上面定义的tensor result
# 关闭会话
sess.close()

2.通过Python上下文管理器使用会话
上下文管理器有自带的关闭功能,因此不用显示的关闭session

# 通过Python的上下文管理器来管理会话
with tf.Session() as sess:
    print(sess.run(result))

指定默认会话后用eval()计算张量的取值

TF不会自动生成默认的会话,需要手动指定。
默认的会话被指定后可通过tensor_obj.eval()计算张量的取值

tensor_obj.eval()

如:

sess = tf.Session() #手动指定一个默认会话
with sess.as_default():  # 通过Python的上下文管理器来管理会话
    print(result.eval()) #计算张量结果

也就是说,得到张量结果有两种方式,一种是直接sess.run(),另一种指定一个默认会话后用eval(),如下面的例子

sess = tf.Session()
print(sess.run(result))
print(result.eval(session=sess))
#得到的结果都是[3. 5.]

交互环境下自动将生成的会话注册为默认会话

交互环境下,使用tf.InteractiveSession,该函数会自动将生成的会话注册为默认会话

# tf.InteractiveSession
sess = tf.InteractiveSession()
print(result.eval())
#sess.close()

占位符(tf.placeholder)和变量(tf.Variable)

在tensorflow中 占位符用来传递真实的样本,变量用于可变的训练变量,如模型的权重或者偏置。

占位符(tf.placeholder)——传递真实样本

占位符其实就相当于我们函数的参数。
创建时不必指定初始值,可在运行时,通过Session.run函数的feed_dict的参数指定。

定义一个占位符需要指定他的类型

a = tf.placeholder(tf.float32) #tf.float32为占位符a的类型

举个例子:

a = tf.placeholder(tf.float32) #定义一个占位符名为a
b = tf.placeholder(tf.float32) #定义一个占位符名为b
adder_node = a + b  # + provides a shortcut for tf.add(a, b)

运行时进行初始化

sess.run(adder_node, {a: 3, b:4.5})

运行时通过字典的形式为所定义的占位符赋值

print(sess.run(adder_node, {a: 3, b:4.5}))  #输出7.5
print(sess.run(adder_node, {a: [1,3], b: [2, 4]})) #输出[3. 7.]

占位符还有一个好处就是普适性非常好,因为他定义的时候没赋初值所以接下来可以对他再进行运算。

add_and_triple = adder_node * 3.
print(sess.run(add_and_triple, {a: 3, b:4.5}))

变量(tf.Variable)——用于可变的训练变量

  • tf.Variable,用于可变的训练变量,如模型的权重或者偏置
  • 创建时必须提供初始值

tf.Variable([.3], dtype=tf.float32)

定义好后还必须进行初始化

init = tf.global_variables_initializer()
sess.run(init)

如果要对变量重新赋值,就用assign

fixW = tf.assign(W, [-1])

  • 变量的值会随在模型的训练而更改

例子
下面通过用TensorFlow实现线性回归进行说明

①首先定义变量W,b 和占位符x

W = tf.Variable([.3], dtype=tf.float32) #相当于线性回归的权重W
b = tf.Variable([-.3], dtype=tf.float32) #相当于线性回归的偏置b
x = tf.placeholder(tf.float32) #x没有初始值,是一个占位符
linear_model = W * x + b #通过这三个就可以定义一个线性回归模型

②对变量进行初始化

init = tf.global_variables_initializer()
sess.run(init)

然后就可以对占位符x进行赋值,得到线性回归模型的结果啦

print(sess.run(linear_model, {x:[1,2,3,4]})) #输出为[0.         0.3        0.6        0.90000004]

③求线性回归模型的损失函数

y = tf.placeholder(tf.float32) #首先定义一个占位符y,作为真实值
squared_deltas = tf.square(linear_model - y)#定义计算模式:计算真实值和预测值的差的平方
loss = tf.reduce_sum(squared_deltas)#损失函数loss就是把每个样本的R方加起来
print(sess.run(loss, {x:[1,2,3,4], y:[0,-1,-2,-3]})) #最后进行计算,得到的结果为23.66

### 我们可以对W,b重新赋值再看损失函数loss
fixW = tf.assign(W, [-1])
fixb = tf.assign(b, [1])
sess.run([fixW, fixb])
print(sess.run(loss, {x:[1,2,3,4], y:[0,-1,-2,-3]})) #结果为0.0,这是最优模型的结果

④用tf.train 学习出来参数

用梯度下降,然后求偏导
首先定义优化器,用优化器优化loss

optimizer = tf.train.GradientDescentOptimizer(0.01) #GradientDescentOptimizer是一个优化器,指定学习率是0.01。采用的梯度下降方法,一步一步求偏导即可得到最后的模型
train = optimizer.minimize(loss) # 用优化器优化上面指定的loss

通过优化器优化得到的模型训练样本

sess.run(init) # 重新设置初始化参数
for i in range(1000):
  sess.run(train, {x:[1,2,3,4], y:[0,-1,-2,-3]}) #迭代一千次,用上面得到的训练模型训练样本

print(sess.run([W, b])) 最后得到的结果[array([-0.9999969], dtype=float32), array([0.9999908], dtype=float32)]

上述代码将用梯度下降的方法得到了一个线性回归的模型,但是是分布讲解的,完整代码如下:
通俗的来理解就是:有一个线性回归方程y=wx+b,我们有这个方程得到的真实的结果,但是不知道参数w和b是多少,我们通过为w和b赋值,得到它的预测值然后与真实结果进行比较,得到一个损失函数,损失函数越小证明w和b距离正确结果越近。

我们训练的过程其实就是用一个优化器最小化损失函数,得到使损失函数最小的w和b也就是训练完成了。

import numpy as np
import tensorflow as tf

# 模型参数
# w和b就是我们最后训练要得到的结果,我们先为它赋上初始值w=3,b=-3
W = tf.Variable([.3], dtype=tf.float32)
b = tf.Variable([-.3], dtype=tf.float32)

# 模型的输入和输出
x = tf.placeholder(tf.float32)
linear_model = W * x + b   #定义线性回归模型
y = tf.placeholder(tf.float32)  #真实结果

# 定义损失函数
# 损失函数就是看预测值和真实结果的差距有多大
loss = tf.reduce_sum(tf.square(linear_model - y)) #linear_model为每一个x代入我们所定义的线性回归模型后得到的预测值组成的一维数组,y中对应的是真实的结果。我们求每一对真实值和预测值的均方误差然后再将结果相加作为损失函数。

# 优化算法
# 优化算法就是使用一种方法降低损失函数
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)

# 训练数据
x_train = [1,2,3,4]
y_train = [0,-1,-2,-3]

# 训练过程
init = tf.global_variables_initializer() #初始化一下
sess = tf.Session()
sess.run(init)


for i in range(100): #迭代一千次进行训练
  sess.run(train, {x:x_train, y:y_train})

# 训练误差
curr_W, curr_b, curr_loss = sess.run([W, b, loss], {x:x_train, y:y_train})
print("W: %s b: %s loss: %s"%(curr_W, curr_b, curr_loss))
版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/zxfhahaha/article/details/80200713
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-04-07 23:25:47
  • 阅读 ( 1050 )
  • 分类:Go Web框架

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢