深度学习及图像分类阶段作业与阶段总结

这目录

深度学习及图像分类阶段作业与阶段总结

深度学习作业

问题1:神经网络构建

深度学习及图像分类阶段作业与阶段总结

问题1代码

# 导入工具包
import tensorflow as tf
from tensorflow.keras import layers
from tensorflow import keras

用function API构建

# 定义模型的输入
inputs = tf.keras.Input(shape=(784,),name="input")
# 四个隐层 
# 第一层 520,relu
x = tf.keras.layers.Dense(520, activation="relu",name="layer1")(inputs)
# 第二层 320 relu
x = tf.keras.layers.Dense(320,activation="relu",name="layer2")(x)
# 第三层 240 relu
x = tf.keras.layers.Dense(240,activation="relu",name="layer3")(x)
# 第四层 120 relu
x = tf.keras.layers.Dense(120,activation="relu",name="layer4")(x)
# 输出层 10 softmax
outputs = tf.keras.layers.Dense(10,activation="softmax",name="layer5")(x)
# 使用Model来创建模型,指明输入和输出
model = tf.keras.Model(inputs=inputs,outputs=outputs,name="my_model")
# 展示模型结果
model.summary()
Model: "my_model"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input (InputLayer)           [(None, 784)]             0         
_________________________________________________________________
layer1 (Dense)               (None, 520)               408200    
_________________________________________________________________
layer2 (Dense)               (None, 320)               166720    
_________________________________________________________________
layer3 (Dense)               (None, 240)               77040     
_________________________________________________________________
layer4 (Dense)               (None, 120)               28920     
_________________________________________________________________
layer5 (Dense)               (None, 10)                1210      
=================================================================
Total params: 682,090
Trainable params: 682,090
Non-trainable params: 0
_________________________________________________________________

通过sequential的方式进行构建

# 定义模型,包括5层
model = keras.Sequential(
[
    #第一层:神经元个数为520,激活函数为relu
    layers.Dense(520,activation="relu",name="layer1",input_shape=(1,784)),
    #第二层:神经元个数为320,激活函数为relu
    layers.Dense(320,activation="relu",name="layer2"),
    #第三层:神经元个数为240,激活函数为relu
    layers.Dense(240,activation="relu",name="layer3"),
    #第四层:神经元个数为120,激活函数为relu
    layers.Dense(120,activation="relu",name="layer4"),
    #第五层(输出层):神经元个数10个,激活函数为softmax
    layers.Dense(10,activation="softmax",name="layer5")
],
name="my_Sequential"
)
# 展示模型结果
model.summary()
# 模型展示
keras.utils.plot_model(model,show_layer_names=True)

深度学习及图像分类阶段作业与阶段总结

通过model的子类构建

class MyModel(tf.keras.Model):
    #在init方法中定义网络层结构
    def __init__(self):
        super(MyModel,self).__init__()
        # 第一层:神经元个数:520,激活函数relu
        self.layer1 = tf.keras.layers.Dense(520,activation="relu",name="layer1",input_shape=(784,))
        # 第二层:神经元个数:320,激活函数:relu
        self.layer2 = tf.keras.layers.Dense(320,activation="relu",name="layer2")
        # 第三层:神经元个数:240,激活函数:relu
        self.layer3 = tf.keras.layers.Dense(240,activation="relu",name="layer3")
        # 第四层:神经元个数:120,激活函数:relu
        self.layer4 = tf.keras.layers.Dense(120,activation="relu",name="layer4")
        # 第五层:神经元个数:10,激活函数:softmax
        self.layer5 = tf.keras.layers.Dense(10,activation="softmax",name="layer5")
    
    # 在call方法中完成前向传播
    def call(self,inputs):
        x = self.layer1(inputs)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)
        return self.layer5(x)
    
# 实例化模型
model = MyModel()
# 设置一个输入,调用模型
x = tf.ones((1,784))
y=model(x)
model.summary()

问题2:特征图大小计算

