tutorial_cifar10_tfrecord.py解读

把Github上TensorLayer的示例——tutorial_cifar10_tfrecord.py看了一下,做了一些中文注解,在此分享一下,方便学习Tensorflow的童鞋们快速了解之。针对TF r0.12的情况,将源代码做了相应的改动。
win10_x64 + Python3.5 + CUDA8.0 + Cudnn5.1环境下运行正常。

#! /usr/bin/python
# -*- coding: utf8 -*-


import tensorflow as tf
import tensorlayer as tl
# from tensorlayer.layers import set_keep
import numpy as np
import time
from PIL import Image
import os
import io

"""重现 TensorFlow 官方 CIFAR-10 卷积神经网络 指导书:
- 该模型有 1,068,298 个参数, 使用GPU训练数小时后准确率可达86%.

描述
-----------
图片作如下处理:
.. 图片被裁剪为 24 x 24 像素, 集中评估或随机训练.
.. 为使模型对动态范围不敏感,图片被近似白化.

为了改善训练效果,我们还对图片应用了一系列的随机变换来人为地增加数据集的大小:
.. 随机左右翻转.
.. 随机改变图片亮度.
.. 随机改变图片对比度.

加速
--------
从磁盘读取图像并进行变换耗费了不短的处理时间。为减轻这些操作对训练速度的影响,
我们在16个独立的线程运行,不断填补tensorflow队列
"""
model_file_name = r"W:\cifar10\models\model_cifar10_advanced.ckpt" # win10下自定义的model和checkpoint文件保存位置
resume = False  # 载入已存在的模型, 从之前的checkpoint重新开始吗?

## 下载数据集, 并转化为TFRecord格式
X_train, y_train, X_test, y_test = tl.files.load_cifar10_dataset(
    shape=(-1, 32, 32, 3), plotable=False)

X_train = np.asarray(X_train, dtype=np.float32)
y_train = np.asarray(y_train, dtype=np.int64)
X_test = np.asarray(X_test, dtype=np.float32)
y_test = np.asarray(y_test, dtype=np.int64)

print('X_train.shape', X_train.shape)  # (50000, 32, 32, 3)
print('y_train.shape', y_train.shape)  # (50000,)
print('X_test.shape', X_test.shape)  # (10000, 32, 32, 3)
print('y_test.shape', y_test.shape)  # (10000,)
print('X %s   y %s' % (X_test.dtype, y_test.dtype))


def data_to_tfrecord(images, labels, filename): # 定义格式转化函数(转化为TFRecord格式)
    """ 将数据转化为TFRecord格式 """
    print("Converting data into %s ..." % filename)
    cwd = os.getcwd() # 获取当前目录路径
    writer = tf.python_io.TFRecordWriter(filename) # 创建TFRecord格式文件
    for index, img in enumerate(images):
        img_raw = img.tobytes() # 将numpy数组类型的图像转化为bytes类型
        ## 可视化一张图像
        # tl.visualize.frame(np.asarray(img, dtype=np.uint8), second=1, saveable=False, name='frame', fig_idx=1236)
        label = int(labels[index])
        # print(label)
        ## 将bytes格式文件转换回图像的操作如下:
        # image = Image.frombytes('RGB', (32, 32), img_raw)
        # image = np.fromstring(img_raw, np.float32)
        # image = image.reshape([32, 32, 3])
        # tl.visualize.frame(np.asarray(image, dtype=np.uint8), second=1, saveable=False, name='frame', fig_idx=1236)
        example = tf.train.Example(features=tf.train.Features(feature={
            "label": tf.train.Feature(int64_list=tf.train.Int64List(value=[label])),
            'img_raw': tf.train.Feature(bytes_list=tf.train.BytesList(value=[img_raw])),
        }))
        writer.write(example.SerializeToString())  # Serialize To String
    writer.close() # 关闭文件


