TensorFlow 基础 (Python)

@Deprecated让我们拥抱tensorflow2.0吧

0. 概述

TensorFlow提供了实现机器学习算法的一套API。当然也提供了一套预定义库实现了常见机器学习算法。由于是开源项目,所有这些算法都可以自行改进。TensorFlow可以很轻松地扩展到集群。


TensorFlow环境
(a*b)+c的TensorFlow计算图

1. 安装

CPU版本
pip install tensorflow
GPU版本

根据https://www.tensorflow.org/install/gpu的版本要求分别安装CUDA和cuDNN
如果要用最新版本的CUDA,参考这篇文章
对应tensorflow版本在这

pip install tensorflow-gpu

2. 样例

实现两个向量相加

import tensorflow as tf

a = tf.constant([1,2], name="a")
b = tf.constant([2,3], name="b")
result = a + b  # 这个代码实际上并不执行任何计算,它只是创建一个计算图
print(result)
# Tensor("add_3:0", shape=(2,), dtype=int32)

sess = tf.Session()
print(sess.run(result))
# [3 5]
sess.close()
# 会话负责处理在 CPU 和 GPU 上的操作并运行它们

'''
为了避免每次重复的close session,更好的写法如下:
'''
with tf.Session() as sess
    sess.run(result)

3.基本概念

Tensor:张量、多维数组。Flow:流,张量之间通过计算互相转换的过程。
TensorFlow程序一般分为两个步骤,首先定义计算图,然后进行计算。在机器学习中,这个步骤相当于先构建模型的计算图,然后进行训练。

计算图

TensorFlow通过计算图的形式来表述系统。计算图上的每个节点都是计算,节点之间的边表示计算之间的依赖关系。


上文样例的计算图,a和b不依赖任何计算,add计算依赖读取a和b的值(TensorFlow会将长亮转化成一种永远输出固定值的运算)

可视化

TensorBoard是TensorFlow的可视化工具。
在代码中加入:

writer = tf.summary.FileWriter("tfgraph", tf.get_default_graph())  # 将计算图写入日志,用于可视化
writer.close()

命令行运行:

tensorboard --logdir="tfgraph"

会启动一个服务,默认端口6006,通过浏览器访问查看可视化结果

默认图

创建的任何节点都会自动添加到默认图

a.graph is tf.get_default_graph()
# True
#a.graph 即获取张量所属的计算图

重置默认图

tf.reset_default_grapgh()

添加图

g = tf.Graph()
with g.as_default():
    x = tf.Variable(2)

x.graph is tf.get_default_graph()
# False

with g.device('/gpu:0'):     # 指定运行的设备
    result = a*a

with tf.Session(graph=g) as sess:
    # do the calculation here

张量

张量是TensorFlow管理数据的形式,可以理解成一个多维数组,0阶的表示的是标量,1阶表示一个一维数组,其中保存的并不是运算的结果,而是如何得到结果的运算过程,一个引用。

a = tf.constant([1,2], name="a")
b = tf.constant([2,3], name="b")
res = a+b
print(res)
# Tensor("add:0", shape=(2,), dtype=int32)

可以看到res是一个张量,张量的结构有三部分组成

  • 名字:张量的唯一标识符,同时以node:src_output的形式告诉了我们这个张量的结果是如何计算出来的,add:0表示该张量的结果是add节点的第0个输出。
  • 维度:维度信息 shape=(2,)表示一维数组,且长度为2。
  • 类型:每个张量都有唯一的类型,当类型不匹配时会报错。在定义变量的时候可以指定类型:a = tf.constant([1,2], name="a", dtype=float32)。

基本操作:get_shape(),reshape(),rank,dtype,cast

TensorFlow基本类型

  • tf.constant常量
  • tf.variable计算图中需要调整地变量。生命周期:从调用initializer到session结束。每个session都持有了所有变量的副本。但是在分布式环境中,变量存储在服务器中,所有session共享。
  • tf.placeholder存放数据

Session 会话

session负责执行定义好的计算,拥有并管理运行时的所有资源,需要通过关闭会话来释放资源。当会话被指定后,可以通过tf.Tensor.eval()来获取张量的取值。

a = tf.constant([1,2], name="a")
b = tf.constant([2,3], name="b")
res = a+b

with tf.Session() as sess:
    print(sess.run(res))
    print(res.eval(session=sess))
# [3, 5]
# 两种表达方式等价

