码迷,mamicode.com
首页 > Web开发 > 详细

tensorflow2.0——ResNet实现

时间:2020-12-14 13:32:55      阅读:7      评论:0      收藏:0      [点我收藏+]

标签:res   else   optimizer   需要   numpy   lis   repr   ram   nta   

一、ResNet结构

  ResNet神经网络主要用的是跳远连接的方式来解决深层神经网络退化的问题,在跳远连接的后需要对输入与激活前的值进行相加,激活前的值y可能与输入值的shape相同,也可能不相同,所以有ResNet有两种方式,当shape不相同时,用1*1的卷积操作来处理,一般来说1*1的卷积对神经网络特征的学习作用不大,通常用来做shape的调整。

  如下图,输入是265通道的图,虚线表示shape不同的ResNet操作,实线表示shape相同的ResNet操作。

  技术图片

 

 

二、ResNet实现

   用cifar10数据集对的shape进行实现,跳远结构也比较简单,和上一节的图示一样只是跳了两层卷积,如何实现维度不同的的跳远连接操作呢,可以通过对比ResNet的输入与卷积之后的输出的shape即可,如下代码:

    # 判断输入和输出是否有相同的channel,不相同则用1*1卷积进行操作
    if block_input.shape[-1] == cov_output.shape[-1]:
        block_out = block_input + cov_output
        return block_out
    else:
        block_out = block_input + Covunit(cov_output, cov_output.shape[-1], [1 * 1])    # 当维度不相同时用1*1的卷积处理
        return block_out

代码示例:

import tensorflow as tf
import numpy as np

gpus = tf.config.list_physical_devices(GPU)
tf.config.experimental.set_visible_devices(devices=gpus[2:8], device_type=GPU)
# os.environ["CUDA_VISIBLE_DEVICES"] = "0"

# 读取数据集,32*32像素3通道图片,标签为10类
(train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.cifar10.load_data()


# 零均值归一化
def normalize(X_train, X_test):
    X_train = X_train / 255.
    X_test = X_test / 255.

    mean = np.mean(X_train, axis=(0, 1, 2, 3))  # 均值
    std = np.std(X_train, axis=(0, 1, 2, 3))  # 标准差
    X_train = (X_train - mean) / (std + 1e-7)
    X_test = (X_test - mean) / (std + 1e-7)
    return X_train, X_test


# 预处理
def preprocess(x, y):
    x = tf.cast(x, tf.float32)
    y = tf.cast(y, tf.int32)
    y = tf.squeeze(y, axis=1)  # 将(50000, 1)的数组转化为(50000)的Tensor
    y = tf.one_hot(y, depth=10)
    return x, y


# 训练数据标准化
train_images, test_images = normalize(train_images, test_images)

# 预处理
train_db = tf.data.Dataset.from_tensor_slices((train_images, train_labels))
train_db = train_db.shuffle(50000).batch(100).map(preprocess)  # 每个批次128个训练样本

test_db = tf.data.Dataset.from_tensor_slices((test_images, test_labels))
test_db = test_db.shuffle(10000).batch(100).map(preprocess)  # 每个批次128个测试样本


# 创建卷积结构单元的函数
def Covunit(unit_input, filters, kernel_size, activation=None):
    ‘‘‘
    :param unit_input: 卷积核输入,tensor
    :param filters: 卷积核个数
    :param kernel_size: 卷积核大小
    :param activation: 激活函数,若为0则不激活
    :return:卷积后输出的tensor
    ‘‘‘

    unit_cov = tf.keras.layers.Conv2D(filters, kernel_size, padding=same)(unit_input)  # 卷积,不改变长于宽
    unit_bn = tf.keras.layers.BatchNormalization()(unit_cov)  # 批标准化

    if activation:
        unit_act = tf.keras.layers.Activation(activation)(unit_bn)
    else:
        unit_act = unit_bn

    return unit_act


# ResNet函数,网络结构中可能有多个这样的结构块,所以需要如此操作
def ResNetblock(block_input, filters=None, activations=None):
    ‘‘‘
    :param block_input: ResNet结构的输入
    :param filters: 该ResNet结构每个卷积层的filters个数
    :param filters: 该ResNet结构每个卷积层的激活函数,最后一层不需要激活函数
    :return: Inceptionblock结构输出的tensor
    ‘‘‘

    # 如果有多个卷积操作,则依次构建卷积操作
    if filters:
        layer_input = block_input  # 定义卷积层的输入,初始为block_input
        for filters_i, activations_j in zip(filters, activations):
            layer_input = Covunit(unit_input=layer_input, filters=filters_i, kernel_size=[3, 3],
                                  activation=activations_j)
        cov_output = layer_input  # 卷积层的输出
    else:
        cov_output = block_input  # 无卷积层的输出

    # 判断输入和输出是否有相同的channel,不相同则用1*1卷积进行操作
    if block_input.shape[-1] == cov_output.shape[-1]:
        block_out = block_input + cov_output
        return block_out
    else:
        block_out = block_input + Covunit(cov_output, cov_output.shape[-1], [1 * 1])    # 当维度不相同时用1*1的卷积处理
        return block_out


# 创建Inception网络
net_input = tf.keras.Input((32, 32, 3)) # 输入,cifar的图片
cov1=Covunit(net_input,32,(3*3),relu) # 卷积操作,32个3*3的卷积核,输出为3*3*32
res1=ResNetblock(cov1,filters=[32,32],activations=[relu,])   # ResNet结构块,这个是shape相同的跳远连接,最后一个卷积没有激活函数
act1=tf.keras.layers.Activation(relu)(res1)   # 对第一个ResNet结构块输出进行激活
res2=ResNetblock(act1,filters=[32,16],activations=[relu,])    # ResNet结构块,这个是shape不相同的跳远连接,最后一个卷积没有激活函数
act2=tf.keras.layers.Activation(relu)(res2)   # 对第一个ResNet结构块输出进行激活
fla2=tf.keras.layers.Flatten()(act2) # 对数据进行Flatten
den3=tf.keras.layers.Dense(units=32*32*4,activation=relu)(fla2)   # 全连接层32*32*4个神经元
drop3=tf.keras.layers.Dropout(0.2)(den3) # drop操作
den4=tf.keras.layers.Dense(units=32*32,activation=relu)(drop3) # 全连接层32*32个神经元
drop3=tf.keras.layers.Dropout(0.2)(den4) # drop操作
den4=tf.keras.layers.Dense(units=8*8,activation=relu)(drop3) # 全连接层8*8个神经元
net_output = tf.keras.layers.Dense(10, softmax)(den4)   # 全连接层10个神经元

ResNet = tf.keras.Model(inputs=net_input, outputs=net_output)  # 构建模型

# 查看模型的结构
ResNet.summary()

# 模型编译
ResNet.compile(
    optimizer=tf.keras.optimizers.Adam(0.00001),
    loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
    metrics=[accuracy]
)

ResNet.fit(train_db)

 

tensorflow2.0——ResNet实现

标签:res   else   optimizer   需要   numpy   lis   repr   ram   nta   

原文地址:https://www.cnblogs.com/dwithy/p/14103493.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!