3: TensorFlow and Neural Nets Review Session

TensorFlow示例

该示例演示了一些Tensorflow的基本功能:

  1. 什么是TensorFlow
  2. 如何输入数据
  3. 如何实施计算
  4. 如何创建变量
  5. 如何使用神经网络解决一个简单的回归问题.
  6. 同时包含一些小技巧

导入需要的库文件

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import matplotlib.patches as mpatches

定义一个函数以恢复Tensorflow

def tf_reset():
    try:
        sess.close()
    except:
        pass
    tf.reset_default_graph()
    return tf.Session()

0. 什么是Tensorflow

Tensorflow只是定义一系列计算图的框架,我们可以定义输入,定义如何计算,然后Tensorflow就给我们计算结果。

先从一个简单的例子开始:

# 先创建个session,就好像我们开始在白纸上写公式
sess = tf_reset()
# 定义输入
a = tf.constant(1.0)
b = tf.constant(2.0)
# 做加法计算
c = a + b
# 得到结果了
c_run = sess.run(c)
print('c = {0}'.format(c_run))
c = 3.0

1. 如何输入数据

Tensorflow有很多方法让我们输入数据,其中一种就是使用常量。

sess = tf_reset()
# 输入常量
a = tf.constant(1.0)
b = tf.constant(2.0)
# 做计算
c = a + b
# 得到结果
c_run = sess.run(c)
print('c = {0}'.format(c_run))
c = 3.0

我们当然也可以通过placeholder,占一个坑位,让我们的输入更加灵活,这里考虑的是我们知道输入的shape。

sess = tf_reset()
# 定义输入placeholder
a = tf.placeholder(dtype=tf.float32, shape=[1], name='a_placeholder')
b = tf.placeholder(dtype=tf.float32, shape=[1], name='b_placeholder')
# 计算 
c = a + b
# 得到结果
c0_run = sess.run(c, feed_dict={a: [1.0], b: [2.0]})
c1_run = sess.run(c, feed_dict={a: [2.0], b: [4.0]})
print('c0 = {0}'.format(c0_run))
print('c1 = {0}'.format(c1_run))
c0 = [3.]
c1 = [6.]

如果我们不知道输入的shape是多少,我们可以用None去代替shape的值。

sess = tf_reset()
a = tf.placeholder(dtype=tf.float32, shape=[None], name='a_placeholder')
b = tf.placeholder(dtype=tf.float32, shape=[None], name='b_placeholder')
c = a + b
c0_run = sess.run(c, feed_dict={a: [1.0], b: [2.0]})
c1_run = sess.run(c, feed_dict={a: [1.0, 2.0], b: [2.0, 4.0]})
print(a)
print('a shape: {0}'.format(a.get_shape()))
print(b)
print('b shape: {0}'.format(b.get_shape()))
print('c0 = {0}'.format(c0_run))
print('c1 = {0}'.format(c1_run))
Tensor("a_placeholder:0", shape=(?,), dtype=float32)
a shape: (?,)
Tensor("b_placeholder:0", shape=(?,), dtype=float32)
b shape: (?,)
c0 = [3.]
c1 = [3. 6.]

2. 如何实施计算

已经知道怎么输入数据了,那就看看怎么进行数据计算吧。

首先,创建要用的实验数据:

sess = tf_reset()
# 输入
a = tf.constant([[-1.], [-2.], [-3.]], dtype=tf.float32)
b = tf.constant([[1., 2., 3.]], dtype=tf.float32)
a_run, b_run = sess.run([a, b])
print('a:\n{0}'.format(a_run))
print('b:\n{0}'.format(b_run))
a:
[[-1.]
 [-2.]
 [-3.]]
b:
[[1. 2. 3.]]

先来做个加法:

c = b + b
c_run = sess.run(c)
print('b:\n{0}'.format(b_run))
print('c:\n{0}'.format(c_run))
b:
[[1. 2. 3.]]
c:
[[2. 4. 6.]]

在计算的时候一定要注意维度匹配,下面的情况明显就出现了广播。

c = a + b
c_run = sess.run(c)
print('a:\n{0}'.format(a_run))
print('b:\n{0}'.format(b_run))
print('c:\n{0}'.format(c_run))
a:
[[-1.]
 [-2.]
 [-3.]]
b:
[[1. 2. 3.]]
c:
[[ 0.  1.  2.]
 [-1.  0.  1.]
 [-2. -1.  0.]]

有些维度不对的计算,会有以外的结果哦:

c_elementwise = a * b
c_matmul = tf.matmul(b, a)
c_elementwise_run, c_matmul_run = sess.run([c_elementwise, c_matmul])
print('a:\n{0}'.format(a_run))
print('b:\n{0}'.format(b_run))
print('c_elementwise:\n{0}'.format(c_elementwise_run))
print('c_matmul: \n{0}'.format(c_matmul_run))
a:
[[-1.]
 [-2.]
 [-3.]]