tf.InteractiveSession()是一种交互式的session方式,它让自己成为了默认的session,也就是说用户在不需要指明用哪个session运行的情况下,就可以运行起来,这就是默认的好处。这样的话就是run()和eval()函数可以不指明session。

ConfigProto

ConfigProto用于配置会话。

config = tf.ConfigProto(allow_soft_placement=True, allow_soft_placement=True)
config.gpu_options.per_process_gpu_memory_fraction = 0.4  #占用40%显存
sess = tf.Session(config=config)
  • 设置tf.ConfigProto()中参数log_device_placement = True ,可以获取到 operations 和 Tensor 被指派到哪个设备(几号CPU或几号GPU)上运行,会在终端打印出各项操作是在哪个设备上运行的
  • 在tf中,通过命令 "with tf.device('/cpu:0'):",允许手动设置操作运行的设备。如果手动设置的设备不存在或者不可用,就会导致tf程序等待或异常,为了防止这种情况,可以设置tf.ConfigProto()中参数allow_soft_placement=True,允许tf自动选择一个存在并且可用的设备来运行操作。

4. 简单神经网络可视化

TensorFlow Playground是一个简单神经网络训练过程可视化工具。

  • 边的黄色越深表示负的绝对值越大
  • 边的蓝色越深表示正的绝对值越大
  • 节点的颜色代表了这个节点的区分平面

5. 完整神经网络样例程序

三层全连接神经网络图结构图
import tensorflow as tf
from numpy.random import RandomState
'''
1. 定义神经网络的参数,输入和输出节点。
'''
batch_size = 8
learning_rate = 0.001
# tf.Variable用于保存和更新神经网络中的参数
w1= tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1)) # tf.random_normal生成正态分布的随机数
w2= tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1))
x = tf.placeholder(tf.float32, shape=(None, 2), name="x-input")
y_= tf.placeholder(tf.float32, shape=(None, 1), name='y-input')
# 如果每次迭代中选取的数据都要用常量来表示,那么计算图将会太大。因为每生成一个常量,都会在计算图中增加一个节点。
# TensorFlow提供了placeholder机制用于提供输入数据。
'''
2. 定义前向传播过程,损失函数及反向传播算法。
'''
a = tf.matmul(x, w1) # tf.matmul 矩阵乘法
y = tf.matmul(a, w2)
y = tf.sigmoid(y) # 激活函数的一种 sigmoid: y = 1/(1 + exp (-x))。
cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0))
                                + (1 - y_) * tf.log(tf.clip_by_value(1 - y, 1e-10, 1.0)))
# reduce_mean求平均值
train_step = tf.train.AdamOptimizer(learning_rate).minimize(cross_entropy)
# 定义了反向传播算法,常用的还有GradientDescentOptimizer, MomentumOptimizer
'''
3. 生成模拟数据集。
'''
rdm = RandomState(1)
X = rdm.rand(128,2)
Y = [[int(x1+x2 < 1)] for (x1, x2) in X]

'''
4. 创建一个会话来运行TensorFlow程序。
'''
with tf.Session() as sess:
    init_op = tf.global_variables_initializer()
    sess.run(init_op)
    
    # 输出目前(未经训练)的参数取值。
    print(sess.run(w1))
    print(sess.run(w2))
    print("\n")
    
    # 训练模型。
    STEPS = 5000
    for i in range(STEPS):
        start = (i*batch_size) % 128
        end = (i*batch_size) % 128 + batch_size
        sess.run([train_step, y, y_], feed_dict={x: X[start:end], y_: Y[start:end]})
        if i % 1000 == 0:
            total_cross_entropy = sess.run(cross_entropy, feed_dict={x: X, y_: Y})
            print("After %d training step(s), cross entropy on all data is %g" % (i, total_cross_entropy))
    
    # 输出训练后的参数取值。
    print("\n")
    print(sess.run(w1))
    print(sess.run(w2))
'''
[[-0.8113182   1.4845988   0.06532937]
 [-2.4427042   0.0992484   0.5912243 ]]
[[-0.8113182 ]
 [ 1.4845988 ]
 [ 0.06532937]]


After 0 training step(s), cross entropy on all data is 1.89805
After 1000 training step(s), cross entropy on all data is 0.655075
After 2000 training step(s), cross entropy on all data is 0.626172
After 3000 training step(s), cross entropy on all data is 0.615096
After 4000 training step(s), cross entropy on all data is 0.610309


[[ 0.02476983  0.56948674  1.6921941 ]
 [-2.1977348  -0.23668921  1.1143895 ]]
[[-0.45544702]
 [ 0.49110925]
 [-0.98110336]]
'''

