Tensorflow 学习笔记

基础

创建常量

1
2
3
4
# 创建一个(1,2)维常量
m1 = tf.constant([[3,3]])
# 创建一个(2,1)常量
m2 = tf.constant([[2],[3]])

定义变量

1
2
# 定义一个(2,)形状的变量
x = tf.Variable([1,2])

运算

基本运算

1
2
3
4
5
6
# 矩阵乘法op,m1,m2为可相乘的张量,product为结果张量
product = tf.matmul(m1, m2)
# 矩阵加法op,x+y,add为结果张量,x和y的张量维度要一致
add = tf.add(x, y)
# 矩阵减法op,x-y,sub为结果张量,x和y的张量维度要一致
sub = tf.subtract(x, y)

逻辑运算

1
2
3
4
5
6
7
8
# 返回input在axis所在维度上的最大值坐标
tf.argmax(input_tensor, axis=None)
# 判断x和y的值是否相等,返回一个bool类型的张量
tf.equal(x, y)
# 将张量x的元素类型转化为dtype型
tf.cast(x, dtype)
# 计算input_tensor在axis维度上的均值,若axis默认为None,计算所有维度
tf.reduce_mean(input_tensor, axis=None)

所有变量初始化

1
2
# 在会话中必须要执行的第一步
init = tf.global_variables_initializer()

创建会话

1
2
3
4
5
6
7
8
9
10
## 第一种方式
sess = tf.Session() # 定义会话
result = sess.run(product) # 调用sess中的run方法来执行矩阵乘法op
print(result) # 打印结果
sess.close() # 结束回话

## 第二种方式
with tf.Session() as sess:
result = sess.run(product) # 调用sess中的run方法来执行矩阵乘法op
print(result)

Fetch & Feed

Fetch: 可以在session中同时计算多个tensor或执行多个操作

1
2
3
4
5
6
7
8
9
10
11
12
# 定义三个常量
input1 = tf.constant(3.0)
input2 = tf.constant(2.0)
input3 = tf.constant(5.0)
# 加法op
add = tf.add(input2,input3)
# 乘法op
mul = tf.multiply(input1, add)

with tf.Session() as sess:
result1, result2 = sess.run([mul, add])
print(result1,result2)

Feed: 先定义占位符,等需要的时候再传入数据

1
2
3
4
5
6
7
8
# 定义两个tensor,不传入数据
input1 = tf.placeholder(tf.float32)
input2 = tf.placeholder(tf.float32)
# 乘法op
output = tf.multiply(input1, input2)

with tf.Session() as sess:
print(sess.run(output, feed_dict={input1:8.0,input2:2.0}))

神经网络

变量初始化器

随机数生成函数

  • tf.random_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32)
  • tf.truncated_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32)
  • tf.random_uniform(shape, minval=0, maxval=None, dtype=tf.float32)
  • tf.random_gamma(shape, alpha, beta=None, dtype=tf.float32)
    与 tf.Variable() 配合使用

变量初始化函数

  • tf.constant_initializer(value=0, dtype=tf.float32)
  • tf.random_normal_initializer(mean=0.0, stddev=1.0, dtype=tf.float32)
  • tf.truncated_normal_initializer(mean=0.0, stddev=1.0, dtype=tf.float32)
  • tf.random_uniform_initializer(minval=0, maxval=None, dtype=tf.float32)
  • tf.ones_initializer()
  • tf.zeros_initializer()
    与 tf.get_variable() 配合使用

常数生成函数

  • tf.ones(shape, dtype=tf.float32)
  • tf.zeros(shape, dtype=tf.float32)
  • tf.fill(dims, value)
  • tf.constant(value, dtype=None, shape=None)
1
2
3
4
5
6
7
8
# 生成全1张量,shape为张量形状
tf.ones(shape)
# 生成全0张量,shape为张量形状
tf.zeros(shape)
# 生成随机正态分布,shape为张量形状
initial = tf.random_normal(shape)
# 生成一个截断的正态分布,shape为张量形状
initial = tf.truncated_normal(shape, stddev=0.1)

以函数的形式定义变量的初始化

1
2
3
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=0.1) # 生成一个截断的正态分布
return tf.Variable(initial)

激活函数

01_activation

1
2
3
# tensor为需要激活的神经元
tanh = tf.nn.tanh(tensor)
relu = tf.nn.relu(tensor)

损失函数