深度学习及图像分类阶段作业与阶段总结

首先这题计算方式有个疑问,以前上课写过的文章计算如下:

深度学习及图像分类阶段作业与阶段总结

注意上式有个+2P,这里带入这个公布发现不能能算出作业的结果,于是我找了一篇博客如下https://www.cnblogs.com/byugo/p/10634464.html,这里计算公式为n’= (n-k)/s+1,就不加那个2P了,这里不知道为啥,先留下这个问题,如果有朋友知道的话,真的麻烦您在评论区留言,感谢感谢!

问题2答案

  1. 首先输入的图像的高(height)为32,宽(weight)为32,通道数(D)为3,经过第一层卷积核大小(kernel_size)为5,步长(strides)为1的共6个卷积核进行卷积后,此时输出图像的大小为(32 - 5)/1 + 1 =28,输出图像的通道数则与卷积核的个数相同,所以输出图像大小为28 * 28 * 6

  2. 经过第一层池化层进行特征降维后,池化大小(pool_size)为2,步长为2,输出图像大小为(28 - 2 )/2 + 1 = 14,因为只有一个池化核,所以输出图像的通道数跟之前相同,此时输出图像大小为14 * 14 *6

  3. 经过第二层卷积层的时候,此时卷积核大小为5 * 5,步长为1,卷积核的个数为16,输出图像的大小为(14 - 5 )/1 + 1 = 10,通道数为16,此时输出图像大小为10 * 10 * 16

  4. 经过第二层池化层进行特征降维后,池化大小为2,步长为2,输出图像的长宽为(10 - 2 )/2 + 1 = 5,因为同样只有一个池化核,所以通道数依旧与之前相同,此时输出图像大小为5 * 5 * 16.

问题3:特征图计算

深度学习及图像分类阶段作业与阶段总结

问题3答案:

参考之前写过的博客:

深度学习及图像分类阶段作业与阶段总结

我在演草纸上写出运算过程,字不好看,凑合凑合吧,哈哈哈哈哈哈!

深度学习及图像分类阶段作业与阶段总结

  1. 所以卷积后的特征图是:

    1 0

    4 -1

  2. RELU激活之后的特征图:大于0的为原值,小于0的置为0,所以激活函数处理后的特征图是:

    1 0

    4 0

  3. 这是最大池化层,所以取最大值,池化后的结果为4。

图像分类作业

问题:ResNet34

深度学习及图像分类阶段作业与阶段总结

代码

import tensorflow as tf
from tensorflow.keras import layers,activations
from tensorflow import keras

模型构建

# 构建残差块
class Residual(tf.keras.Model):
    #定义网络的层
    def __init__(self,num_channels,use_1x1conv=False,strides=1):
        super(Residual,self).__init__()
        #两个3x3的卷积层
        self.conv1=layers.Conv2D(num_channels,padding='same',kernel_size=3,strides=strides)
        self.conv2=layers.Conv2D(num_channels,padding='same',kernel_size=3)
        #判断是否使用1x1卷积层 来统一通道数
        if use_1x1conv==True:
            self.conv3=layers.Conv2D(num_channels,kernel_size=1,strides=strides)
        else:
            self.conv3=None
            
        #在每个卷积层后面都有一个BN层 标准化
        #这里定义网络层的次序 指的并不是模型里面各层之间的顺序  call方法里面前向传播的次序才决定模型里面个层的顺序
        self.bn1=layers.BatchNormalization()
        self.bn2=layers.BatchNormalization()

    
    #定义前向传播过程  决定模型里面各层之间的顺序
    def call(self,x):
        y=tf.keras.layers.Activation(activation='relu')(self.bn1(self.conv1(x)))
        y=self.bn2(self.conv2(y))
        
        if self.conv3:
            x=self.conv3(x)
        return tf.keras.layers.Activation(activation='relu')(y+x)
        