def read_and_decode(filename, is_train=None):
    """ 从TFRecord文件读取并返回tensor """
    filename_queue = tf.train.string_input_producer([filename])
    reader = tf.TFRecordReader()
    _, serialized_example = reader.read(filename_queue)
    features = tf.parse_single_example(serialized_example,
                                       features={
                                           'label': tf.FixedLenFeature([], tf.int64),
                                           'img_raw': tf.FixedLenFeature([], tf.string),
                                       })
    # You can do more image distortion here for training data
    img = tf.decode_raw(features['img_raw'], tf.float32)
    img = tf.reshape(img, [32, 32, 3])
    # img = tf.cast(img, tf.float32) #* (1. / 255) - 0.5
    if is_train == True:
        # 1. 随机裁剪图像中[height, width] 的一部分.
        img = tf.random_crop(img, [24, 24, 3])
        # 2. 随机水平翻转.
        img = tf.image.random_flip_left_right(img)
        # 3. 随机改变亮度.
        img = tf.image.random_brightness(img, max_delta=63)
        # 4. 随机改变对比度.
        img = tf.image.random_contrast(img, lower=0.2, upper=1.8)
        # 5. 标准化(去均值,除方差).
        img = tf.image.per_image_standardization(img)
    elif is_train == False:
        # 1. 裁剪图片中央的[height, width]部分.
        img = tf.image.resize_image_with_crop_or_pad(img, 24, 24)
        # 2. 标准化(去均值,除方差).
        img = tf.image.per_image_standardization(img)
    elif is_train == None:
        img = img

    label = tf.cast(features['label'], tf.int32)
    return img, label


data_to_tfrecord(images=X_train, labels=y_train, filename="train.cifar10")
data_to_tfrecord(images=X_test, labels=y_test, filename="test.cifar10")

## 数据可视化举例
# img, label = read_and_decode("train.cifar10", None)
# img_batch, label_batch = tf.train.shuffle_batch([img, label],
#                                                 batch_size=4,
#                                                 capacity=50000,
#                                                 min_after_dequeue=10000,
#                                                 num_threads=1)
# print("img_batch   : %s" % img_batch._shape)
# print("label_batch : %s" % label_batch._shape)
#
# init = tf.global_variables_initializer() # 定义初始化graph中所有变量的op
# with tf.Session() as sess: # 开启会话
#     sess.run(init) # 变量初始化
#     coord = tf.train.Coordinator() # 创建一个线程协调器
#     threads = tf.train.start_queue_runners(sess=sess, coord=coord) # 创建线程
#
#     for i in range(3):  # number of mini-batch (step)
#         print("Step %d" % i)
#         val, l = sess.run([img_batch, label_batch])
#         # exit()
#         print(val.shape, l)
#         tl.visualize.images2d(val, second=1, saveable=False, name='batch'+str(i), dtype=np.uint8, fig_idx=2020121)
#
#     coord.request_stop() # 请求终止所有线程
#     coord.join(threads) # 等待所有线程终止
#     sess.close()

# with tf.device('/gpu:1'): # 使用GPU1
# sess = tf.InteractiveSession() # 开启交互式会话



batch_size = 128 # 设置batch大小