1
2
3
4
5
# 二次代价函数,y_actual为真实值,y_predict为预测值
loss = tf.losses.mean_squared_error(y_actual, y_predict)
# 交叉熵
loss = tf.losses.sigmoid_cross_entropy(y_actual, y_predict) # 用于激活函数sigmoid的结果
loss = tf.losses.softmax_cross_entropy(y_actual, y_predict) # 用于softmax的结果

防止过拟合

Dropout

1
2
# 定义L1层神经元按比例失活,失活比例为keep_prob
L1_drop = tf.nn.dropout(L1, keep_prob)

keep_prob建议使用占位符方式传入

正则化

1
2
3
4
5
6
# L1正则项损失
l1_loss = tf.nn.l1_loss(W) + tf.nn.l1_loss(b)
# L2正则项损失
l2_loss = tf.nn.l2_loss(W) + tf.nn.l2_loss(b)
# 将正则化损失加入loss,0.0005为正则化参数
loss = tf.losses.softmax_cross_entropy(y,prediction) + 0.0005*l2_loss

由于偏置项b较权重W而言,参数少很多,在计算正则化时可以不予考虑

优化器

优化器列表

  • tf.train.GradientDescentOptimizer
  • tf.train.AdadeltaOptimizer
  • tf.train.AdagradOptimizer
  • tf.train.AdagradDAOptimizer
  • tf.train.MomentumOptimizer
  • tf.train.FtrlOptimizer
  • tf.train.ProximalGradientDescentOptimizer
  • tf.train.ProximalAdagradOptimizer
  • tf.train.RMSPropOptimizer
1
2
3
4
5
6
# 定义一个梯度下降法优化器,η为学习率,一般取值0.01
optimizer = tf.train.GradientDescentOptimizer(η)
# 定义Adam优化器,η为学习率,一般取值0.001
optimizer = tf.train.AdamOptimizer(η)
# 最小化代价函数
train = optimizer.minimize(loss)

一般情况下Adam优化器比梯度下降优化器的学习率取值小,Adam优化器也是一个整体性能较优的优化器,如果不知道如何选择优化器,可以首先考虑Adam

其他优化器

1
2
optimizer = tf.train.GradientDescentOptimizer(η)
optimizer = tf.train.AdamOptimizer(η)

图片预处理

图像解码

在图片预处理之前,需要将图片读取为张量的形式

1
2
3
4
5
6
# 读取图片,其中filename为图片完整路径
image = tf.read_file(filename)
# 效果同上
image = tf.gfile.FastGFile(filename, 'rb').read()
# 将图像解码,或者tf.image.decode_png
image = tf.image.decode_jpeg(image, channels=3)

注:解码函数根据图像格式的选取有所不同

读取图片为张量后,将其数值进行调整

1
2
3
4
5
6
# 将 0~255 的像素转化为 0.0~1.0 范围内的实数
image = tf.image.convert_image_dtype(image, dtype=tf.float32)
# 下述三步骤同上述步骤效果
image = tf.cast(image, tf.float32) / 255.0
image = tf.subtract(image, 0.5)
image = tf.multiply(image, 2.0)

图像大小调整

1
2
# 调整图像大小,method有四中模式,可取值0,1,2,3
image = tf.image.resize_images(image, [300, 300], method=1)

图像大小调整 tensorflow.image.resize_images 提供四种模式选择

  • 0:双线性插值
  • 1:最近邻居法
  • 2:双三次插值法
  • 3:面积插值法

先看原始图片:
02_resize

各种方法的对比结果:
03_resize

1
2
3
# 通过tf.image.resize_image_with_crop_or_pad函数调整图像大小
croped = tf.image.resize_image_with_crop_or_pad(image, 1500, 1500)
padded = tf.image.resize_image_with_crop_or_pad(image, 3500, 3500)

该函数有三个参数,images 表示原始图像,target_height 表示调整后目标图像高度,target_width 表示调整后目标图像宽度。如果原始图像尺寸大于目标图像,那么这个函数会自动截取原始图像居中的部分;反之,函数会自动在原始图像的四周填充全0背景。

输出结果:

04_crop_pad

图像裁减

1
2
通过tf.image.central_crop函数按比例裁减图像
central_cropped = tf.image.central_crop(image, 0.5)

该函数有两个参数,images 表示原始图像,central_fraction 表示调整比例。按比例裁减图像,参数 central_fraction 是一个介于 (0,1] 之间的实数,该函数也是自动截取中心部分。

输出结果:

05_central_crop