# ResNet模块构建
# 同一个残差模块里面的残差块的通道数(卷积核个数),卷积核大小整个模型都是是一样的3x3,
class ResnetBlock(tf.keras.layers.Layer):
    # 定义所需的网络层
    def __init__(self, num_channels, num_res, first_block=False):
        super(ResnetBlock, self).__init__()
        # 定义list来存储残差块
        self.listLayers = []
        # 按照要求的一个模块里面的残差块数目 循环 生成模块
        for i in range(num_res):
            # 如果不是第一个模块 是其他模块的是第一个残差块 则这个残差块的步长度需要是2降维 而且要加1x1的卷积核统一通道数目
            # 因为本次模块的输入图片来自上各模块的输出 上个模块的卷积核个数和本模块不同 所以上个模块输出的图片通道数和本模块的卷积核个数不同
            # 在最后+x的时候 需要把输入的x转化成本模块的通道数
            if i == 0 and first_block == False:
                self.listLayers.append(
                    Residual(num_channels, use_1x1conv=True, strides=2))
            else:
                self.listLayers.append(Residual(num_channels))
    # 定义前向传播的过程
    def call(self, x):
        for layer in self.listLayers.layers:
            x = layer(x)
        return x
# 模型构建
class ResNet(tf.keras.Model):
    #定义各个层 其中先传入参数(每个模块里面的残差快个数) 整个模型可以改变每个模块残差块的个数 和残差块的卷积核个数 但保证每个模块里残差块的卷积核个数都一样
    def __init__(self,num_blocks):
        super(ResNet,self).__init__()
        #输入层 64个7x7大小卷积核的卷积层 步长度是2
        self.conv=layers.Conv2D(64,kernel_size=7,strides=2,padding='same')
        #BN层
        self.bn=layers.BatchNormalization()
        #激活函数
        self.relu=layers.Activation('relu')
        #池化
        self.mp=layers.MaxPool2D(pool_size=3,strides=2,padding='same')
        #几个串联的block模块(内含多个残差块)
        #每个残差模块里的残差块卷积核个数都相等=残差块里各卷积层卷积核个数
        self.res_block1=ResnetBlock(64,num_blocks[0],first_block=True)
        self.res_block2=ResnetBlock(128,num_blocks[1])
        self.res_block3=ResnetBlock(256,num_blocks[2])
        self.res_block4=ResnetBlock(512,num_blocks[3])
        #输出部分 首先全局平均池化层
        self.gap=layers.GlobalAveragePooling2D()
        #全连接层
        self.fc=layers.Dense(units=10,activation=tf.keras.activations.softmax)
        #定义前向传播过程
    def call(self,x):
        #输入部分的传输过程
        x=self.conv(x)
        x=self.bn(x)
        x=self.relu(x)
        x=self.mp(x)
        #残差模块部分传输过程
        x=self.res_block1(x)
        x=self.res_block2(x)
        x=self.res_block3(x)
        x=self.res_block4(x)
        # 输出部分的传输
        x=self.gap(x)
        x=self.fc(x)
        return x
        
