TensorFlow示例
该示例演示了一些Tensorflow的基本功能:
- 什么是TensorFlow
- 如何输入数据
- 如何实施计算
- 如何创建变量
- 如何使用神经网络解决一个简单的回归问题.
- 同时包含一些小技巧
导入需要的库文件
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>
![](https://img.haomeiwen.com/i15463866/c8f6fc85bf31c238.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>
![](https://img.haomeiwen.com/i15463866/9d9749a04d9bc8b1.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)
网友评论