tf系列4——模型构建4种方法

这篇文章有一定借鉴意义

https://panjinquan.blog.csdn.net/article/details/86712328

一共就这4种,足够,别瞎想

1 使用现有的预训练模型

keras.applications.vgg16.VGG16(include_top=True, weights='imagenet',
                                input_tensor=None, input_shape=None,
                                pooling=None,
                                classes=1000)

model = tf.keras.applications.MobileNetV2(weights=None, classes=5)

https://mattzheng.blog.csdn.net/article/details/72859145

这个案例很好https://xercis.blog.csdn.net/article/details/88660053?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-2.control&dist_request_id=1330144.35460.16182210027491941&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-2.control

2 Keras Sequential模式建立模型(不推荐用,跳接结构不行)

2.1 Sequential内置

在这里插入图片描述
在这里插入图片描述
参考:https://www.bilibili.com/video/BV1B7411L7Qt?p=33

在这里插入图片描述

2.2 Sequential外置

def mnist_cnn(input_shape):
    '''
    构建一个CNN网络模型
    :param input_shape: 指定输入维度
    :return:
    '''
    model=keras.Sequential()
    model.add(keras.layers.Conv2D(filters=32,kernel_size = 5,strides = (1,1),
                                  padding = 'same',activation = tf.nn.relu,input_shape = input_shape))
    model.add(keras.layers.MaxPool2D(pool_size=(2,2), strides = (2,2), padding = 'valid'))
    model.add(keras.layers.Conv2D(filters=64,kernel_size = 3,strides = (1,1),padding = 'same',activation = tf.nn.relu))
    model.add(keras.layers.MaxPool2D(pool_size=(2,2), strides = (2,2), padding = 'valid'))
    model.add(keras.layers.Dropout(0.25))
    model.add(keras.layers.Flatten())
    model.add(keras.layers.Dense(units=128,activation = tf.nn.relu))
    model.add(keras.layers.Dropout(0.5))
    model.add(keras.layers.Dense(units=10,activation = tf.nn.softmax))
    return model

3 Functional API 函数api建立模型(最常用,复杂网络)

多输入模型,
多输出模型,
具有共享层的模型(同一层被调用多次),
具有非序列数据流的模型(例如,剩余连接)

这种方式就是各个层都是一个函数,通过函数的叠加就可以实现,一般使用这种方法,将模型封装成一个模型函数。

inputs = tf.keras.Input(shape=(28, 28, 1))
x = tf.keras.layers.Flatten()(inputs)
x = tf.keras.layers.Dense(units=100, activation=tf.nn.relu)(x)
x = tf.keras.layers.Dense(units=10)(x)
outputs = tf.keras.layers.Softmax()(x)
model = tf.keras.Model(inputs=inputs, outputs=outputs)

看下面这个FCN构建,结合了迁移学习和函数api建立模型
https://blog.csdn.net/xiaotiig/article/details/110355547

下面这个resnet网络结构的实现,也是用的这种方法实现的,因为有很多的残差结构
https://blog.csdn.net/xiaotiig/article/details/117673634

4 tf构建模型Class

4.1 初识

在这里插入图片描述
实例化层然后调用方法,两步
init里实例化各种方法
call调用各种方法

在这里插入图片描述
继承 tf.keras.Model 后,我们同时可以使用父类的若干方法和属性,例如在实例化类 model = Model() 后,可以通过 model.variables 这一属性直接获得模型中的所有变量,免去我们一个个显式指定变量的麻烦。

对于上面的 y_pred = w * X + b ,我们可以通过模型类的方式编写如下:这里,我们没有显式地声明a 和 b 两个变量并写出 y_pred = w x X + b 这一线性变换,而是建立了一个继承了 tf.keras.Model 的模型类 Linear 。这个类在初始化部分实例化了一个 全连接层 ( tf.keras.layers.Dense ),并在 call 方法中对这个层进行调用,实现了线性变换的计算。

import tensorflow as tf

X = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
y = tf.constant([[10.0], [20.0]])

# 1、构建线性模型
class Linear(tf.keras.Model):
    def __init__(self):
        super().__init__()
        self.dense = tf.keras.layers.Dense(
            units=1,
            activation=None,
            kernel_initializer=tf.zeros_initializer(),
            bias_initializer=tf.zeros_initializer()
        )

    def call(self, input):
        output = self.dense(input)
        return output


# 以下代码结构与前节类似
model = Linear()
optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)
for i in range(100):
    with tf.GradientTape() as tape:
        y_pred = model(X)
        loss = 0.5 * tf.reduce_mean(tf.square(y_pred - y))
    # 使用 model.variables 这一属性直接获得模型中的所有变量
    grads = tape.gradient(loss, model.variables)
    optimizer.apply_gradients(grads_and_vars=zip(grads, model.variables))
print(model.variables)