6. TensorFlow实战之线性回归

用到的房价数据集,可以参考这篇简书
也可以直接用代码中的方法housing = fetch_california_housing()

正态方程解

根据这篇简书,线性回归的正态方程解为

正态方程的解

用TensorFlow实现求解:

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

tf.reset_default_graph()

housing = fetch_california_housing()
m, n = housing.data.shape
# 向所有训练实例添加一个额外的偏置输入特征( x0 = 1 )
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()

theta_value
'''
array([[-3.7185181e+01],
       [ 4.3633747e-01],
       [ 9.3952334e-03],
       [-1.0711310e-01],
       [ 6.4479220e-01],
       [-4.0338000e-06],
       [-3.7813708e-03],
       [-4.2348403e-01],
       [-4.3721911e-01]], dtype=float32)
'''


print(housing.DESCR)
'''
.. _california_housing_dataset:

California Housing dataset
--------------------------

**Data Set Characteristics:**

    :Number of Instances: 20640

    :Number of Attributes: 8 numeric, predictive attributes and the target

    :Attribute Information:
        - MedInc        median income in block
        - HouseAge      median house age in block
        - AveRooms      average number of rooms
        - AveBedrms     average number of bedrooms
        - Population    block population
        - AveOccup      average house occupancy
        - Latitude      house block latitude
        - Longitude     house block longitude

    :Missing Attribute Values: None
'''

Numpy实现:

X = housing_data_plus_bias
y = housing.target.reshape(-1, 1)
theta_numpy = np.linalg.inv(X.T.dot(X)).dot(X.T).dot(y)

print(theta_numpy)

Scikit-Learn实现

from sklearn.linear_model import LinearRegression
lin_reg = LinearRegression()
lin_reg.fit(housing.data, housing.target.reshape(-1, 1))

print(np.r_[lin_reg.intercept_.reshape(-1, 1), lin_reg.coef_.T])

梯度下降

首先归一化特征向量

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaled_housing_data = scaler.fit_transform(housing.data)
scaled_housing_data_plus_bias = np.c_[np.ones((m, 1)), scaled_housing_data]

手动计算梯度


X = tf.constant(scaled_housing_data_plus_bias, 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.0, 1.0, seed=42), name="theta")
y_pred = tf.matmul(X, theta, name="predictions")
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()
'''
Epoch 0 MSE = 9.161542
Epoch 100 MSE = 0.7145004
Epoch 200 MSE = 0.56670487
Epoch 300 MSE = 0.5555718
Epoch 400 MSE = 0.5488112
Epoch 500 MSE = 0.5436363
Epoch 600 MSE = 0.5396291
Epoch 700 MSE = 0.5365092
Epoch 800 MSE = 0.53406775
Epoch 900 MSE = 0.5321473
'''
best_theta
'''
array([[ 2.0685523 ],
       [ 0.8874027 ],
       [ 0.14401656],
       [-0.34770882],
       [ 0.36178368],
       [ 0.00393811],
       [-0.04269556],
       [-0.6614529 ],
       [-0.6375279 ]], dtype=float32)
'''

利用tf.gradients自动计算梯度

reset_graph()

n_epochs = 1000
learning_rate = 0.01

X = tf.constant(scaled_housing_data_plus_bias, 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.0, 1.0, seed=42), name="theta")
y_pred = tf.matmul(X, theta, name="predictions")
error = y_pred - y
mse = tf.reduce_mean(tf.square(error), name="mse")
'''
tensorflow计算梯度使用的是反向模式 reverse-mode autodiff
    gradients()函数使用一个   op(在这种情况下是MSE)和一个变量列表(在这种情况下只 是 theta),
它创建一个ops列表(每个变量一个)来计算op的梯度变量。   
因此,梯度节 点将计算 MSE相对于theta的梯度向量
'''
gradients = tf.gradients(mse, [theta])[0]  

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()

print("Best theta:")
print(best_theta)
'''
Epoch 0 MSE = 9.161542
Epoch 100 MSE = 0.71450037
Epoch 200 MSE = 0.56670487
Epoch 300 MSE = 0.5555718
Epoch 400 MSE = 0.54881126
Epoch 500 MSE = 0.5436363
Epoch 600 MSE = 0.53962916
Epoch 700 MSE = 0.5365092
Epoch 800 MSE = 0.53406775
Epoch 900 MSE = 0.5321473
Best theta:
[[ 2.0685523 ]
 [ 0.8874027 ]
 [ 0.14401656]
 [-0.3477088 ]
 [ 0.36178365]
 [ 0.00393811]
 [-0.04269556]
 [-0.66145283]
 [-0.6375278 ]]
'''

