HML--上手tensorflow

1.在Session中创造第一个graph


import tensorflow as tf
x=tf.Variable(3,name='x')
y=tf.Variable(4,name='y')
f=x*x*y+y+2

这就是它的全部!最重要的是,这段代码实际上并不执行任何计算,尽管它看起来像是计算(特别是最后一行)。它只是创建了一个计算图。事实上,即使是变量还没有被初始化。要计算这个图,您需要打开一个TensorFlow  session,然后evaluate f。TensorFlow会话负责将操作放置到CPU和GPU等设备上,并运行它们,并保存所有变量值。它的形式也有以下这几种

sess=tf.Session()
sess.run(x.initializer)
sess.run(y.initializer)
result=sess.run(f)
print(result)
sess.close()

总是重复sess.run()有点麻烦,但幸运的是还有更好的方法:

with tf.Session() as sess:
    x.initializer.run()
    y.initializer.run()
    result=f.eval()
在with模块中,会话设置为默认会话。调用x.Initializer.run()等同于调用tf.get_defaultsession.run(x.Initiator),类似地,f.val()等效于调用tf.get_defaultsession().run(F)。这使得代码更易于读取。此外,会话在块末尾自动关闭。


与手动运行每个变量的初始化程序不同,您可以使用global_variables_initializer()函数。请注意,它实际上并不是立即执行初始化,而是在图中创建一个节点,在运行时初始化所有变量

init=tf.global_variables_initializer()
with tf.Session() as sess:
    init.run()
    result=f.eval()

2.图的管理

创建的任何节点都会自动添加到默认图形中。在大多数情况下,这是很好的,但有时你可能希望管理多个独立的图形。

>>> graph = tf.Graph()
>>> with graph.as_default():
... x2 = tf.Variable(2)
...
>>> x2.graph is graph
True
>>> x2.graph is tf.get_default_graph()
False

3.节点的生命周期

在计算节点时,TensorFlow会自动确定它所依赖的节点集,并首先计算这些节点:

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

首先,这段代码定义了一个非常简单的图形。然后它启动一个会话并运行图来计算y:TensorFlow自动检测y依赖于w,它依赖于x,所以它首先计算w,然后x,然后y,然后返回Y的值。最后,代码运行这个图来计算Z。再次,TensorFlow检测到它必须首先计算w和x。需要注意的是,它不会重用以前对w和x进行的计算结果。简而言之,前面的代码计算w和x两次。

所有节点值都在图运行之间删除,变量值除外,变量值由会话跨图运行维护。变量在其初始化程序运行时开始其生命,在会话关闭时结束

如果您想要有效地计算y和z,而不需要计算w和x,则必须要求TensorFlow在一个图运行中计算y和z,如下代码所示:

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

4.线性回归

输入和输出是多维数组,称为张量(因此名为“张量流”)。就像numpy数组一样,张量有一个类型和一个形状。实际上,在pythonAPI中,tensor只有numpy ndarrayy表示。它们通常包含浮点数,但也可以使用它们来携带字符串(任意字节数组)。

下面的操作演示了tensorflow在二维数据上的应用。数据来源于加利福尼亚房屋数据集。theta的正则方程为:

import tensorflow as tf
from sklearn.datasets import fetch_california_housing
import numpy as np

housing=fetch_california_housing()
m,n=housing.data.shape
housing_data_plus_bias=np.c_[np.ones((m,1)),housing.data]

X=tf.constant(housing_data_plus_bias,dtype=tf.float32,name='X')
y=tf.constant(housing.target.reshape(-1,1),dtype=tf.float32,name='y')
XT=tf.transpose(X)
theta=tf.matmul(tf.matmul(tf.matrix_inverse(tf.matmul(XT, X)), XT), y)

with tf.Session() as sess:
    theta_value=theta.eval()

与直接使用numpy计算正常方程相比,此代码的主要优点是,如果有GPU卡,TensorFlow将自动在GPU卡上运行。

5.应用梯度下降

5.1手工计算

首先一些注意事项:

  •  random_uniform()函数在图中创建一个节点,该节点将生成包含随机值的张量,给定其形状和值范围,就像numpy的rand()函数一样
  • 函数创建一个节点,将一个新值赋值给变量。在这种情况下,它实现了批处理梯度下降步骤theta=theta-
  • 主循环一次又一次地执行训练步骤,每100次迭代就会输出当前的均方误差(MSE)。