1
2
3
4
# 通过tf.image.crop_to_bounding_box裁减图像
crop_to = tf.image.crop_to_bounding_box(image, 500, 500, 1000, 1000)
# 通过tf.image.pad_to_bounding_box裁减图像
pad_to = tf.image.pad_to_bounding_box(image, 0, 0, 3500, 3500)

上述两个函数五参数相同,分别为:images 表示原始图像,offset_height 表示距离上边高度,offset_width 表示距离左边宽度,target_height 表示目标图像高度,target_width 表示目标图像宽度。

crop_to_bounding_box 要求原始图像尺寸大于目标图像, pad_to_bounding_box 要求原始图像尺寸小于目标图像,并按照 offset_h / offset_w 的值截取或填充原始图像。

输出结果:

06_bounding_box

图片翻转

1
2
3
4
5
6
7
8
9
# 上下翻转
flipped_up_down = tf.image.flip_up_down(image)
# 左右翻转
flipped_left_right = tf.image.flip_left_right(image)
# 沿对角线翻转
transposed = tf.image.transpose_image(image)
# 以50%的概率对图像上下翻转,左右翻转
flipped = tf.image.random_flip_up_down(image)
flipped = tf.image.random_flip_left_right(image)

在很多图像识别问题中,图像的翻转不应该影响识别的结果。于是在训练神经网络模型时,可随机翻转训练图像,这样训练得到的模型可以识别不同角度的实体。

输出结果:

07_flipped

图片色彩调整

亮度

1
2
3
4
5
# 将图像亮度-0.5,并截断取值之0~1之间
adjusted = tf.image.adjust_brightness(image, -0.5)
adjusted = tf.clip_by_value(adjusted, 0.0, 1.0)
# 在[-max_delta, max_delta]范围内随机调整图像亮度
adjusted = tf.image.random_brightness(image, max_delta)

函数 tf.image.adjust_brightness 包含两个参数, images 表示原始图像, delta 表示亮度大小。 delta 绝对值的范围应该在 [0,1) 之内色彩调整的API可能导致像素的实数值超出 0~1 的范围,所以要用上述第二个函数,将取值截断。否则不仅图像无法可视化,输入的神经网络训练质量也会受到影响。

08_bright

对比度

1
2
3
4
# 将图像的对比度减少到0.5倍或增加5倍
adjusted = tf.image.adjust_contrast(image, 5)
# 在[lower, upper]的范围内随机调整图的对比度
adjusted = tf.image.random_contrast(image, lower, upper)

函数 tf.image.adjust_contrast 包含两个参数, images 表示原始图像, contrast_factor 表示对比度调整参数。

对比度的调整,官方文档解释如下:

For each channel, this Op computes the mean of the image pixels in the channel and then adjusts each component x of each pixel to (x - mean) * contrast_factor + mean

输出结果:

09_contrast

色相

1
2
3
4
# 将图像的色相相加一个值,调整值在[-1, 1]之间
adjusted = tf.image.adjust_hue(img_data, 0.6)
# 在[-max_delta, max_delta]的范围内随机调整图像的色相,max_delta的取值在[0, 0.5]之间
adjusted = tf.image.random_hue(image, max_delta)

函数 tf.image.adjust_hue 包含两个参数, images 表示原始图像, delta 表示增加的色相大小。

色相的调整,官方文档解释如下:

image is an RGB image. The image hue is adjusted by converting the image to HSV and rotating the hue channel (H) by delta. The image is then converted back to RGB.

输出结果:

10_hue

饱和度

1
2
3
4
# 将图像的饱和度-5或+5
adjusted = tf.image.adjust_saturation(img_data, 5)
# 在[lower, upper]的范围内随机调整图的饱和度
adjusted = tf.image.random_saturation(image, lower, upper)

函数 tf.image.adjust_saturation 包含两个参数, images 表示原始图像, saturation_factor 表示饱和度调整参数。

饱和度的调整,官方文档解释如下:

image is an RGB image. The image saturation is adjusted by converting the image to HSV and multiplying the saturation (S) channel by saturation_factor and clipping. The image is then converted back to RGB.

输出结果:

11_saturation

图像预处理完整样例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

#### 1. 随机调整图片的色彩,定义两种顺序。
def distort_color(image, color_ordering=0):
if color_ordering == 0:
image = tf.image.random_brightness(image, max_delta=32./255.)
image = tf.image.random_saturation(image, lower=0.5, upper=1.5)
image = tf.image.random_hue(image, max_delta=0.2)
image = tf.image.random_contrast(image, lower=0.5, upper=1.5)
else:
image = tf.image.random_saturation(image, lower=0.5, upper=1.5)
image = tf.image.random_brightness(image, max_delta=32./255.)
image = tf.image.random_contrast(image, lower=0.5, upper=1.5)
image = tf.image.random_hue(image, max_delta=0.2)