b:
[[1. 2. 3.]]
c_elementwise:
[[-1. -2. -3.]
 [-2. -4. -6.]
 [-3. -6. -9.]]
c_matmul: 
[[-14.]]

这些计算都可以形成链条,进行依次计算,形成计算图。

# operations can be chained together
c0 = b + b
c1 = c0 + 1
c0_run, c1_run = sess.run([c0, c1])
print('b:\n{0}'.format(b_run))
print('c0:\n{0}'.format(c0_run))
print('c1:\n{0}'.format(c1_run))
b:
[[1. 2. 3.]]
c0:
[[2. 4. 6.]]
c1:
[[3. 5. 7.]]

最后,Tensorflow起始包含了很多内置的函数,比如下面的计算平均的函数reduce_mean.

c = tf.reduce_mean(b)
c_run = sess.run(c)
print('b:\n{0}'.format(b_run))
print('c:\n{0}'.format(c_run))
b:
[[1. 2. 3.]]
c:
2.0

3. 如何创建变量

下面来考虑下如何引入变量,有了变量我们才可以使用优化方法,比如梯度下降,Adam,Moment等等。

首先,还是来生成一些实验数据:

sess = tf_reset()
# inputs
b = tf.constant([[1., 2., 3.]], dtype=tf.float32)
sess = tf.Session()
b_run = sess.run(b)
print('b:\n{0}'.format(b_run))
b:
[[1. 2. 3.]]

下面创建变量:

var_init_value = [[2.0, 4.0, 6.0]]
var = tf.get_variable(name='myvar',
                      shape=[1, 3],
                      dtype=tf.float32,
                      initializer=tf.constant_initializer(var_init_value))
print(var)
<tf.Variable 'myvar:0' shape=(1, 3) dtype=float32_ref>

检查看看这个变量是不是添加到了Tensorflow的变量列表吧。

print(tf.global_variables())
[<tf.Variable 'myvar:0' shape=(1, 3) dtype=float32_ref>]

变量当然是和其他张量一样得使用。

# can do operations
c = b + var
print(b)
print(var)
print(c)
Tensor("Const:0", shape=(1, 3), dtype=float32)
<tf.Variable 'myvar:0' shape=(1, 3) dtype=float32_ref>
Tensor("add:0", shape=(1, 3), dtype=float32)

但是在进行最后计算之前,不要忘记对变量进行初始化。

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

初始化之后才可以进行运算。

c_run = sess.run(c)
print('b:\n{0}'.format(b_run))
print('var:\n{0}'.format(var_init_value))
print('c:\n{0}'.format(c_run))
b:
[[1. 2. 3.]]
var:
[[2.0, 4.0, 6.0]]
c:
[[3. 6. 9.]]

4. 如何使用神经网络解决一个简单的回归问题

首先,先建立一个一维的回归问题,我们用sin函数来生成了一些需要的数据。

# 生成sin数据
inputs = np.linspace(-2*np.pi, 2*np.pi, 10000)[:, None]
outputs = np.sin(inputs) + 0.05 * np.random.normal(size=[len(inputs),1])
plt.scatter(inputs[:, 0], outputs[:, 0], s=0.1, color='k', marker='o')
<matplotlib.collections.PathCollection at 0x7ffa1bed23c8>


output_41_1.png

下面的代码先创建输入,创建变量,和创建NN的计算图,使用均方差作为损失函数,使用梯度下降的优化算法,最后使用minibatches运行训练过程。

sess = tf_reset()
def create_model():
    # 创建输入
    input_ph = tf.placeholder(dtype=tf.float32, shape=[None, 1])
    output_ph = tf.placeholder(dtype=tf.float32, shape=[None, 1])
    # 创建变量
    W0 = tf.get_variable(name='W0', shape=[1, 20], initializer=tf.contrib.layers.xavier_initializer())
    W1 = tf.get_variable(name='W1', shape=[20, 20], initializer=tf.contrib.layers.xavier_initializer())
    W2 = tf.get_variable(name='W2', shape=[20, 1], initializer=tf.contrib.layers.xavier_initializer())
    b0 = tf.get_variable(name='b0', shape=[20], initializer=tf.constant_initializer(0.))
    b1 = tf.get_variable(name='b1', shape=[20], initializer=tf.constant_initializer(0.))
    b2 = tf.get_variable(name='b2', shape=[1], initializer=tf.constant_initializer(0.))
    weights = [W0, W1, W2]
    biases = [b0, b1, b2]
    activations = [tf.nn.relu, tf.nn.relu, None]
    # 构建计算图
    layer = input_ph
    for W, b, activation in zip(weights, biases, activations):
        layer = tf.matmul(layer, W) + b
        if activation is not None:
            layer = activation(layer)
    output_pred = layer
    
    return input_ph, output_ph, output_pred
    