TensorFlow梯度优化器
tf.train.GradientDescentOptimizer
tf.train.MomentumOptimizer

reset_graph()

n_epochs = 1000
learning_rate = 0.01

X = tf.constant(scaled_housing_data_plus_bias, 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.0, 1.0, seed=42), name="theta")
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)
# optimizer = tf.train.MomentumOptimizer(learning_rate=learning_rate, momentum=0.9)
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()

print("Best theta:")
print(best_theta)
'''
Epoch 0 MSE = 9.161542
Epoch 100 MSE = 0.7145004
Epoch 200 MSE = 0.56670487
Epoch 300 MSE = 0.5555718
Epoch 400 MSE = 0.54881126
Epoch 500 MSE = 0.5436363
Epoch 600 MSE = 0.53962916
Epoch 700 MSE = 0.5365092
Epoch 800 MSE = 0.53406775
Epoch 900 MSE = 0.5321473
Best theta:
[[ 2.0685523 ]
 [ 0.8874027 ]
 [ 0.14401656]
 [-0.3477088 ]
 [ 0.36178365]
 [ 0.00393811]
 [-0.04269556]
 [-0.66145283]
 [-0.6375278 ]]
'''

将数据提供给训练算法

tf.placeholder本身不执行任何计算,只是输出数据,通常用于存放训练数据。下面实现以下小批量梯度下降。

learning_rate = 0.01

reset_graph()

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

theta = tf.Variable(tf.random_uniform([n + 1, 1], -1.0, 1.0, seed=42), name="theta")
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()

n_epochs = 10
batch_size = 100 # 定义批量大小
n_batches = int(np.ceil(m / batch_size)) # 计算总批次

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 = scaled_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()

best_theta
'''
array([[ 2.0703337 ],
       [ 0.8637145 ],
       [ 0.12255152],
       [-0.31211877],
       [ 0.38510376],
       [ 0.00434168],
       [-0.0123295 ],
       [-0.83376896],
       [-0.8030471 ]], dtype=float32)
'''

保存和恢复模型

在构造阶段结束(创建所有变量节点之后)创建一个保存节点tf.train.Saver(),在执行阶段调用它的 save() 方法

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")

在执行阶段的开始调用store()方法恢复数据

with tf.Session() as sess:
    saver.restore(sess, "tmp/my_model_final.ckpt")
    best_theta_restored = theta.eval()

save() 方法可以只保存想要的数据,下面这个例子保存了theta,并且键值为weights

saver = tf.train.Saver({"weights": theta})

保存器Saver默认会把计算图的结构保存在另外一个.meta文件中,可以通过tf.train.import_meta_graph()恢复计算图

reset_graph()
# notice that we start with an empty graph.

saver = tf.train.import_meta_graph("tmp/my_model_final.ckpt.meta")  # this loads the graph structure
theta = tf.get_default_graph().get_tensor_by_name("theta:0") 

使用 TensorBoard 展现计算图和训练曲线

除了上文可视化中提到的本地启动TensorBoard服务之外,也可以在jupyterlab中使用一个在线的TensorBoard服务,方法如下:

from tensorflow_graph_in_jupyter import show_graph
show_graph(tf.get_default_graph())
jupyterlab中的效果图

每次运行程序时都需要使用不同的日志目录,否则
TensorBoard 将会合并来自不同运行的统计信息,这将会混乱可视化。 最简单的解决方案是在日志目录名称中包含时间戳。

reset_graph()

from datetime import datetime

now = datetime.utcnow().strftime("%Y%m%d%H%M%S")
root_logdir = "tf_logs"
logdir = "{}/run-{}/".format(root_logdir, now)

接下来,在构建阶段结束时添加以下代码:

mse_summary = tf.summary.scalar('MSE', mse)
file_writer = tf.summary.FileWriter(logdir, tf.get_default_graph())

第一行创建一个节点,这个节点将求出 MSE 值并将其写入summary
完整代码:

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

housing = fetch_california_housing()
m, n = housing.data.shape
print("数据集:{}行,{}列".format(m, n))
housing_data_plus_bias = np.c_[np.ones((m, 1)), housing.data]