with tf.device('/cpu:0'): # 使用CPU0
    # 定义会话,为了避免指定的设备不存在的情况,allow_soft_placement设为True可以使程序自动选择一个存在并且支持的设备来运行op
    sess = tf.Session(config=tf.ConfigProto(allow_soft_placement=True))
    # 准备数据
    x_train_, y_train_ = read_and_decode("train.cifar10", True)
    x_test_, y_test_ = read_and_decode("test.cifar10", False)

    x_train_batch, y_train_batch = tf.train.shuffle_batch([x_train_, y_train_],
                                                          batch_size=batch_size,
                                                          capacity=2000,
                                                          min_after_dequeue=1000,
                                                          num_threads=32)  # 这里设置线程数
    # 测试时, 使用 batch 替代 shuffle_batch
    x_test_batch, y_test_batch = tf.train.batch([x_test_, y_test_],
                                                batch_size=batch_size,
                                                capacity=50000,
                                                num_threads=32)


    def inference(x_crop, y_, reuse):
        with tf.variable_scope("model", reuse=reuse): # 开启一个scope(作用域),指定可否复用
            tl.layers.set_name_reuse(reuse) # 允许layer名称复用,当你想要两个或多个input placeholder(inference)共享相同的模型参数时
            network = tl.layers.InputLayer(x_crop, name='input_layer') # 定义输入层
            network = tl.layers.Conv2dLayer(network,  # 定义卷积层
                                            act=tf.nn.relu, # 定义激活函数,使用relu函数
                                            shape=[5, 5, 3, 64],  # 卷积核的shape:[高度, 宽度, 输入通道数, 输出通道数]
                                            strides=[1, 1, 1, 1], # 卷积核的滑动步长strides = [1, 垂直步长, 水平步长, 1]
                                            padding='SAME', # 定义padding方式为‘SAME’
                                            W_init=tf.truncated_normal_initializer(stddev=5e-2),# 定义权值矩阵初始化器为0均值和指定标准差的截尾正态分布
                                            b_init=tf.constant_initializer(value=0.0),# 定义偏置向量的初始化器为初值为0的常量初始化器
                                            name='cnn_layer1')  # 本层输出: (batch_size, 24, 24, 64)
            network = tl.layers.PoolLayer(network, # 定义池化层
                                          ksize=[1, 3, 3, 1],
                                          strides=[1, 2, 2, 1],
                                          padding='SAME',
                                          pool=tf.nn.max_pool, # 定义池化方式为最大值池化
                                          name='pool_layer1', )  # 本层输出:(batch_size, 12, 12, 64)
            network.outputs = tf.nn.lrn(network.outputs, 4, bias=1.0, alpha=0.001 / 9.0,
                                        beta=0.75, name='norm1') # Local Response Normalization局部响应正则化,详见Alex论文
            network = tl.layers.Conv2dLayer(network,
                                            act=tf.nn.relu,
                                            shape=[5, 5, 64, 64],
                                            strides=[1, 1, 1, 1],
                                            padding='SAME',
                                            W_init=tf.truncated_normal_initializer(stddev=5e-2),
                                            b_init=tf.constant_initializer(value=0.1),
                                            name='cnn_layer2')  # 本层输出: (batch_size, 12, 12, 64)
            network.outputs = tf.nn.lrn(network.outputs, 4, bias=1.0, alpha=0.001 / 9.0,
                                        beta=0.75, name='norm2')
            network = tl.layers.PoolLayer(network,
                                          ksize=[1, 3, 3, 1],
                                          strides=[1, 2, 2, 1],
                                          padding='SAME',
                                          pool=tf.nn.max_pool,
                                          name='pool_layer2')  # 本层输出: (batch_size, 6, 6, 64)
            # 定义Flatten层,将多维输入压平(flatten)为一个向量,为全连接层(DenseLayer)做准备
            network = tl.layers.FlattenLayer(network, name='flatten_layer')  # 本层输出: (batch_size, 2304)
            network = tl.layers.DenseLayer(network, n_units=384, act=tf.nn.relu, # 定义全连接层
                                           W_init=tf.truncated_normal_initializer(stddev=0.04),
                                           b_init=tf.constant_initializer(value=0.1),
                                           name='relu1')  # 本层输出: (batch_size, 384)
            network = tl.layers.DenseLayer(network, n_units=192, act=tf.nn.relu,
                                           W_init=tf.truncated_normal_initializer(stddev=0.04),
                                           b_init=tf.constant_initializer(value=0.1),
                                           name='relu2')  # 本层输出: (batch_size, 192)
            network = tl.layers.DenseLayer(network, n_units=10, act=tf.identity,
                                           W_init=tf.truncated_normal_initializer(stddev=1 / 192.0),
                                           b_init=tf.constant_initializer(value=0.0),
                                           name='output_layer')  # 本层输出: (batch_size, 10)
            y = network.outputs
            # 计算交叉熵损失ce,因此网络没有softmax层,因而使用softmax_cross_entropy_with_logits函数
            ce = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(y, y_))
            # L2范数正则化,防止过学习,没有它准确率将下降15%.
            L2 = tf.contrib.layers.l2_regularizer(0.004)(network.all_params[4]) + \
                 tf.contrib.layers.l2_regularizer(0.004)(network.all_params[6])
            cost = ce + L2 # 定义网络的损失函数

            # correct_prediction = tf.equal(tf.argmax(tf.nn.softmax(y), 1), y_)
            correct_prediction = tf.equal(tf.cast(tf.argmax(y, 1), tf.int32), y_) # 判断预测是否准确
            acc = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))  # 计算预测准确率

            return cost, acc, network


    def inference_batch_norm(x_crop, y_, reuse, is_train):
        """
        For batch normalization, the normalization should be placed after cnn
        with linear activation.
        """
        with tf.variable_scope("model", reuse=reuse):
            tl.layers.set_name_reuse(reuse)
            network = tl.layers.InputLayer(x_crop, name='input_layer')
            network = tl.layers.Conv2dLayer(network,
                                            act=tf.identity, #定义激活函数为线性函数,即y = x
                                            shape=[5, 5, 3, 64],
                                            strides=[1, 1, 1, 1],
                                            padding='SAME',
                                            W_init=tf.truncated_normal_initializer(stddev=5e-2),
                                            # b_init=tf.constant_initializer(value=0.0),
                                            b_init=None, # 无偏置项
                                            name='cnn_layer1')  # 本层输出: (batch_size, 24, 24, 64)
            # 定义batch正则化层,详见论文Batch Normalization: Accelerating Deep Network Training by  Reducing Internal Covariate Shift
            network = tl.layers.BatchNormLayer(network, is_train=is_train, name='batch_norm1')
            network.outputs = tf.nn.relu(network.outputs, name='relu1') # 对输出进行relu操作
            network = tl.layers.PoolLayer(network,
                                          ksize=[1, 3, 3, 1],
                                          strides=[1, 2, 2, 1],
                                          padding='SAME',
                                          pool=tf.nn.max_pool,
                                          name='pool_layer1', )  # 本层输出: (batch_size, 12, 12, 64)

            network = tl.layers.Conv2dLayer(network,
                                            act=tf.identity,
                                            shape=[5, 5, 64, 64],
                                            strides=[1, 1, 1, 1],
                                            padding='SAME',
                                            W_init=tf.truncated_normal_initializer(stddev=5e-2),
                                            # b_init=tf.constant_initializer(value=0.1),
                                            b_init=None,
                                            name='cnn_layer2')  # 本层输出: (batch_size, 12, 12, 64)

            network = tl.layers.BatchNormLayer(network, is_train=is_train, name='batch_norm2')
            network.outputs = tf.nn.relu(network.outputs, name='relu2')
            network = tl.layers.PoolLayer(network,
                                          ksize=[1, 3, 3, 1],
                                          strides=[1, 2, 2, 1],
                                          padding='SAME',
                                          pool=tf.nn.max_pool,
                                          name='pool_layer2')  # 本层输出: (batch_size, 6, 6, 64)
            network = tl.layers.FlattenLayer(network, name='flatten_layer')
            network = tl.layers.DenseLayer(network, n_units=384, act=tf.nn.relu,
                                           W_init=tf.truncated_normal_initializer(stddev=0.04),
                                           b_init=tf.constant_initializer(value=0.1),
                                           name='relu1')  # 本层输出: (batch_size, 384)
            network = tl.layers.DenseLayer(network, n_units=192, act=tf.nn.relu,
                                           W_init=tf.truncated_normal_initializer(stddev=0.04),
                                           b_init=tf.constant_initializer(value=0.1),
                                           name='relu2')  # 本层输出: (batch_size, 192)
            network = tl.layers.DenseLayer(network, n_units=10, act=tf.identity,
                                           W_init=tf.truncated_normal_initializer(stddev=1 / 192.0),
                                           b_init=tf.constant_initializer(value=0.0),
                                           name='output_layer')  # 本层输出: (batch_size, 10)
            y = network.outputs

            ce = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(y, y_))
            # L2范数正则化,防止过学习,没有它准确率将下降15%.
            L2 = tf.contrib.layers.l2_regularizer(0.004)(network.all_params[4]) + \
                 tf.contrib.layers.l2_regularizer(0.004)(network.all_params[6])
            cost = ce + L2

            # correct_prediction = tf.equal(tf.argmax(tf.nn.softmax(y), 1), y_)
            correct_prediction = tf.equal(tf.cast(tf.argmax(y, 1), tf.int32), y_)
            acc = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

            return cost, acc, network


    ## You can also use placeholder to feed_dict in data after using
    ## val, l = sess.run([x_train_batch, y_train_batch]) to get the data
    # x_crop = tf.placeholder(tf.float32, shape=[batch_size, 24, 24, 3])
    # y_ = tf.placeholder(tf.int32, shape=[batch_size,])
    # cost, acc, network = inference(x_crop, y_, None)

    with tf.device('/gpu:0'): # 使用GPU
        cost, acc, network = inference(x_train_batch, y_train_batch, None)
        cost_test, acc_test, _ = inference(x_test_batch, y_test_batch, True)
        ## 你可以尝试batch正则化方法
        # cost, acc, network = inference_batch_norm(x_train_batch, y_train_batch, None, is_train=True)
        # cost_test, acc_test, _ = inference_batch_norm(x_test_batch, y_test_batch, True, is_train=False)

    ## 训练
    n_epoch = 50000 # 定义epoch数
    learning_rate = 0.0001 # 定义学习速率
    print_freq = 1 # 定义打印频率
    n_step_epoch = int(len(y_train) / batch_size) # 计算每个epoch的迭代次数
    n_step = n_epoch * n_step_epoch # 计算总的迭代次数

    with tf.device('/gpu:0'):# 使用GPU
        # 在GPU上训练
        train_params = network.all_params # 待训练的参数为所有的网络参数
        # 定义训练操作,使用自适应矩估计(ADAM)算法最小化损失函数
        train_op = tf.train.AdamOptimizer(learning_rate, beta1=0.9, beta2=0.999,
                                          epsilon=1e-08, use_locking=False).minimize(cost)  # , var_list=train_params)

    sess.run(tf.global_variables_initializer()) # 初始化所有变量
    if resume: # 若是要从之前的checkpoint重新开始
        print("Load existing model " + "!" * 10)
        saver = tf.train.Saver()
        saver.restore(sess, model_file_name) # 载入之前的model

    network.print_params(False) # 不打印网络参数信息
    network.print_layers() # 打印网络各个layer的信息

    print('   learning_rate: %f' % learning_rate)
    print('   batch_size: %d' % batch_size)
    print('   n_epoch: %d, step in an epoch: %d, total n_step: %d' % (n_epoch, n_step_epoch, n_step))

    coord = tf.train.Coordinator() # 创建一个线程协调器
    threads = tf.train.start_queue_runners(sess=sess, coord=coord) # 创建线程
    # for step in range(n_step):
    step = 0
    for epoch in range(n_epoch): # 对每一个epoch
        start_time = time.time()# 计时开始
        train_loss, train_acc, n_batch = 0, 0, 0 # 初始化为0
        for s in range(n_step_epoch): # 对每一次迭代
            ## You can also use placeholder to feed_dict in data after using
            # val, l = sess.run([x_train_batch, y_train_batch])
            # tl.visualize.images2d(val, second=3, saveable=False, name='batch', dtype=np.uint8, fig_idx=2020121)
            # err, ac, _ = sess.run([cost, acc, train_op], feed_dict={x_crop: val, y_: l})
            err, ac, _ = sess.run([cost, acc, train_op]) # 计算损失函数、训练准确率
            step += 1
            train_loss += err
            train_acc += ac
            n_batch += 1

        if epoch + 1 == 1 or (epoch + 1) % print_freq == 0:# 按预定的打印频率打印训练信息
            print("Epoch %d : Step %d-%d of %d took %fs" % (
            epoch, step, step + n_step_epoch, n_step, time.time() - start_time))
            print("   train loss: %f" % (train_loss / n_batch))
            print("   train acc: %f" % (train_acc / n_batch))

            test_loss, test_acc, n_batch = 0, 0, 0 #打印测试信息
            for _ in range(int(len(y_test) / batch_size)):
                err, ac = sess.run([cost_test, acc_test])
                test_loss += err
                test_acc += ac
                n_batch += 1
            print("   test loss: %f" % (test_loss / n_batch))
            print("   test acc: %f" % (test_acc / n_batch))

        if (epoch + 1) % (print_freq * 20) == 0: # 定义保存model的时机
            print("Save model " + "!" * 10)
            saver = tf.train.Saver()
            save_path = saver.save(sess, model_file_name)

    coord.request_stop()# 请求终止所有线程
    coord.join(threads)# 等待终止所有线程
    sess.close()#关闭会话

