3: TensorFlow示例

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进行可视化并监控训练过程。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容