4.2 Keras 当中的layer(层)接口

在这里插入图片描述

4.3 Models

在这里插入图片描述

4.4 一个小案例

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5 函数式和class方式实现unet

5.1 函数式模型实现unet

# 使用函数式编程实现UNet
import tensorflow as tf

def Unet_model(input_shape=(256,256,3), num_classes=2):
    inputs = tf.keras.layers.Input(input_shape)

    x1 = tf.keras.layers.Conv2D(64, kernel_size=3, activation="relu", padding="same")(inputs)
    x1 = tf.keras.layers.Conv2D(64, kernel_size=3, activation="relu", padding="same")(x1)

    x2 = tf.keras.layers.MaxPooling2D()(x1)
    x2 = tf.keras.layers.Conv2D(128, kernel_size=3, activation="relu", padding="same")(x2)
    x2 = tf.keras.layers.Conv2D(128, kernel_size=3, activation="relu", padding="same")(x2)

    x3 = tf.keras.layers.MaxPooling2D()(x2)
    x3 = tf.keras.layers.Conv2D(256, kernel_size=3, activation="relu", padding="same")(x3)
    x3 = tf.keras.layers.Conv2D(256, kernel_size=3, activation="relu", padding="same")(x3)

    x4 = tf.keras.layers.MaxPooling2D()(x3)
    x4 = tf.keras.layers.Conv2D(512, kernel_size=3, activation="relu", padding="same")(x4)
    x4 = tf.keras.layers.Conv2D(512, kernel_size=3, activation="relu", padding="same")(x4)

    # 最下面一层
    x5 = tf.keras.layers.MaxPooling2D()(x4)
    x5 = tf.keras.layers.Conv2D(1024, kernel_size=3, activation="relu", padding="same")(x5)
    x5 = tf.keras.layers.Conv2D(1024, kernel_size=3, activation="relu", padding="same")(x5)

    # 开始上采样
    x6 = tf.keras.layers.Conv2DTranspose(512, kernel_size=3, strides=2, padding="same")(x5)
    x6 = tf.concat([x4,x6],axis=-1)
    x6 = tf.keras.layers.Conv2D(512, kernel_size=3, activation="relu", padding="same")(x6)
    x6 = tf.keras.layers.Conv2D(512, kernel_size=3, activation="relu", padding="same")(x6)

    x7 = tf.keras.layers.Conv2DTranspose(256, kernel_size=3, strides=2, padding="same")(x6)
    x7 = tf.concat([x3, x7], axis=-1)
    x7 = tf.keras.layers.Conv2D(256, kernel_size=3, activation="relu", padding="same")(x7)
    x7 = tf.keras.layers.Conv2D(256, kernel_size=3, activation="relu", padding="same")(x7)

    x8 = tf.keras.layers.Conv2DTranspose(128, kernel_size=3, strides=2, padding="same")(x7)
    x8 = tf.concat([x2, x8], axis=-1)
    x8 = tf.keras.layers.Conv2D(128, kernel_size=3, activation="relu", padding="same")(x8)
    x8 = tf.keras.layers.Conv2D(128, kernel_size=3, activation="relu", padding="same")(x8)

    x9 = tf.keras.layers.Conv2DTranspose(64, kernel_size=3, strides=2, padding="same")(x8)
    x9 = tf.concat([x1, x9], axis=-1)
    x9 = tf.keras.layers.Conv2D(64, kernel_size=3, activation="relu", padding="same")(x9)
    x9 = tf.keras.layers.Conv2D(64, kernel_size=3, activation="relu", padding="same")(x9)

    out = tf.keras.layers.Conv2D(num_classes, kernel_size=1, padding="same")(x9)
    out = tf.keras.layers.Activation('softmax')(out)

    model = tf.keras.models.Model(inputs,out,name='unet')

    return model

加载

from nets.unet import Unet_model
model = Unet_model(input_shape=(img_target_size[0], img_target_size[1], 3),num_classes=N_CLASS)
model.summary()
opt = Adam(base_lr)
model_save_dir = os.path.join( './model_unet/unet_320.h5')
checkpoint = ModelCheckpoint(model_save_dir, verbose=True, save_best_only=True, monitor='val_mean_iou', mode='max')
scheduleLR = LearningRateScheduler(lr_schedular, verbose=True)
model.compile(opt, 'categorical_crossentropy', metrics=['accuracy', mean_iou])
model.fit(tr_gen, epochs=40, validation_data=val_gen, callbacks=[checkpoint, scheduleLR])

5.2 class方式实现unet

# 实现了unet模型
import tensorflow as tf
import numpy as np