另外,对涉及到的一些函数做一下说明:
1.tl.visualize.frame(I=None, second=5, saveable=True, name='frame', cmap=None, fig_idx=12836)
功能:显示一帧(图像).使用前确保 OpenAI Gym render() 为失效状态。
参数说明:
———-
I : numpy.array, numpy数组格式的图像
second : int,图像显示的时间(以秒计),若saveable为False.
saveable : boolean,保存(True) 或 画出图像(False).
name : a string,保存图像使用的名称, 若saveable为True.
cmap : None or string, ‘gray’ -灰度化, None-默认
fig_idx : int,matplotlib图像索引.

2.tf.train.string_input_producer(string_tensor, num_epochs=None, shuffle=True, seed=None, capacity=32, shared_name=None, name=None, cancel_op=None)
功能: 输出的字符串(例如文件名)到一个输入管道的队列。
参数说明:
———-
string_tensor: 1-D的字符串tensor.
num_epochs: 整数 (可选). 若指定该参数, string_input_producer在出现OutOfRange错误前从string_tensor 产生 num_epochs 次字符串。若不指定,string_input_producerstring_tensor 循环地产生字符串无限多次。
shuffle: 布尔量. 若为true, 字符串在epoch内随机洗牌.
seed: 整数(可选).在shuffle == True使用.
capacity: 整数. 设置队列的容量.
shared_name: (可选). 若设置,则该队列将通过指定的名称在多个sessions中被共享.
name:操作名(可选).
cancel_op: 为该队列取消op(可选)