scaler = StandardScaler()
scaled_housing_data = scaler.fit_transform(housing.data)
scaled_housing_data_plus_bias = np.c_[np.ones((m, 1)), scaled_housing_data]

from datetime import datetime

now = datetime.utcnow().strftime("%Y%m%d%H%M%S")
root_logdir = r"D://tf_logs"
logdir = "{}/run-{}/".format(root_logdir, now)

n_epochs = 1000
learning_rate = 0.01
X = tf.placeholder(tf.float32, shape=(None, n + 1), name="X")
y = tf.placeholder(tf.float32, shape=(None, 1), name="y")
theta = tf.Variable(tf.random_uniform([n + 1, 1], -1.0, 1.0, seed=42), name="theta")
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()

mse_summary = tf.summary.scalar('MSE', mse)
file_writer = tf.summary.FileWriter(logdir, tf.get_default_graph())

n_epochs = 10
batch_size = 100
n_batches = int(np.ceil(m / batch_size))


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 = scaled_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})
    best_theta = theta.eval()

file_writer.close()
print(best_theta)

名称作用域 name scope

当处理更复杂的模型(如神经网络)时,该图可以很容易地与数千个节点混淆。 为了避免这种情况,可以创建名称作用域来对相关节点进行分组。

reset_graph()

a1 = tf.Variable(0, name="a")      # name == "a"
a2 = tf.Variable(0, name="a")      # name == "a_1"

with tf.name_scope("param"):       # name == "param"
    a3 = tf.Variable(0, name="a")  # name == "param/a"

with tf.name_scope("param"):       # name == "param_1"
    a4 = tf.Variable(0, name="a")  # name == "param_1/a"

for node in (a1, a2, a3, a4):
    print(node.op.name)
'''
a
a_1
param/a
param_1/a
'''

模块性

一段重复的代码如下:

n_features = 3
X = tf.placeholder(tf.float32, shape=(None, n_features), name="X")
w1 = tf.Variable(tf.random_normal((n_features, 1)), name="weights1")
w2 = tf.Variable(tf.random_normal((n_features, 1)), name="weights2")
b1 = tf.Variable(0.0, name="bias1")
b2 = tf.Variable(0.0, name="bias2")
z1 = tf.add(tf.matmul(X, w1), b1, name="z1")
z2 = tf.add(tf.matmul(X, w2), b2, name="z2")
relu1 = tf.maximum(z1, 0., name="relu1")
relu2 = tf.maximum(z2, 0., name="relu2")
output = tf.add(relu1, relu2, name="output")

用一个函数来构建ReLUs,add_n() 创建一个计算张量列表之和的操作。

def relu(X):
    w_shape = (int(X.get_shape()[1]), 1)
    w = tf.Variable(tf.random_normal(w_shape), name="weights")
    b = tf.Variable(0.0, name="bias")
    z = tf.add(tf.matmul(X, w), b, name="z")
    return tf.maximum(z, 0., name="relu")

n_features = 3
X = tf.placeholder(tf.float32, shape=(None, n_features), name="X")
relus = [relu(X) for i in range(5)]
output = tf.add_n(relus, name="output")

创建节点时,TensorFlow 将检查其名称是否已存在,如果它已经存在,则会附加一个下划线,后跟一个索引,以使该名称是唯一的。 因此,第一个 ReLU 包含名为 weights , bias , z 和 relu 的节点(加上其他默认名称的更多节点,如 MatMul ); 第二个 ReLU 包含名为 weights_1 , bias_1 等节点的节点; 第三个 ReLU 包含名为weights_2 , bias_2 的节点,依此类推。
利用name scope可以让计算图更清晰

reset_graph()

def relu(X):
    with tf.name_scope("relu"):
        w_shape = (int(X.get_shape()[1]), 1)                          
        w = tf.Variable(tf.random_normal(w_shape), name="weights")    
        b = tf.Variable(0.0, name="bias")                             
        z = tf.add(tf.matmul(X, w), b, name="z")                      
        return tf.maximum(z, 0., name="max")  

共享变量

使用get_variable() 函数,如果它还不存在,则创建共享变量,如果已经存在,则复用它。
以下代码将创建一个名为 relu/threshold 的变量

with tf.variable_scope("relu"):
    threshold = tf.get_variable("threshold", shape=(), initializer=tf.constant_initializer(0.0))

如果变量已经通过较早的 get_variable() 调用创建,则此代码将引发异常。 这种行为可以防止错误地复用变量。如果要复用变量,则需要通过将variable_scope的复用属性设置为True

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

推荐阅读更多精彩内容