tensorflow的一些基础用法
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梯度下降方法。我们需要将上面的代码迭代部分的X和y替换为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的一些基础用法的更多相关文章
- PropertyGrid控件由浅入深(二):基础用法
目录 PropertyGrid控件由浅入深(一):文章大纲 PropertyGrid控件由浅入深(二):基础用法 控件的外观构成 控件的外观构成如下图所示: PropertyGrid控件包含以下几个要 ...
- logstash安装与基础用法
若是搭建elk,建议先安装好elasticsearch 来自官网,版本为2.3 wget -c https://download.elastic.co/logstash/logstash/packag ...
- elasticsearch安装与基础用法
来自官网,版本为2.3 注意elasticsearch依赖jdk,2.3依赖jdk7 下载rpm包并安装 wget -c https://download.elastic.co/elasticsear ...
- BigDecimal最基础用法
BigDecimal最基础用法 用字符串生成的BigDecimal是不会丢精度的. 简单除法. public class DemoBigDecimal { public static void mai ...
- Vue组件基础用法
前面的话 组件(Component)是Vue.js最强大的功能之一.组件可以扩展HTML元素,封装可重用的代码.根据项目需求,抽象出一些组件,每个组件里包含了展现.功能和样式.每个页面,根据自己所需, ...
- Smarty基础用法
一.Smarty基础用法: 1.基础用法如下 include './smarty/Smarty.class.php';//引入smarty类 $smarty = new Smarty();//实例化s ...
- 前端自动化测试神器-Katalon的基础用法
前言 最近由于在工作中需要通过Web端的功能进行一次大批量的操作,数据量大概在5000左右,如果手动处理, 完成一条数据的操作用时在20秒左右的话,大概需要4-5个人/天的工作量(假设一天8小时的工作 ...
- Bootstrap fileinput:文件上传插件的基础用法
官网地址:http://plugins.krajee.com/ 官网提供的样例:http://plugins.krajee.com/file-input/demo 基础用法一 导入核心CSS及JS文件 ...
- asyncio 基础用法
asyncio 基础用法 python也是在python 3.4中引入了协程的概念.也通过这次整理更加深刻理解这个模块的使用 asyncio 是干什么的? asyncio是Python 3.4版本引入 ...
随机推荐
- javascript瀑布流效果
javascript瀑布流效果 其实javascript瀑布流 前几年都已经很流行了(特别是美丽说,蘑菇街),最近看到网上有人问这个瀑布流效果,所以自己有空的时候就研究了下,其实也是研究别人的代码,研 ...
- PAT B1017 A除以B (20 分)
本题要求计算 /,其中 A 是不超过 1000 位的正整数,B 是 1 位正整数.你需要输出商数 Q 和余数 R,使得 A=B×Q+R成立. 输入格式: 输入在一行中依次给出 A 和 B,中间以 1 ...
- vector,deque,list的区别和使用
vector: 表示一段连续的内存区域,每个元素被顺序存储在这段内存中,对vector的随机访问效率很高,但对非末尾元素的插入和删除则效率非常低. deque: 也表示N段连续的内存区域组成,但与ve ...
- DQN(Deep Reiforcement Learning) 发展历程(四)
目录 不基于模型的控制 选取动作的方法 在策略上的学习(on-policy) 不在策略上的学习(off-policy) 参考 DQN发展历程(一) DQN发展历程(二) DQN发展历程(三) DQN发 ...
- day79
昨日回顾 昨日回顾: cookie: -是什么?存储在客户端浏览器上的键值对 -干啥用的?记录状态 -django中使用: -设置值: -HttpResponse对象,obj.set_cookie(k ...
- day41
今日内容: 1.完整查询语句 2.多表查询 3.子查询 1.完整查询语句: 首先对于昨天的学习补充一个复制表 示例:首先我在一个库中创建了一个t1表(id 为int类型 设置为主键 并且设置了自增描述 ...
- Python+Selenium爬取动态加载页面(2)
注: 上一篇<Python+Selenium爬取动态加载页面(1)>讲了基本地如何获取动态页面的数据,这里再讲一个稍微复杂一点的数据获取全国水雨情网.数据的获取过程跟人手动获取过程类似,所 ...
- Luogu P1113 杂务
终于没有打模板题了. 一道简单的拓扑题目(但记得以前第一次做的时候爆0了). 发现这个做事的过程是按一定顺序的,然后如果一个工作的前面没有任何事情的话,它一定先被完成(如果不的话就不能使时间最小化,其 ...
- Android环境下使用call_usermodehelper()以及调试
有时候设备驱动需要做一些与其他的设备通信的操作,但是驱动本身又不可以去实作,那这个时候就可以通过调用用户态的软件,通过这个软件和其他的设备进行通信. 那在内核态如何去调用用户态的程序呢?call_us ...
- git和github使用教程
看官请移步git和github简单教程, 本文是上述链接的截图,担心哪天作者不小心删除了,备一份在自己这里,仅为自己看着方便.侵权请告知