TensorFlow是一个采用数据流图,用于数值计算的开源软件库。自己接触tensorflow比较的早,可是并没有系统深入的学习过,现在TF在深度学习已经成了“标配”,所以打算系统的学习一遍。在本篇文章中主要介绍TF的基础知识。。。

创建并运行图###

首先创建 两个变量

import tensorflow as tf
reset_graph()
x = tf.Variable(3, name="x")
y = tf.Variable(4, name="y")
f = x*x*y + y + 2
>>f
<tf.Tensor 'add_3:0' shape=() dtype=int32>

然而,f中并没有得到想要的结果,实际上上面的代码并没有真正的运行,它只是创建了一个计算图(compution graph),并且定义的变量也并没有被初始化,为了计算刚才定义的图,我们需要开启一个session,然后初始化上面的变量。

sess = tf.Session()
sess.run(x.initializer)
sess.run(y.initializer)
result = sess.run(f)
sess.close() # 最终关闭这个session
>>print(result)
42

类似python的with open()语法,我们还可以这样写

with tf.Session() as sess:
x.initializer.run() #sess.run(x.initializer)
y.initializer.run()
result = f.eval() #sess.run(f)
print(result)

注意上面代码注释的部分,这两钟方法是等价的,即

 x.initializer.run()  = tf.get_default_session().run(x.initializer)

选择哪一种写法主要取决于哪种方法简单。那么如果我们由很多的变量,都需要进行初始化,再逐一初始化就显得繁琐了,这时候我们可以使用global_variables_initializer()方法进行初始化。

init = tf.global_variables_initializer() # 准备init节点
with tf.Session() as sess:
init.run() #执行初始化动作
print(f.eval)

从上面的代码可以看出,TF程序的运行过程分为两个阶段,

  • 1.构建计算图,构建能够表示 机器学习模型的图。
  • 2.运行部分,通常是一个循环,重复地对训练步骤进行评估,改善模型的参数。

管理计算图###

当我们创建一个节点的时候, 被创建的节点自动的被添加到默认的计算图中:

>>x.graph is tf.get_default_graph()
True

但是大多的时候,我们想分别管理相互独立的graphs,这时候就要创建新的graph

graph = tf.Graph()
with graph.as_default():
x1 = tf.Variable(2) print(x1.graph is graph) #True
print(x1.graph is tf.get_default_graph) #False

note:我们在使用Python shell试验阶段的时候,可能会出现输出和我们的预期不一样,这是因为多次运行导致默认的graph包含重复的nodes,一个解决方案是重启shell,另外一个是使用tf.reset_default_graph()

节点的生命周期###

节点的生命周期也成为变量的生命周期,因为在TF中每一个变量在graph中都对应一个node,当我们创建一个node,TF会自动判断该节点的依赖关系,例如下面这段代码:

w = tf.constant(3)
x = w + 2
y = x + 5
z = x * 3
with tf.Session() as sess:
print(y.eval()) #10
print(z.eval()) #15

上面这段代码定义了一个简单的graph,并计算y和z的值,TF发现y依赖x、x依赖w。所以它依次计算w、x和y。再计算z的时候,发现需要计算x和w。最终这段代码执行了两次w和x。当执行完毕后所有的节点都被删除,除了Variable值,variable的生命周期为整个session。也就是说variable的生命周期从initializer开始,到sessionclose结束。

上面这段代码在正式的生产环境下效率是很低的,为了避免被重复计算,我们就需要告诉TF计算y和z在同一个graph中。下面是代码:

with tf.Session() as sess:
y_val,z_val = sess.run([y,z]) ##
print(y_val)
print(z_val)

note:在单进程的TF程序中,多个session是不共用变量(数据)的,每一个session有着独自的变量copy。在分布式TF程序中,变量是存储在server,而不是在session中,所以多个session可以共享变量。

使用TF求解线性回归###

1 正规方程求解####

在之前的文章使用sklearn进行数据挖掘介绍了使用sklean进行数据挖掘,这里我们使用TF来进行计算,不过为了方便我们直接使用sklean提供的数据集,跳过数据处理过程,直接使用正规方程(Normal Equation)方法求解\(\theta=(X^T\cdot X)^{-1}\cdot X^T\cdot y\)。类似Numpy,TF也提供了许多数据转换的方法,在numpy数组被成为ndarray,详见掌握numpy,在TF中的多维数组被成为张量(tensors)。

