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


这目录

  • 深度学习及图像分类阶段作业与阶段总结
    • 深度学习作业
      • 问题1:神经网络构建
      • 问题1代码
        • 用function API构建
        • 通过sequential的方式进行构建
        • 通过model的子类构建
      • 问题2:特征图大小计算
      • 问题2答案
      • 问题3:特征图计算
      • 问题3答案:
    • 图像分类作业
      • 问题:ResNet34
      • 代码
        • 模型构建
        • 利用fashionmnist数据对网络进行训练
          • 数据读取
          • 模型编译
          • 模型训练
          • 模型评估
          • **遇到问题:tensorflow 里面fashion_mnist下载失败(超时)的问题**
    • 阶段总结

深度学习及图像分类阶段作业与阶段总结 深度学习作业 问题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 ShapeParam # ================================================================= 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 ShapeParam # ================================================================= conv2d_102 (Conv2D)multiple3200 _________________________________________________________________ batch_normalization_93 (Batc multiple256 _________________________________________________________________ activation (Activation)multiple0 _________________________________________________________________ max_pooling2d_3 (MaxPooling2 multiple0 _________________________________________________________________ resnet_block (ResnetBlock)multiple223104 _________________________________________________________________ resnet_block_1 (ResnetBlock) multiple1119360 _________________________________________________________________ resnet_block_2 (ResnetBlock) multiple5649152 _________________________________________________________________ resnet_block_3 (ResnetBlock) multiple17846784 _________________________________________________________________ global_average_pooling2d (Gl multiple0 _________________________________________________________________ dense_3 (Dense)multiple5130 ================================================================= 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路径下。
阶段总结 学完深度学习方面的内容,感觉之前学习的神经网络一些不懂得地方都突然豁然开朗,之前第一次学习真的是怀疑人生。。。。一开始认为卷积神经网络会很复杂,但是看完之后,认为只要掌握他里面的重要知识点,就会很容易掌握。所以当遇到当时学习的时候不会的,感觉很难的知识点时,可以稍微发一点脾气,出去玩放松放松,但是不能放弃,可以先暂时跳过,继续学习后面的,等未来再次接触时会有“柳暗花明又一村”的感觉!
【#|深度学习及图像分类阶段作业与阶段总结】学习完图像分类,感觉像是初入计算机视觉的大门,接下来我将学习目标检测方面的内容,学习重要的是坚持,为了完成毕设,坚持学习下去!

    推荐阅读