#########################################    2 前向传播
class Downsample(tf.keras.layers.Layer):
    "先定义,再调用,进行下采样"
    def __init__(self, units):
        "units是卷积核的数量"
        super(Downsample,self).__init__()
        # 使用了same填充,原论文使用valid填充
        self.conv1 = tf.keras.layers.Conv2D(units, kernel_size=3,padding="same")
        self.conv2 = tf.keras.layers.Conv2D(units, kernel_size=3, padding="same")
        # tf.keras.layers.MaxPooling2D()和tf.keras.layers.MaxPool2D()区别是什么?
        self.pool = tf.keras.layers.MaxPooling2D()

    def call(self, x, is_pool = True):
        if is_pool:
            x = self.pool(x)
        x = self.conv1(x)
        x = tf.nn.relu(x)
        x = self.conv2(x)
        x = tf.nn.relu(x)
        return x


class Upsample(tf.keras.layers.Layer):
    "先定义,再调用,进行上采样"
    def __init__(self, units):
        "units是卷积核的数量"
        super(Upsample, self).__init__()
        self.conv1 = tf.keras.layers.Conv2D(units, kernel_size=3, padding="same")
        self.conv2 = tf.keras.layers.Conv2D(units, kernel_size=3, padding="same")
        self.deconv = tf.keras.layers.Conv2DTranspose(units//2,kernel_size=3,strides=2,padding="same")

    def call(self, x):
        x = self.conv1(x)
        x = tf.nn.relu(x)
        x = self.conv2(x)
        x = tf.nn.relu(x)
        x = self.deconv(x)
        x = tf.nn.relu(x)
        return x

class Unet_model(tf.keras.Model):
    def __init__(self):
        "只进行初始化,定义层,还没有进行前向传播"
        super(Unet_model, self).__init__()
        # 这步只是进行卷积
        self.down1 = Downsample(64)

        # 4次下采样
        self.down2 = Downsample(128)
        self.down3 = Downsample(256)
        self.down4 = Downsample(512)
        self.down5 = Downsample(1024)

        # 4次上采样,定义一个上采样层
        # 第一个上采样只进行上采样,不进行卷积
        self.up1 = tf.keras.layers.Conv2DTranspose(512, kernel_size=3, strides=2, padding="same")
        # 上采样加卷积
        self.up2 = Upsample(512)
        self.up3 = Upsample(256)
        self.up4 = Upsample(128)

        # 进行两次卷积
        self.conv_last = Downsample(64)

        # 进行最后的1*1卷积分类,进行城市街景共34个类别的分类,所以输出层为34,,
        # 如果进行别的任务,是几类就写几,因为需要喝MeanIou一样,否则会报错
        self.last = tf.keras.layers.Conv2D(21, kernel_size=1, padding="same")

    def call(self, x):
        "进行前向传播模型的构建"

        # 第一次先进行两次卷积
        x1 = self.down1(x, is_pool = False)

        # 进行4次下采样加两次卷积
        x2 = self.down2(x1)
        x3 = self.down3(x2)
        x4 = self.down4(x3)
        x5 = self.down5(x4)

        # 进行一次上采样
        x5 = self.up1(x5)

        # 进行合并,然后卷积卷积上采样
        x6 = tf.concat([x4, x5], axis=-1)
        x6 = self.up2(x6)

        x7 = tf.concat([x3, x6], axis=-1)
        x7 = self.up3(x7)

        x8 = tf.concat([x2, x7], axis=-1)
        x8 = self.up4(x8)

        # 合并,然后两层卷积
        x9 = tf.concat([x1, x8], axis=-1)
        x9 = self.conv_last(x9, is_pool = False)

        # 输出为34层,共34个类别
        out = self.last(x9)

        return out

加载

from nets.unet import Unet_model
model = Unet_model()
opt = Adam(base_lr)
model_save_dir = os.path.join( './model_unet/unet_320.h5')
checkpoint = ModelCheckpoint(model_save_dir, verbose=True, save_best_only=True, monitor='val_mean_iou', mode='max')
scheduleLR = LearningRateScheduler(lr_schedular, verbose=True)
model.compile(opt, 'categorical_crossentropy', metrics=['accuracy', mean_iou])
model.fit(tr_gen, epochs=40, validation_data=val_gen, callbacks=[checkpoint, scheduleLR])
model.summary()

6 补充,深度学习的各种层大全

【1】tensorflow2.0——神经网络的层(层全连接层、卷积层、池化层、BN层、激活层、dropout层及其他层) - 我不是高斯分布 - 博客园
https://www.cnblogs.com/dwithy/p/14028108.html

7 模型可视化

# from keras.utils import plot_model
# import os
# os.environ["PATH"] += os.pathsep + 'C:/Program Files (x86)/Graphviz2.38/bin/'
#
# model = danet_resnet101(height=512, width=512, channel=3, classes=1)
# model.summary()
# plot_model(model, to_file='danet_resnet101.png', show_shapes=True)
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晓码bigdata

如果文章给您带来帮助,感谢打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值