import numpy as np
from sklearn.datasets import fetch_california_housing
housing = fetch_california_housing()
m,n = housing.data.shape
data = np.c_[np.ones((m,1)),housing.data] #添加X0=1
X = tf.constant(data,dtype=tf.float32,name='X')
y = tf.constant(housing.target.reshape(-1,1),dtype=tf.float32,name='y')#转为列向量(1D -> 2D)
X_T = tf.transpose(X)
theat = tf.matmul(tf.matmul(tf.matrix_inverse( tf.matmul(X_T,X)),X_T),y)
with tf.Session() as sess:
theat_hat = theat.eval()
print(theat_hat)

上面这段代码可以完全使用Numpy替代,当然也可以使用sklearn的回归方法,也是分分钟搞定的事情,

from sklearn.linear_model import LinearRegression
lin_reg = LinearRegression()
lin_reg.fit(housing.data, housing.target.reshape(-1, 1))
print(np.vstack((lin_reg.intercept_.reshape(-1, 1), lin_reg.coef_.T)))

使用TF的优势是可以使用GPU进行运算。

note:reshape(-1,1)的作用是将一维数组转化为二维数组,参数-1表示unspecified,表示会根据数组的长度作为这一维度的值。

2 使用批梯度下降求解####

上面使用的是正规方程求解,现在我们使用梯度下降方法求解,在求解之前我们需要现对数据做normalize,否则会导致收敛速度慢

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaled_data = scaler.fit_transform(housing.data)
data = np.c_[np.ones((m,1)),scaled_data] #添加X0=1

下面就是使用TF计算梯度下降了,最终的迭代公式为$ \theta{'}=\frac{2}{m}XT\cdot (X\cdot \theta-y) $,这里就不再赘述。

n_epoch = 100
learning_rate = 0.1
X = tf.constant(data,dtype=tf.float32,name='X')
y = tf.constant(housing.target.reshape(-1,1),dtype=tf.float32,name='y')
theta = tf.Variable(tf.random_uniform([n+1,1],-1,1),name='theta')
y_pred = tf.matmul(X,theta,name='prediction')
error = y_pred - y
mse = tf.reduce_mean(tf.square(error),name='mse') #Mean Squared Error
gradient = 2/m * tf.matmul(tf.transpose(X),error)
training_op = tf.assign(theta,theta - learning_rate * gradient) init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
for epoch in range(n_epoch):
if epoch % 100 == 0:
print("Epoch", epoch, "MSE =", mse.eval())
sess.run(training_op)
>>print('best theta:',theta.eval())
Epoch 0 MSE = 9.16154
Epoch 100 MSE = 0.714501
Epoch 200 MSE = 0.566705
Epoch 300 MSE = 0.555572
Epoch 400 MSE = 0.548812
Epoch 500 MSE = 0.543636
Epoch 600 MSE = 0.539629
Epoch 700 MSE = 0.536509
Epoch 800 MSE = 0.534068
Epoch 900 MSE = 0.532147
'best theta:'
[[ 2.06855249],
[ 0.88740271],
[ 0.14401658],
[-0.34770882],
[ 0.36178368],
[ 0.00393812],
[-0.04269557],
[-0.66145277],
[-0.63752776]]

上面的代码比较简单,tf.random_uniform()生成一个均匀分布,大小为(n+1,1),取值范围(-1,1)。至于为什么n+1,是因为考虑到\(x_0=1\)。 tf.assign()是创建一个新的节点,为variable更新值

2.1使用TF自动求导####

上面代码通过手动计算损失函数导数的迭代公式计算出\(\theta\)的值,一个线性回归手动算起来固然容易,但当模型为一个神经网络再进行手动求导就会很吃力了。TF提供了自动求导功能,只需要将上面那段代码的梯度部分替换成下面

gradient = tf.gradients(mse,[theta])[0]

上面的gradients()方法能够自动的将损失函数针对参数进行求导(本例分别为\(mse\)和 \(\theta\)),

2.2使用优化器####

TF提供了计算梯度的方法,非常方便,不过还可以变得更加的方便。TF提供了许多优化方法,例如梯度下降优化器(Gradient Descent optimizer)。仅仅需要将gradient = 和training_op替换为以下代码:

optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate)
training_op = optimizer.minimize(mse)