#实例化模型
mynet=ResNet([3,4,5,4])
print(mynet)
x=tf.random.uniform(shape=(1,224,224,1))
y=mynet(x)
mynet.summary()
<__main__.ResNet object at 0x0000029710D756A0>
Model: "res_net"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_102 (Conv2D)          multiple                  3200      
_________________________________________________________________
batch_normalization_93 (Batc multiple                  256       
_________________________________________________________________
activation (Activation)      multiple                  0         
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 multiple                  0         
_________________________________________________________________
resnet_block (ResnetBlock)   multiple                  223104    
_________________________________________________________________
resnet_block_1 (ResnetBlock) multiple                  1119360   
_________________________________________________________________
resnet_block_2 (ResnetBlock) multiple                  5649152   
_________________________________________________________________
resnet_block_3 (ResnetBlock) multiple                  17846784  
_________________________________________________________________
global_average_pooling2d (Gl multiple                  0         
_________________________________________________________________
dense_3 (Dense)              multiple                  5130      
=================================================================
Total params: 24,846,986
Trainable params: 24,830,730
Non-trainable params: 16,256
_________________________________________________________________

利用fashionmnist数据对网络进行训练

数据读取
import numpy as np
from tensorflow.keras.datasets import fashion_mnist
# 获取手写数字数据集
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
# 训练集数据维度的调整:N H W C
train_images = np.reshape(train_images,(train_images.shape[0],train_images.shape[1],train_images.shape[2],1))
# 测试集数据维度的调整:N H W C
test_images = np.reshape(test_images,(test_images.shape[0],test_images.shape[1],test_images.shape[2],1))
# 定义两个方法随机抽取部分样本演示
# 获取训练集数据
def get_train(size):
    # 随机生成要抽样的样本的索引
    index = np.random.randint(0, np.shape(train_images)[0], size)
    # 将这些数据resize成22*227大小
    resized_images = tf.image.resize_with_pad(train_images[index],224,224,)
    # 返回抽取的
    return resized_images.numpy(), train_labels[index]
# 获取测试集数据 
def get_test(size):
    # 随机生成要抽样的样本的索引
    index = np.random.randint(0, np.shape(test_images)[0], size)
    # 将这些数据resize成224*224大小
    resized_images = tf.image.resize_with_pad(test_images[index],224,224,)
    # 返回抽样的测试样本
    return resized_images.numpy(), test_labels[index]

# 获取训练样本和测试样本
train_images,train_labels = get_train(256)
test_images,test_labels = get_test(128)
模型编译
#优化器
optimizer=tf.keras.optimizers.SGD(learning_rate=0.01,momentum=0.9)
#模型编译
mynet.compile(optimizer=optimizer,loss='sparse_categorical_crossentropy',metrics=['accuracy'])
模型训练
# 模型训练:指定训练数据,batchsize,epoch,验证集
mynet.fit(train_images,train_labels,batch_size=128,epochs=3,verbose=1,validation_split=0.1)
Epoch 1/3
2/2 [==============================] - 33s 16s/step - loss: 3.4795 - accuracy: 0.1087 - val_loss: 93.5103 - val_accuracy: 0.0769
Epoch 2/3
2/2 [==============================] - 29s 14s/step - loss: 3.2747 - accuracy: 0.1261 - val_loss: 76.9233 - val_accuracy: 0.0769
Epoch 3/3
2/2 [==============================] - 26s 13s/step - loss: 2.7347 - accuracy: 0.3043 - val_loss: 65.8635 - val_accuracy: 0.1923
模型评估
mynet.evaluate(test_images,test_labels)
4/4 [==============================] - 3s 857ms/step - loss: 61.4498 - accuracy: 0.0703
[61.44978332519531, 0.0703125]
遇到问题:tensorflow 里面fashion_mnist下载失败(超时)的问题

下载自带的数据集过慢,然后建议从网上下载数据集,我直接百度网盘分享

链接:https://pan.baidu.com/s/1YwN60rFsWy8SqGjrxsDVwA
提取码:cd69
下载之后移动到C盘C:\Users\LH.keras\datasets路径下。

阶段总结

学完深度学习方面的内容,感觉之前学习的神经网络一些不懂得地方都突然豁然开朗,之前第一次学习真的是怀疑人生。。。。一开始认为卷积神经网络会很复杂,但是看完之后,认为只要掌握他里面的重要知识点,就会很容易掌握。所以当遇到当时学习的时候不会的,感觉很难的知识点时,可以稍微发一点脾气,出去玩放松放松,但是不能放弃,可以先暂时跳过,继续学习后面的,等未来再次接触时会有“柳暗花明又一村”的感觉!

学习完图像分类,感觉像是初入计算机视觉的大门,接下来我将学习目标检测方面的内容,学习重要的是坚持,为了完成毕设,坚持学习下去!

上一篇:静态变量设为non-public或者加final关键字


下一篇:EffectiveJava 1创建和销毁对象 3用私有构造器或枚举类型强化Singleton属性