import tensorflow as tf
from sklearn.datasets import fetch_california_housing
import numpy as np
from sklearn.preprocessing import scale

housing=fetch_california_housing()
m,n=housing.data.shape
housing_data_plus_bias=np.c_[np.ones((m,1)),housing.data]
scale_housing_data_plus_bias=scale(housing_data_plus_bias)

n_epochs=1000
learning_rate=0.01

X=tf.constant(scale_housing_data_plus_bias,dtype=tf.float32,name='X')
y=tf.constant(housing.target.reshape(-1,1),dtype=tf.float32,name='y')
XT=tf.transpose(X)
theta=tf.Variable(tf.random_uniform([n+1,1],-1.0,1.0),name='theta')
y_pred=tf.matmul(X,theta,name='predictctions')
error=y_pred-y
mse = tf.reduce_mean(tf.square(error), name="mse")
gradients = 2/m * tf.matmul(tf.transpose(X), error)
training_op = tf.assign(theta, theta - learning_rate * gradients)
init=tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)
    for epoch in range(n_epochs):
        if  epoch%100==0:
            print('Epoch',epoch,'MSE=',mse.eval())
            sess.run(training_op)
    best_theta=theta.eval()

运行结果如下:


5.2使用autodiff

TensorFlow的Autodiff特性:它可以自动高效地计算梯度

gradients=tf.gradients(mse,[theta])[0])
gradients()函数接受运算op(mse)和变量theta,并创建一个列表中的行动(每一个变量)计算OP的梯度。因此,梯度节点将计算与θ有关的MSE的梯度向量。

5.3使用优化器

还可以变得更加简单:

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

当然,optimizer可以自由选择种类。

完成代码贴一遍:

import tensorflow as tf
from sklearn.datasets import fetch_california_housing
import numpy as np
from sklearn.preprocessing import scale

housing=fetch_california_housing()
m,n=housing.data.shape
housing_data_plus_bias=np.c_[np.ones((m,1)),housing.data]
scale_housing_data_plus_bias=scale(housing_data_plus_bias)

n_epochs=1000
learning_rate=0.01

X=tf.constant(scale_housing_data_plus_bias,dtype=tf.float32,name='X')
y=tf.constant(housing.target.reshape(-1,1),dtype=tf.float32,name='y')
XT=tf.transpose(X)
theta=tf.Variable(tf.random_uniform([n+1,1],-1.0,1.0),name='theta')
y_pred=tf.matmul(X,theta,name='predictctions')
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()

with tf.Session() as sess:
    sess.run(init)
    for epoch in range(n_epochs):
        if  epoch%100==0:
            print('Epoch',epoch,'MSE=',mse.eval())
            sess.run(training_op)
    best_theta=theta.eval()

6.给训练算法喂数据

让我们尝试修改前面的代码来实现小批量渐变下降。为此,我们需要一种在下一次迭代中用每一个迭代替换x和y的方法。做到这一点最简单的方法是使用占位符节点。这些节点是特殊的,因为它们实际上不执行任何计算,它们只在运行时输出你告诉它们该输出的数据。如果在运行时没有为占位符指定值,则会得到一个异常

若要创建占位符节点,必须调用 placeholder()函数并指定输出张量的数据类型,也可以指定它的shape。

例如:

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

好,现在开始应用到Mini-batch Gradient Descent 。

# -*- coding: utf-8 -*-
"""
Created on Sat Mar 10 18:00:36 2018

@author: john
"""
import tensorflow as tf
from sklearn.datasets import fetch_california_housing
import numpy as np
from sklearn.preprocessing import scale

housing=fetch_california_housing()
m,n=housing.data.shape
housing_data_plus_bias=np.c_[np.ones((m,1)),housing.data]
scale_housing_data_plus_bias=scale(housing_data_plus_bias)
target=housing.target

n_epochs=1000
learning_rate=0.01
batch_size=100
n_batches=int(np.ceil(m / batch_size))


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

XT=tf.transpose(X)
theta=tf.Variable(tf.random_uniform([n+1,1],-1.0,1.0),name='theta')
y_pred=tf.matmul(X,theta,name='predictctions')
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()