有许多的优化方法,例如MomentumOptimizer

3 向算法中输入数据和mini-batch求导###

前面使用的是批梯度下降方法求解\(\theta\),这种方法比较适用与较小的数据集,如果数据集很大最好使用mini-batch梯度下降方法。我们需要将上面的代码迭代部分的Xy替换为mini-batch,可以使用placeholder来实现mini-batch,顾名思义这是使用占位符的方法,它们并不参与运算,只有在你指定训练的时候才输出数据,举一个例子:

A = tf.placeholder(tf.float32,shape=(None,3))
B = A + 5
with tf.Session() as sess:
test_b_1 = B.eval(feed_dict={A:[[1,2,3]]})
test_b_2 = B.eval(feed_dict={A:[[4,5,6],[7,8,9]]})
print(test_b_1) #[[ 6. 7. 8.]]
print(test_b_2) #[[ 9. 10. 11.] [ 12. 13. 14.]]

上面这段代码使用placeholder()创建一个占位符节点,并且指定其数值类型和输入形状,None表示任意长度。接着又创建一个节点为B=A+5。当计算B的值时候,使用feed_dict以字典的类型传入到eval()中。

实现mini-batch我们只需要修改少量代码,首先我们需要先定义好参与迭代的X和y

X = tf.placeholder(tf.float32, shape=(None, n + 1), name="X")
y = tf.placeholder(tf.float32, shape=(None, 1), name="y")

然后定义需要迭代的次数、学习率、batch的大小以及batch的个数还有目标函数

learning_rate = 0.01
batch_size = 100
n_batches = int(np.ceil(m / batch_size))
theta = tf.Variable(tf.random_uniform([n + 1, 1], -1.0, 1.0, seed=42), name="theta") #X0
y_pred = tf.matmul(X, theta, name="predictions")
error = y_pred - y
mse = tf.reduce_mean(tf.square(error), name="mse")
optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate)
training_op = optimizer.minimize(mse)
init = tf.global_variables_initializer()

最后就是计算过程,mini-batch逐个被送到训练算法中

def fetch_batch(epoch, batch_index, batch_size):
np.random.seed(epoch * n_batches + batch_index)
indices = np.random.randint(m, size=batch_size)
X_batch = data[indices]
y_batch = housing.target.reshape(-1, 1)[indices]
return X_batch, y_batch with tf.Session() as sess:
sess.run(init)
for epoch in range(n_epochs):#迭代的次数
for batch_index in range(n_batches):
X_batch, y_batch = fetch_batch(epoch, batch_index, batch_size)
sess.run(training_op, feed_dict={X: X_batch, y: y_batch}) best_theta = theta.eval()

模型的持久化###

类似sklearn,模型训练好之后我们可以将model持久化,以备以后的使用TF提供了Saver()方法,

init = tf.global_variables_initializer()
saver = tf.train.Saver()
with tf.Session() as sess:
sess.run(init)
for epoch in range(n_epochs):
if epoch % 100 == 0:
print("Epoch", epoch, "MSE =", mse.eval()) # 保存运行过程
save_path = saver.save(sess, "/tmp/my_model.ckpt")
sess.run(training_op) best_theta = theta.eval()
save_path = saver.save(sess, "/tmp/my_model_final.ckpt")#保存最后的结果

模型的加载也是很简单的:

with tf.Session() as sess:
saver.restore(sess, "/tmp/my_model_final.ckpt")
best_theta_restored = theta.eval()

