日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

【神经网络】(18) EfficientNetV2 代码复现,网络解析,附Tensorflow完整代码

發布時間:2023/11/27 生活经验 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【神经网络】(18) EfficientNetV2 代码复现,网络解析,附Tensorflow完整代码 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

各位同學好,今天和大家分享一下如何使用 Tensorflow 搭建 EfficientNetV2 卷積神經網絡模型。

EfficientNetV2 在 EfficientNetV1 的基礎上進行了改進,引入了Fused-MBConv模塊,和漸進式學習策略,訓練更快。本篇只介紹如何搭建網絡模型,訓練過程不做介紹。

EfficientNetV1 的文章在這,感興趣的可以看一下:https://blog.csdn.net/dgvv4/article/details/123553351

在EfficientNet中作者更關注準確率、參數數量、以及FLOPs,在EfficientNetV2中作者更關心模型的訓練速度。


1. EfficientNet 中存在的缺點:

(1)訓練圖像的尺寸很大時,訓練速度非常慢。

針對這個問題一個比較好想到的方法是降低訓練圖像的尺寸,卷各地訓練圖像的尺寸不僅能加快訓練速度,還能使用更大的batch_size

(2)在網絡淺層中使用深度卷積(Depthwise)的速度會很慢。

因為當前深度卷積(Depthwise Convolution)無法使用一些現有的加速器。雖然理論計算量很小,但實際使用起來沒有想象的那么快。因此作者引入Fused-MBConv模塊,將網絡淺層的MBConv模塊替換成Fused-MBConv模塊。

(3)同等的放大每個stage是次優的

在EfficientNetV1中,每個stage的深度和寬度都是同等放大的。單每個stage對網絡的訓練速度iji參數數量的貢獻并不相同,所以直接使用同等縮放的策略并不合理。因此作者采用了非均勻的縮放策略來縮放模型。


2. EfficientNetV2 的創新點

(1)引入新的網絡EfficientNetV2,該網絡在訓練速度以及參數量上都優于先前的一些網絡。

(2)提出改進的漸進學習方法,該方法會根據圖像的尺寸動態調節正則化方法,提升訓練速度和準確率。

(3)通過實驗與先前的一些網絡相比,訓練速度提升11倍,參數量減少1/6.8

與 EfficientNetV1 的區別

(1)在網絡淺層使用Fused-MBConv模塊,在深層使用MBConv模塊

(2)使用較小的通道上升倍數

(3)偏向使用更小的卷積核size(3*3)

(4)移除了EfficientNetV1中最后一個步距為1的stage


3. 網絡核心模塊

深度可分離卷積逆轉殘差結構、SE注意力機制就不再介紹了,之前的文章中已經詳細介紹過幾次了,有疑問的可以看:https://blog.csdn.net/dgvv4/article/details/123553351

3.1 Stochastic Depth

該Dopout方法和之前的隨機概率殺死神經元的Dropout方法不同。如下圖,前向傳播過程中,有許多殘差結構,主分支進行卷積操作,shortcut殘差連接輸入和輸出。

Stochastic Depth 有一定概率丟棄主分支的輸出結果,直接將上一層的輸出作為該層的輸出,相當于沒有這一層了,網絡的深度變得隨機,決定于丟棄了幾層。在EfficientNetV2中丟棄概率是0-0.2

這里的Stochastic Depth類型的Dropout層,僅用于Fused-MBConv模塊和MBConv模塊中的Dropout層,不包括網絡最后的全連接層的Dropout層

該方法提升了訓練速度,小幅提升了準確率。代碼中只需要比普通的dropout函數多添加一個參數即可。