return tf.clip_by_value(image, 0.0, 1.0)

#### 2. 对图片进行预处理,将图片转化成神经网络的输入层数据。
def preprocess_for_train(image, height, width, bbox):
# 查看是否存在标注框。
if bbox is None:
bbox = tf.constant([0.0, 0.0, 1.0, 1.0], dtype=tf.float32, shape=[1, 1, 4])
if image.dtype != tf.float32:
image = tf.image.convert_image_dtype(image, dtype=tf.float32)

# 随机的截取图片中一个块。
bbox_begin, bbox_size, _ = tf.image.sample_distorted_bounding_box(
tf.shape(image), bounding_boxes=bbox, min_object_covered=0.4)
bbox_begin, bbox_size, _ = tf.image.sample_distorted_bounding_box(
tf.shape(image), bounding_boxes=bbox, min_object_covered=0.4)
distorted_image = tf.slice(image, bbox_begin, bbox_size)

# 将随机截取的图片调整为神经网络输入层的大小。
distorted_image = tf.image.resize_images(distorted_image, [height, width], method=np.random.randint(4))
distorted_image = tf.image.random_flip_left_right(distorted_image)
distorted_image = distort_color(distorted_image, np.random.randint(2))
return distorted_image

#### 3. 读取图片。
image_raw_data = tf.gfile.FastGFile("../../datasets/cat.jpg", "rb").read()
with tf.Session() as sess:
img_data = tf.image.decode_jpeg(image_raw_data)
boxes = tf.constant([[[0.05, 0.05, 0.9, 0.7], [0.35, 0.47, 0.5, 0.56]]])
for i in range(9):
result = preprocess_for_train(img_data, 299, 299, boxes)
plt.imshow(result.eval())
plt.show()

卷积神经网络 CNN

定义卷积层

1
2
# 定义一层卷积层神经网络,input为输入数据,filter为滤波器即权重,strides步长为1,padding可以取'SAME'和'VALID'
conv2d = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='SAME')

定义池化层