tensorflow的一些基础用法的更多相关文章

  1. PropertyGrid控件由浅入深(二):基础用法

    目录 PropertyGrid控件由浅入深(一):文章大纲 PropertyGrid控件由浅入深(二):基础用法 控件的外观构成 控件的外观构成如下图所示: PropertyGrid控件包含以下几个要 ...

  2. logstash安装与基础用法

    若是搭建elk,建议先安装好elasticsearch 来自官网,版本为2.3 wget -c https://download.elastic.co/logstash/logstash/packag ...

  3. elasticsearch安装与基础用法

    来自官网,版本为2.3 注意elasticsearch依赖jdk,2.3依赖jdk7 下载rpm包并安装 wget -c https://download.elastic.co/elasticsear ...

  4. BigDecimal最基础用法

    BigDecimal最基础用法 用字符串生成的BigDecimal是不会丢精度的. 简单除法. public class DemoBigDecimal { public static void mai ...

  5. Vue组件基础用法

    前面的话 组件(Component)是Vue.js最强大的功能之一.组件可以扩展HTML元素,封装可重用的代码.根据项目需求,抽象出一些组件,每个组件里包含了展现.功能和样式.每个页面,根据自己所需, ...

  6. Smarty基础用法

    一.Smarty基础用法: 1.基础用法如下 include './smarty/Smarty.class.php';//引入smarty类 $smarty = new Smarty();//实例化s ...

  7. 前端自动化测试神器-Katalon的基础用法

    前言 最近由于在工作中需要通过Web端的功能进行一次大批量的操作,数据量大概在5000左右,如果手动处理, 完成一条数据的操作用时在20秒左右的话,大概需要4-5个人/天的工作量(假设一天8小时的工作 ...

  8. Bootstrap fileinput:文件上传插件的基础用法

    官网地址:http://plugins.krajee.com/ 官网提供的样例:http://plugins.krajee.com/file-input/demo 基础用法一 导入核心CSS及JS文件 ...

  9. asyncio 基础用法

    asyncio 基础用法 python也是在python 3.4中引入了协程的概念.也通过这次整理更加深刻理解这个模块的使用 asyncio 是干什么的? asyncio是Python 3.4版本引入 ...

随机推荐

  1. Blog Contents

    This page is intently left for contents catalog of my articles. |----------------------------------- ...

  2. Docker学习5-Services – 服务(未完待续)

    扩展应用程序并启用负载平衡, 为此,必须在分布式应用程序的层次结构中提升一级:服务.在分布式应用程序中,应用程序的不同部分称为“服务”.例如,一个视频共享站点,它可能包含用于将应用程序数据存储在数据库 ...

  3. OpenCV开发环境搭建-并测试一个图像灰度处理程序

    转载地址:http://blog.csdn.net/sjz_iron/article/details/8614070

  4. lwip lwiperf 方法进行性能测试 4.5MB/S

    硬件配置: STM32F407 + DP83848 + FreeRTOS V10.1.1 + LWIP 2.1.2    2018年12月5日14:31:24 1.先读取 PHY 寄存器 , 查看 自 ...

  5. 2015531 网络攻防 Exp1 PC平台逆向破解(5)M

    2015531 网络攻防 Exp1 PC平台逆向破解(5)M 实践目标 本次实践的对象是linux的可执行文件 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串 ...

  6. mfc CFileDialog类

    知识点: CFileDialog类 SetBitmap LoadImage 动态显示图片 一.CFileDialog类 构造函数 CFileDialog( BOOL bOpenFileDialog, ...

  7. Execute SQL Task 如何返回结果数据集

    Execute Sql Task的Result DataSet 主要有以下四种,当Execute Sql Task返回结果之后,需要使用SSIS Variable 来接收数据. 例子中使用的数据表代码 ...

  8. SPA程序加载首界面eclipse卡顿解决笔记

    最近在开发SPA程序项目时遇到一个问题,因为是在开发阶段,所以直接就在eclipse中启动项目. 每次进入首界面时,eclipse就会长时间卡顿,前端界面也加载不出来,很影响开发效率. 在查找问题的时 ...

  9. 起步 - vue-router路由与页面间导航

    vue-router 我们知道路由定义了一系列访问的地址规则,路由引擎根据这些规则匹配找到对应的处理页面,然后将请求转发给页进行处理.可以说所有的后端开发都是这样做的,而前端路由是不存在"请 ...

  10. centos 7 git的管理和使用

    一.linux 安装git (服务端) 1.首先创建用户账号 useradd zlx passwd zlx .... 2.创建目录git仓库 mkdir zlx_git.git 3.赋权限 chown ...