x = layers.Dropout(rate = dropout_rate,  # 隨機丟棄輸出層的概率noise_shape = (None,1,1,1))  # 代表不是殺死神經元,是丟棄輸出層


3.2 MBConv模塊

基本模塊(stride=1):圖像輸入,先經過1x1卷積上升通道數;然后在高緯空間下使用深度卷積;再經過SE注意力機制優化特征圖數據;再經過1x1卷積下降通道數(使用線性激活函數);若此時輸入特征圖的shape和輸出特征圖的shape相同,那么對1x1卷積降維后的特征圖加一個 Stochastic Depth 類型的 Dropout層,防止過擬合;最后殘差連接輸入和輸出

下采樣模塊(stride=2):大致流程和基本模塊相同,不采用Dropout層和殘差連接,1x1卷積降維后直接輸出特征圖。

代碼實現:

#(3)逆轉殘差模塊
def MBConv(x, expansion, kernel_size, stride, out_channel, dropout_rate):'''expansion: 第一個卷積層特征圖通道數上升的倍數kernel_size: 深度卷積層的卷積核sizestride: 深度卷積層的步長out_channel: 第二個卷積層下降的通道數dropout_rate: Dropout層隨機丟棄輸出層的概率,直接將輸入接到輸出    '''# 殘差邊residual = x# 輸入特征圖的通道數in_channel = x.shape[-1]# ① 1*1標準卷積升維x = conv_block(inputs = x, filters = in_channel * expansion,  # 上升通道數為expansion倍 kernel_size = (1,1), stride = 1,activation = True)# ② 3*3深度卷積x = layers.DepthwiseConv2D(kernel_size = kernel_size,strides = stride,padding = 'same',use_bias = False)(x)x = layers.BatchNormalization()(x)x = swish(x)# ④ SE注意力機制,輸入特征圖x,和MBConv模塊輸入圖像的通道數x = se_block(inputs = x, in_channel = in_channel)# ⑤ 1*1標準卷積降維,使用線性激活x = conv_block(inputs = x,filters = out_channel,  # 上升通道數kernel_size = (1,1),stride = 1,activation = False)  # 不使用swish激活# ⑥ 只有步長=1且輸入等于輸出shape,才使用殘差連接輸入和輸出if stride == 1 and residual.shape == x.shape:# 判斷是否進行dropout操作if dropout_rate > 0:# 參數noise_shape一定的概率將某一層的輸出丟棄x = layers.Dropout(rate = dropout_rate,  # 丟棄概率noise_shape = (None,1,1,1))# 殘差連接輸入和輸出x = layers.Add([residual, x])return x# 如果步長=2,直接輸出1*1卷積降維后的結果return x

3.3 Fused-MBconv模塊

不用上升通道數(expansion == 1):圖像輸入,經過 3*3 標準卷積,對輸出特征圖使用?Stochastic Depth 類型的 Dropout層?步長=1且該模塊的輸入圖像和卷積輸出圖像的shape相同,使用殘差連接輸入和輸出;當步長=2下采樣階段,直接輸出卷積輸出的特征圖。

需要上升通道數(expansion != 1):圖像輸入,先使用 3*3 標準卷積上升通道數,再使用1*1卷積下降通道數,輸入特征圖經過?Stochastic Depth 類型的 Dropout層?步長=1且該模塊的輸入圖像和1*1卷積輸出圖像的shape相同,使用殘差連接輸入和輸出;當步長=2下采樣階段,直接輸出卷積輸出的特征圖。

代碼實現:

#(4)Fused-MBConv模塊
def Fused_MBConv(x, expansion, kernel_size, stride, out_channel, dropout_rate):    # 殘差邊residual = x# 輸入特征圖的通道數in_channel = x.shape[-1]# ① 如果通道擴展倍數expansion==1,就不需要升維if expansion != 1:# 3*3標準卷積升維x = conv_block(inputs = x, filters = in_channel * expansion,  # 通道數上升為原來的expansion倍 kernel_size = kernel_size, stride = stride)# ② 判斷卷積的類型# 如果expansion==1,變成3*3卷積+BN+激活;# 如果expansion!=1,變成1*1卷積+BN,步長為1x = conv_block(inputs = x, filters = out_channel, # FusedMBConv模塊輸出特征圖通道數kernel_size = (1,1) if expansion != 1 else kernel_size, stride = 1 if expansion != 1 else stride,activation = False if expansion != 1 else True)# ④ 當步長=1且輸入輸出shape相同時殘差連接if stride == 1 and residual.shape == x.shape:# 判斷是否使用Dropout層if dropout_rate > 0:x = layers.Dropout(rate = dropout_rate,  # 隨機丟棄輸出層的概率noise_shape = (None,1,1,1))  # 代表不是殺死神經元,是丟棄輸出層# 殘差連接輸入和輸出outputs = layers.Add([residual, x])return outputs# 若步長等于2,直接輸出卷積層輸出結果return x

4. 代碼展示

4.1 網絡結構圖

EfficientNetV2 網絡結構圖如下。opterator列中MBConv4代表上升通道數為原輸入通道數的4倍,channels代表每個模塊的輸出通道數,layers代表每個模塊重復執行多少次。


4.2 完整代碼

函數方法搭建網絡,代碼如下

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import Model, layers#(1)swish激活函數
def swish(x):x = x * tf.nn.sigmoid(x)return x#(2)標準卷積塊
def conv_block(inputs, filters, kernel_size, stride, activation=True):# 卷積+BN+激活x = layers.Conv2D(filters = filters, kernel_size = kernel_size, strides = stride,padding = 'same',use_bias = False)(inputs)x = layers.BatchNormalization()(x)if activation:  # 如果activation==True就使用激活函數x = swish(x)return x#(3)SE注意力機制
def se_block(inputs, in_channel, ratio=0.25):'''inputs: 深度卷積層的輸出特征圖input_channel: MBConv模塊的輸入特征圖的通道數ratio: 第一個全連接層的通道數下降為MBConv輸入特征圖的幾倍''' squeeze = int(in_channel * ratio)  # 第一個FC降低通道數個數excitation = inputs.shape[-1]  # 第二個FC上升通道數個數# 全局平均池化 [h,w,c]==>[None,c]x = layers.GlobalAveragePooling2D()(inputs)# [None,c]==>[1,1,c]x = layers.Reshape(target_shape=(1, 1, x.shape[-1]))(x)# [1,1,c]==>[1,1,c/4]x = layers.Conv2D(filters = squeeze, # 通道數下降1/4kernel_size = (1,1),strides = 1,padding = 'same')(x)x = swish(x)  # swish激活# [1,1,c/4]==>[1,1,c]x = layers.Conv2D(filters = excitation,  # 通道數上升至原來kernel_size = (1,1),strides = 1,padding = 'same')(x)x = tf.nn.sigmoid(x)  # sigmoid激活,權重歸一化# [h,w,c] * [1,1,c] ==> [h,w,c]outputs = layers.multiply([inputs, x])return outputs#(3)逆轉殘差模塊
def MBConv(x, expansion, kernel_size, stride, out_channel, dropout_rate):'''expansion: 第一個卷積層特征圖通道數上升的倍數kernel_size: 深度卷積層的卷積核sizestride: 深度卷積層的步長out_channel: 第二個卷積層下降的通道數dropout_rate: Dropout層隨機丟棄輸出層的概率,直接將輸入接到輸出    '''# 殘差邊residual = x# 輸入特征圖的通道數in_channel = x.shape[-1]# ① 1*1標準卷積升維x = conv_block(inputs = x, filters = in_channel * expansion,  # 上升通道數為expansion倍 kernel_size = (1,1), stride = 1,activation = True)# ② 3*3深度卷積x = layers.DepthwiseConv2D(kernel_size = kernel_size,strides = stride,padding = 'same',use_bias = False)(x)x = layers.BatchNormalization()(x)x = swish(x)# ④ SE注意力機制,輸入特征圖x,和MBConv模塊輸入圖像的通道數x = se_block(inputs = x, in_channel = in_channel)# ⑤ 1*1標準卷積降維,使用線性激活x = conv_block(inputs = x,filters = out_channel,  # 上升通道數kernel_size = (1,1),stride = 1,activation = False)  # 不使用swish激活# ⑥ 只有步長=1且輸入等于輸出shape,才使用殘差連接輸入和輸出if stride == 1 and residual.shape == x.shape:# 判斷是否進行dropout操作if dropout_rate > 0:# 參數noise_shape一定的概率將某一層的輸出丟棄x = layers.Dropout(rate = dropout_rate,  # 丟棄概率noise_shape = (None,1,1,1))# 殘差連接輸入和輸出x = layers.Add([residual, x])return x# 如果步長=2,直接輸出1*1卷積降維后的結果return x#(4)Fused-MBConv模塊
def Fused_MBConv(x, expansion, kernel_size, stride, out_channel, dropout_rate):    # 殘差邊residual = x# 輸入特征圖的通道數in_channel = x.shape[-1]# ① 如果通道擴展倍數expansion==1,就不需要升維if expansion != 1:# 3*3標準卷積升維x = conv_block(inputs = x, filters = in_channel * expansion,  # 通道數上升為原來的expansion倍 kernel_size = kernel_size, stride = stride)# ② 判斷卷積的類型# 如果expansion==1,變成3*3卷積+BN+激活;# 如果expansion!=1,變成1*1卷積+BN,步長為1x = conv_block(inputs = x, filters = out_channel, # FusedMBConv模塊輸出特征圖通道數kernel_size = (1,1) if expansion != 1 else kernel_size, stride = 1 if expansion != 1 else stride,activation = False if expansion != 1 else True)# ④ 當步長=1且輸入輸出shape相同時殘差連接if stride == 1 and residual.shape == x.shape:# 判斷是否使用Dropout層if dropout_rate > 0:x = layers.Dropout(rate = dropout_rate,  # 隨機丟棄輸出層的概率noise_shape = (None,1,1,1))  # 代表不是殺死神經元,是丟棄輸出層# 殘差連接輸入和輸出outputs = layers.Add([residual, x])return outputs# 若步長等于2,直接輸出卷積層輸出結果return x#(5)每個模塊重復執行num次
# Fused_MBConv模塊
def Fused_stage(x, num, expansion, kernel_size, stride, out_channel, dropout_rate):for _ in range(num):# 傳入參數,反復調用Fused_MBConv模塊x = Fused_MBConv(x, expansion, kernel_size, stride, out_channel, dropout_rate)return x# MBConv模塊
def stage(x, num, expansion, kernel_size, stride, out_channel, dropout_rate):for _ in range(num):# 反復執行MBConv模塊x = MBConv(x, expansion, kernel_size, stride, out_channel, dropout_rate)return x#(6)主干網絡
def efficientnetv2(input_shape, classes, dropout_rate):# 構造輸入層inputs = keras.Input(shape=input_shape)# 標準卷積層[224,224,3]==>[112,112,24]x = conv_block(inputs, filters=24, kernel_size=(3,3), stride=2)# [112,112,24]==>[112,112,24]x = Fused_stage(x, num=2, expansion=1, kernel_size=(3,3), stride=1, out_channel=24, dropout_rate=dropout_rate)# [112,112,24]==>[56,56,48]x = Fused_stage(x, num=4, expansion=4, kernel_size=(3,3), stride=2, out_channel=48, dropout_rate=dropout_rate)# [56,56,48]==>[32,32,64]x = Fused_stage(x, num=4, expansion=4, kernel_size=(3,3), stride=2, out_channel=64, dropout_rate=dropout_rate)# [32,32,64]==>[16,16,128]x = stage(x, num=6, expansion=4, kernel_size=(3,3), stride=2, out_channel=128, dropout_rate=dropout_rate)# [16,16,128]==>[16,16,160]x = stage(x, num=9, expansion=6, kernel_size=(3,3), stride=1, out_channel=160, dropout_rate=dropout_rate)# [16,16,160]==>[8,8,256]x = stage(x, num=15, expansion=6, kernel_size=(3,3), stride=2, out_channel=256, dropout_rate=dropout_rate)# [8,8,256]==>[8,8,1280]x = conv_block(x, filters=1280, kernel_size=(1,1), stride=1)# [8,8,1280]==>[None,1280]x = layers.GlobalAveragePooling2D()(x)# dropout層隨機殺死神經元if dropout_rate > 0:x = layers.Dropout(rate=dropout_rate)    # [None,1280]==>[None,classes]logits = layers.Dense(classes)(x)# 構建網絡model = Model(inputs, logits)return model#(7)接收網絡模型
if __name__ == '__main__':model = efficientnetv2(input_shape = [224,224,3], # 輸入圖像shape classes = 1000, # 分類數 dropout_rate = 0)model.summary()  # 查看網絡架構

4.3 查看網絡結構

通過model.summary()查看網絡架構,約有兩千萬的參數量

--------------------------------
dense (Dense)                   (None, 1000)         1281000     global_average_pooling2d_30[0][0]
==================================================================================================
Total params: 21,612,360
Trainable params: 21,458,488
Non-trainable params: 153,872
__________________________________________________________________________________________________

總結

以上是生活随笔為你收集整理的【神经网络】(18) EfficientNetV2 代码复现,网络解析,附Tensorflow完整代码的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。