1
2
# 定义一层池化层神经网络,value为输入数据,ksize为池化窗口大小,strides步长为2,padding可以取'SAME'和'VALID'
max_pool = tf.nn.max_pool(value, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')

循环神经网络 RNN

LSTM

1
2
3
4
5
6
7
8
9
10
# 初始化输出层权值
weights = tf.Variable(tf.truncated_normal([lstm_size, n_classes], stddev=0.1))
# 初始化输出层偏置值
biases = tf.Variable(tf.constant(0.1, shape=[n_classes]))
# 定义一个LSTM单元,lstm_hidden_size为隐藏层节点数
lstm_cell = tf.nn.rnn_cell.LSTMCell(lstm_hidden_size)
# 每一步处理时间序列的时刻,inputs为输入,outputs包含了所有时刻的输出h_t,final_state最后一个时刻的输出c_t和h_t
outputs, final_state = tf.nn.dynamic_rnn(lstm_cell, inputs, dtype=tf.float32)
# 计算最后的结果
results = tf.nn.softmax(tf.matmul(final_state[1], weights) + biases)

模型的保存与载入

使用tensorflow过程中,训练结束后我们需要用到模型文件。有时候,我们可能也需要用到别人训练好的模型,并在这个基础上再次训练。这时候我们需要掌握如何操作这些模型数据。看完本文,相信你一定会有收获!

Tensorflow模型文件

我们在checkpoint_dir目录下保存的文件结构如下:

1
2
3
4
5
--checkpoint_dir
| |--checkpoint
| |--MyModel.meta
| |--MyModel.data-00000-of-00001
| |--MyModel.index

meta文件

MyModel.meta文件保存的是图结构,meta文件是pb(protocol buffer)格式文件,包含变量、op、集合等。

ckpt文件

ckpt文件是二进制文件,保存了所有的weights、biases、gradients等变量。在tensorflow 0.11之前,保存在.ckpt文件中。0.11后,通过两个文件保存,如:

1
2
MyModel.data-00000-of-00001
MyModel.index

checkpoint文件

我们还可以看,checkpoint_dir目录下还有checkpoint文件,该文件是个文本文件,里面记录了保存的最新的checkpoint文件以及其它checkpoint文件列表。在inference时,可以通过修改这个文件,指定使用哪个model。

保存Tensorflow模型

tensorflow 提供了 tf.train.Saver 类来保存模型,值得注意的是,在tensorflow中,变量是存在于Session环境中,也就是说,只有在Session环境下才会存有变量值,因此,保存模型时需要传入session:

1
2
saver = tf.train.Saver()
saver.save(sess,"./checkpoint_dir/MyModel")

上面第二句写入会话中,执行后,在checkpoint_dir目录下创建模型文件如下:

1
2
3
4
checkpoint
MyModel.data-00000-of-00001
MyModel.index
MyModel.meta

另外,如果想要在1000次迭代后,再保存模型,只需设置global_step参数即可:

1
saver.save(sess, './checkpoint_dir/MyModel', global_step=1000)

保存的模型文件名称会在后面加-1000,如下:

1
2
3
4
checkpoint
MyModel-1000.data-00000-of-00001
MyModel-1000.index
MyModel-1000.meta

在实际训练中,我们可能会在每1000次迭代中保存一次模型数据,但是由于图是不变的,没必要每次都去保存,可以通过如下方式指定不保存图:

1
saver.save(sess, './checkpoint_dir/MyModel', global_step=step, write_meta_graph=False)

另一种比较实用的是,如果你希望每2小时保存一次模型,并且只保存最近的5个模型文件:

1
tf.train.Saver(max_to_keep=5, keep_checkpoint_every_n_hours=2)

如果我们不对tf.train.Saver指定任何参数,默认会保存所有变量。如果你不想保存所有变量,而只保存一部分变量,可以通过指定variables/collections。在创建tf.train.Saver实例时,通过将需要保存的变量构造list或者dictionary,传入到Saver中:

1
2
3
4
5
6
w1 = tf.Variable(tf.random_normal(shape=[2]), name='w1')
w2 = tf.Variable(tf.random_normal(shape=[5]), name='w2')
saver = tf.train.Saver([w1,w2])
sess = tf.Session()
sess.run(tf.global_variables_initializer())
saver.save(sess, './checkpoint_dir/MyModel', global_step=1000)

导入训练好的模型

在第1小节中我们介绍过,tensorflow将图和变量数据分开保存为不同的文件。因此,在导入模型时,也要分为2步:构造网络图和加载参数

构造网络图

一个比较笨的方法是,手敲代码,实现跟模型一模一样的图结构。其实,我们既然已经保存了图,那就没必要在去手写一次图结构代码。

1
saver=tf.train.import_meta_graph('./checkpoint_dir/MyModel-1000.meta')

上面一行代码,就把图加载进来了

加载参数

仅仅有图并没有用,更重要的是,我们需要前面训练好的模型参数(即weights、biases等),本文第2节提到过,变量值需要依赖于Session,因此在加载参数时,先要构造好Session:

1
2
3
4
5
with tf.Session() as sess:
# 保存模型结构
saver = tf.train.import_meta_graph('./checkpoint_dir/MyModel-1000.meta')
# 加载模型参数
saver.restore(sess,tf.train.latest_checkpoint('./checkpoint_dir'))

使用恢复的模型

前面我们理解了如何保存和恢复模型,很多时候,我们希望使用一些已经训练好的模型,如prediction、fine-tuning以及进一步训练等。这时候,我们可能需要获取训练好的模型中的一些中间结果值,可以通过graph.get_tensor_by_name(‘w1:0’)来获取,注意w1:0是tensor的name。

假设我们有一个简单的网络模型,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

# 载入数据集
mnist = input_data.read_data_sets("MNIST_data", one_hot=True)

# 批次大小
batch_size = 64
# 计算一个周期一共有多少个批次
n_batch = mnist.train.num_examples // batch_size

# 定义两个placeholder
x = tf.placeholder(tf.float32,[None,784], name='x_input')
y = tf.placeholder(tf.float32,[None,10], name='y_input')

# 创建一个简单的神经网络:784-10
W = tf.Variable(tf.truncated_normal([784,10], stddev=0.1))
b = tf.Variable(tf.zeros([10]) + 0.1)
prediction = tf.nn.softmax(tf.matmul(x,W)+b, name='output')

# 二次代价函数
loss = tf.losses.mean_squared_error(y, prediction)
# 使用梯度下降法
train = tf.train.AdamOptimizer(0.001).minimize(loss, name='train')

# 结果存放在一个布尔型列表中
correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(prediction,1))
# 求准确率
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32), name='accuracy')