def fetch_batch(epoch,batch_index,batch_size):
    np.random.seed(epoch*n_batches+batch_index) # 每次调用 都有不同的 随机种子
    indices = np.random.randint(m,size=batch_size) # 去 0 ~ m-1 之间去 batch_size 整数
    X_batch = scale_housing_data_plus_bias[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()

7.加载和保存模型

一旦你训练好了你的模型,你应该把它的参数保存到磁盘上,这样你就可以随时回到它,在其他程序中使用它,和其他模型比较,等等。此外,你可能想在训练期间把检查点保存在checkpoint上,这样如果你的电脑在训练期间崩溃,你可以从上一个检查点开始,而不是从头开始

TensorFlow使保存和恢复模型变得非常容易。只需在构建阶段结束时(在创建了所有可变节点之后)创建一个Saver节点;然后,在执行阶段,只要您想保存模型,传递它的会话和检查点文件的路径,只需调用它的Save()方法。

[...]
theta = tf.Variable(tf.random_uniform([n + 1, 1], -1.0, 1.0), name="theta")
[...]
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: # checkpoint every 100 epochs
            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")

恢复模式是一样容易:你在最后阶段创建了一个Saver,就像之前,但在执行阶段的开始,而不是初始化变量,而是restore:

with tf.Session() as sess:
saver.restore(sess, "/tmp/my_model_final.ckpt")
[...]

7.在TensorBoard 中可视化图以及训练曲线

第一步是稍微调整一下程序,这样它就会将图形定义和一些训练状态(例如,训练错误(MSE))写入一个日志目录,TensorBoard将从中读取。每次运行程序时,都需要使用不同的日志目录,否则tensorboard将合并来自不同运行的状态,这会破坏可视化。最简单的解决方案是包括。日志目录名中的时间戳。在程序的开头添加以下代码:

from datetime import datetime
now = datetime.utcnow().strftime("%Y%m%d%H%M%S")
root_logdir = "tf_logs"
logdir = "{}/run-{}/".format(root_logdir, now)
import tensorflow as tf
from sklearn.datasets import fetch_california_housing
import numpy as np
from sklearn.preprocessing import scale
from datetime import datetime
##在开头加上这些代码
now=datetime.utcnow().strftime("%Y%m%d%H%M%S")
root_logdir = "tf_logs"
logdir = "{}/run-{}/".format(root_logdir, now)



housing=fetch_california_housing()
m,n=housing.data.shape
housing_data_plus_bias=np.c_[np.ones((m,1)),housing.data]
scale_housing_data_plus_bias=scale(housing_data_plus_bias)
target=housing.target

n_epochs=1000
learning_rate=0.01
batch_size=100
n_batches=int(np.ceil(m / batch_size))


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

XT=tf.transpose(X)
theta=tf.Variable(tf.random_uniform([n+1,1],-1.0,1.0),name='theta')
y_pred=tf.matmul(X,theta,name='predictctions')
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()
saver=tf.train.Saver()
##在模型构建后面加上以下语句
mse_summary=tf.summary.scalar('MSE',mse)
file_writer=tf.summary.FileWriter(logdir,tf.get_default_graph())


def fetch_batch(epoch,batch_index,batch_size):
    np.random.seed(epoch*n_batches+batch_index) # 每次调用 都有不同的 随机种子
    indices = np.random.randint(m,size=batch_size) # 去 0 ~ m-1 之间去 batch_size 整数
    X_batch = scale_housing_data_plus_bias[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)
            if batch_index % 10 == 0:
                summary_str = mse_summary.eval(feed_dict={X:X_batch,y:y_batch})
                step = epoch * n_batches + batch_index
                file_writer.add_summary(summary_str,step)
            sess.run(training_op, feed_dict={X: X_batch, y: y_batch})

运行完成后,


8.命名空间

当处理更复杂的模型(如神经网络)时,图中很容易出现数千节点的混乱。为了避免这一点,可以创建名称作用域来分组相关节点。例如,让我们修改前面的代码,在名范围“丢失”中定义错误和MSE操作:

with tf.name_scope("loss") as scope:
error = y_pred - y
mse = tf.reduce_mean(tf.square(error), name="mse")
>>> print(error.op.name)
loss/sub
>>> print(mse.op.name)
loss/mse











  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值