input_ph, output_ph, output_pred = create_model()
    
# 创建损失函数
mse = tf.reduce_mean(0.5 * tf.square(output_pred - output_ph))
# 创建Optimizer
opt = tf.train.AdamOptimizer().minimize(mse)
# 变量初始化
sess.run(tf.global_variables_initializer())
# 创建个saver,把变量保存起来
saver = tf.train.Saver()
# 开始训练过程
batch_size = 32
for training_step in range(10000):
    # 随机获取训练数据的子集
    indices = np.random.randint(low=0, high=len(inputs), size=batch_size)
    input_batch = inputs[indices]
    output_batch = outputs[indices]
    
    # 运行optimizer,然后会得到MSE(均方差)
    _, mse_run = sess.run([opt, mse], feed_dict={input_ph: input_batch, output_ph: output_batch})
    
    # 运行过程中在每个1000步的时候把MSE打印出来。
    if training_step % 1000 == 0:
        print('{0:04d} mse: {1:.3f}'.format(training_step, mse_run))
        saver.save(sess, '/tmp/model.ckpt')
0000 mse: 0.428
1000 mse: 0.067
2000 mse: 0.027
3000 mse: 0.016
4000 mse: 0.006
5000 mse: 0.002
6000 mse: 0.002
7000 mse: 0.001
8000 mse: 0.002
9000 mse: 0.001

NN我们已经训练好了,然后就可以用来做预测了:

sess = tf_reset()
# 创建个model
input_ph, output_ph, output_pred = create_model()
# 从保存的模型中恢复模型参数
saver = tf.train.Saver()
saver.restore(sess, "/tmp/model.ckpt")
output_pred_run = sess.run(output_pred, feed_dict={input_ph: inputs})
plt.scatter(inputs[:, 0], outputs[:, 0], c='k', marker='o', s=0.1)
plt.scatter(inputs[:, 0], output_pred_run[:, 0], c='r', marker='o', s=0.1)
INFO:tensorflow:Restoring parameters from /tmp/model.ckpt
<matplotlib.collections.PathCollection at 0x7ff9dc62a550>


output_45_2.png

其实看起来并不难,基本原理就这样,高级用法也不是在这里能够说清楚的了。

5. 一些小技巧

(a) 注意检查数据维度
# 这样的操作会有产生广播的。
a = tf.constant(np.random.random((4, 1)))
b = tf.constant(np.random.random((1, 4)))
c = a * b
assert c.get_shape() == (4, 4)
(b) 要注意见擦汗变量是否被创建
sess = tf_reset()
a = tf.get_variable('I_am_a_variable', shape=[4, 6])
b = tf.get_variable('I_am_a_variable_too', shape=[2, 7])
for var in tf.global_variables():
    print(var.name)
I_am_a_variable:0
I_am_a_variable_too:0
(c) 随时看看tensorflow的API,找到帮助文档。
help(tf.reduce_mean)

(d) Tensorflow还包含了很多内置的高级封装可以简化代码,当然也可以用Keras.
help(tf.contrib.layers.fully_connected)

(e) 好好使用variable_scope可以让我们的变量更有逻辑,避免陷入混乱之中。
sess = tf_reset()
# 创建变量
with tf.variable_scope('layer_0'):
    W0 = tf.get_variable(name='W0', shape=[1, 20], initializer=tf.contrib.layers.xavier_initializer())
    b0 = tf.get_variable(name='b0', shape=[20], initializer=tf.constant_initializer(0.))
with tf.variable_scope('layer_1'):
    W1 = tf.get_variable(name='W1', shape=[20, 20], initializer=tf.contrib.layers.xavier_initializer())
    b1 = tf.get_variable(name='b1', shape=[20], initializer=tf.constant_initializer(0.))
    
with tf.variable_scope('layer_2'):
    W2 = tf.get_variable(name='W2', shape=[20, 1], initializer=tf.contrib.layers.xavier_initializer())
    b2 = tf.get_variable(name='b2', shape=[1], initializer=tf.constant_initializer(0.))
#打印变量
var_names = sorted([v.name for v in tf.global_variables()])
print('\n'.join(var_names))
layer_0/W0:0
layer_0/b0:0
layer_1/W1:0
layer_1/b1:0
layer_2/W2:0
layer_2/b2:0
(f) 可以指定GPU,还可以指定内存的使用量。
gpu_device = 0
gpu_frac = 0.5
# 设置只使用1个GPU
import os
os.environ["CUDA_VISIBLE_DEVICES"] = str(gpu_device)
# 设置只使用部分GPU显存。
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=gpu_frac)
config = tf.ConfigProto(gpu_options=gpu_options)
# 创建session
tf_sess = tf.Session(graph=tf.Graph(), config=config)
(g) 好好使用tensorboard进行可视化并监控训练过程。

https://www.jianshu.com/p/8cbd0d0c3c05

「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!
0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论