3.tf.cast(x, dtype, name=None)
功能:将tensor铸型为指定的类型。
参数说明:
———-
x: TensorSparseTensor.
dtype: 目标类型.
name: 操作名(可选)

4.tf.shuffle_batch(tensors, batch_size, capacity, min_after_dequeue, num_threads=1, seed=None, enqueue_many=False, shapes=None, allow_smaller_final_batch=False, shared_name=None, name=None)

功能:对tensors随机洗牌创建batches。
参数说明:
———-
tensors: 列表 或 tensors到enqueue的字典.
batch_size: batch大小.
capacity: 整数. 队列中元素的最大个数.
min_after_dequeue: 一次出列后,队列中最少的元素个数,用于保证元素的混合程度
num_threads: 列队 tensor_list的线程数.
seed: 随机洗牌的seed
enqueue_many: tensor_list的tensor是否为单个样本.
shapes: (可选l) 每个样本的shape.
allow_smaller_final_batch: (可选) 布尔量.若为True`, 当队列中剩下的元素不足时,允许最后的batch 小于预定值.
shared_name: (可选) 若设置,则该队列将通过指定的名称在多个sessions中被共享.
name: (可选)操作名.

5.start_queue_runners(sess=None, coord=None, daemon=True, start=True, collection='queue_runners')
功能: 为graph中所有的queue runners开启线程. 返回所有线程的列表。
参数说明:
———-
sess: 运行队列ops的会话.
coord: 可选,用于协调开始的线程的协调器.
daemon:是否将线程标记为守护进程, 这意味着他们不阻止程序退出.
start: 设置为False表示只创建进程,不开始进程.

6.variable_scope(name_or_scope, default_name=None, values=None, initializer=None, regularizer=None, caching_device=None, partitioner=None, custom_getter=None, reuse=None, dtype=None)
功能: 用于定义创建 variables (layers)的op的上下文管理器,返回一个能被捕获和复用的作用域(scope).
参数说明:
———-
name_or_scope: stringVariableScope: 要开启的作用域(Scope).
default_name:使用的默认名称,若name_or_scope参数为None.若name_or_scope已存在,则它不被使用,因而可以不设置或为None.
values: 传递到op函数的 Tensor 参数列表
regularizer: 作用域内的变量的默认的正则化矩阵
caching_device: 作用域内的变量的默认的缓存设备.
partitioner: 作用域内的变量的默认的分割器.
custom_getter: 作用域内的变量的默认的custom getter
reuse: TrueNone; 若为True,将作用域及其所有的子作用域进入复用模式;若为 None, 则仅继承其父作用域的复用模式.
dtype: 此作用域内创建的变量的类型

7.tl.layers.FlattenLayer
功能:把多维输入压平成一个向量 ,以应用到 DenseLayer, RNNLayer, ConcatLayer 等,[batch_size, mask_row, mask_col, n_mask] —> [batch_size, mask_row * mask_col * n_mask]
参数说明:
———-
layer : 供给到本层的layer.
name : a string or None 本层的名称(可选)

8.关于TF的Padding方式
有 ‘SAME’ 和 ‘VALID’两种。
对于’SAME’ padding, 输出的高和宽计算如下:
垂直步长:strides[1],水平步长:strides[2]

输出图像高度 = ceil(输入图像的高度 / 垂直步长) # ceil表示向上取整
输出图像宽度 = ceil(输入图像的宽度 / 水平步长)

顶部和左侧的padding计算如下:

pad_沿高度 = (输出图像高度 - 1) * 垂直步长 + 滤波器高度 - 输入图像的高度
pad_沿宽度 = (输出图像宽度 - 1) * 水平步长 + 滤波器宽度 - 输入图像的宽度
pad_顶部 = pad_沿高度/ 2
pad_左侧 = pad_沿宽度 / 2
注意的是当不能被2整除时,底部和右侧总是比顶部和左侧多一个像素。 比如, pad_沿高度 = 5时, pad 2个像素到顶部、3 个像素到底部。这与 cuDNN和Caffe不同,它们总是在两边pad同样的像素。

对于’VALID’ padding, 输出的高和宽计算如下:

输出图像高度 = ceil((输入图像的高度 - 滤波器高度 + 1) / 垂直步长)
输出图像宽度 = ceil((输入图像的宽度 - 滤波器宽度 + 1) / 水平步长)
padding值总是0. 原始输入图像区域外的任何值都被认为是零 (即填充0到图像的边界).

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值