#创建一个Saver对象,用于保存所有变量
saver = tf.train.Saver()

with tf.Session() as sess:
# 变量初始化
sess.run(tf.global_variables_initializer())
# 周期epoch:所有数据训练一次,就是一个周期
for epoch in range(21):
for batch in range(n_batch):
# 获取一个批次的数据和标签
batch_xs,batch_ys = mnist.train.next_batch(batch_size)
sess.run(train,feed_dict={x:batch_xs,y:batch_ys})
# 每训练一个周期做一次测试
acc = sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels})
print("Iter " + str(epoch) + ",Testing Accuracy " + str(acc))
saver.save(sess, './checkpoint_dir/MyModel', global_step=1000)

接下来我们使用graph.get_tensor_by_name()方法来操纵这个保存的模型。用graph.get_tensor_by_name()方法来获取之前模型定义的操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

# 载入数据集
mnist = input_data.read_data_sets("MNIST_data", one_hot=True)

# 批次大小
batch_size = 64
# 计算一个周期一共有多少个批次
n_batch = mnist.train.num_examples // batch_size

with tf.Session() as sess:
# 载入模型结构
saver = tf.train.import_meta_graph('./checkpoint_dir/MyModel-1000.meta')
# 载入模型参数
saver.restore(sess, tf.train.latest_checkpoint('./checkpoint_dir'))
# 根据tensor的名字获取对应的tensor
output = sess.graph.get_tensor_by_name("output:0")
# 之前模型保存时的准确率计算
accuracy = sess.graph.get_tensor_by_name("accuracy:0")
# 之前模型保存时模型训练保存为train
train = sess.graph.get_operation_by_name("train")

# 把测试数据喂到网络中计算准确率
# 'x_input'是模型数据的输入,'y_input'是模型标签的输入
print(sess.run(accuracy,feed_dict={'x_input:0':mnist.test.images, 'y_input:0':mnist.test.labels}))

# 周期epoch:所有数据训练一次,就是一个周期
for epoch in range(21):
for batch in range(n_batch):
# 获取一个批次的数据和标签
batch_xs,batch_ys = mnist.train.next_batch(batch_size)
sess.run(train,feed_dict={'x_input:0':batch_xs, 'y_input:0':batch_ys})
# 每训练一个周期做一次测试
acc = sess.run(accuracy, feed_dict={'x_input:0':mnist.test.images, 'y_input:0':mnist.test.labels})
print("Iter " + str(epoch) + ",Testing Accuracy " + str(acc))

注意:保存模型时,只会保存变量的值,placeholder里面的值不会被保存。若没有./checkpoint_dir/MyModel-1000.meta文件,则需要手动编写模型结构代码。

第二种保存Tensorflow模型方式

模型训练好后,直接在Session的最后写入:

1
2
3
4
5
6
# 保存模型参数和结构,把变量变成常量
# output_node_names设置可以输出tensor
output_graph_def = tf.graph_util.convert_variables_to_constants(sess, sess.graph_def, output_node_names=['output', 'accuracy'])
# 保存模型到目录的models文件夹
with tf.gfile.FastGFile('pb_models/my_model.pb', mode='wb') as f:
f.write(output_graph_def.SerializeToString())

第二种模型载入方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 载入数据集
mnist = input_data.read_data_sets("MNIST_data", one_hot=True)

# 载入模型
with tf.gfile.FastGFile('pb_models/my_model.pb', 'rb') as f:
# 创建一个图
graph_def = tf.GraphDef()
# 把模型文件载入到图中
graph_def.ParseFromString(f.read())
# 载入图到当前环境中
tf.import_graph_def(graph_def, name='')

with tf.Session() as sess:
# 根据tensor的名字获取对应的tensor
output = sess.graph.get_tensor_by_name("output:0")
# 之前模型保存时的准确率计算
accuracy = sess.graph.get_tensor_by_name("accuracy:0")
# 之前模型保存时模型训练保存为train

# 把测试数据喂到网络中计算准确率
# 'x_input'是模型数据的输入,'y_input'是模型标签的输入
print(sess.run(accuracy,feed_dict={'x_input:0':mnist.test.images, 'y_input:0':mnist.test.labels}))

第二种模型载入方式,比较简单,但是由于载入的常量,所以模型只能用于做预测,而不能用来做训练。

Tensorbord

网络结构

记录数据

参考链接

官网:https://www.tensorflow.org/api_docs/python/tf

坚持原创技术分享,您的支持将鼓励我继续创作!