tensorflow2實現resnet18和50網絡,最少代碼!!!

resnet網絡是一種使用了殘差網絡的結構,相較於普通的神經網絡在達到一定accuracy後會出現一定的下降,resnet解決了這個問題
對於初學cnn的人來說,這是一個非常好的上手模型,它的結構不復雜,實現起來也非常的容易,然而,爲了搞清如何使用tensorflow2實現resnet,
我百度了各種使用tensorflow2.0實現resnet的方法,雖然也搜到了幾個使用tensorflow2.0實現resnet網絡,但要麼只有resnet18,要麼使用tensorflow1實現的,並且由於我本身對於tensorflow2.0的不太熟悉,看了半天才勉強看懂,自己重寫卻總是出現各種錯誤,
於是我又花了好長時間從官網學習tensorflow2,終於我碼出來了resnet18和50的代碼,我自認爲實現的代碼數量以及精簡程度比其他人寫的稍微少一點,當然,這並不是說代碼的質量有多好,而是爲了對新手更友好點,
我希望將其分享出來,以備那些初學cnn以及對於tensorflow還不是特別熟悉的人,可以借鑑下我實現模型的寫法,希望新人們不會像我一樣卡在實現resnet模型的結點上,
這兩個模型我已經在我的數據集(一個4分類的1600張118*118的關於上下左右箭頭分類的圖片上)試驗過了,均可以達到100%的accuracy,因此,模型應該是沒有問題的
好了,話不多說,代碼奉上
resnet18:

import tensorflow as tf
import numpy as np
import os
from tensorflow import keras
from tensorflow.keras import layers,Sequential

class prepare(layers.Layer):
    def __init__(self):
        super(prepare, self).__init__()
        self.conv1=layers.Conv2D(64,(3,3),strides=1,padding="same")
        self.bn=layers.BatchNormalization()
        self.Relu=layers.Activation('relu')
        self.mp=layers.MaxPool2D(pool_size=(2,2),strides=2)
            
    def call(self,inputs):
        x=self.conv1(inputs)
        x=self.bn(x)
        x=self.Relu(x)
        x=self.mp(x)
        return x
class BasicBlock(layers.Layer):
    def __init__(self,filter_num,stride=1):
        super(BasicBlock, self).__init__()
        self.conv1=layers.Conv2D(filter_num,(3,3),strides=stride,padding='same')
        self.bn1=layers.BatchNormalization()
        self.relu=layers.Activation('relu')
        self.conv2=layers.Conv2D(filter_num,(3,3),strides=1,padding='same')
        self.bn2 = layers.BatchNormalization()

        if stride!=1:
            self.downsample=Sequential()
            self.downsample.add(layers.Conv2D(filter_num,(1,1),strides=stride))
        else:
            self.downsample=lambda x:x
    def call(self,input,training=None):
        out=self.conv1(input)
        out=self.bn1(out)
        out=self.relu(out)

        out=self.conv2(out)
        out=self.bn2(out)

        identity=self.downsample(input)
        output=layers.add([out,identity])
        output=tf.nn.relu(output)
        return output
def get_model(num_classes):
    
    input_image = layers.Input(shape=(112, 112, 3), dtype="float32")
    output=prepare()(input_image)
    output=BasicBlock(64)(output)
    output=BasicBlock(64)(output)
    output=BasicBlock(128,2)(output)
    output=BasicBlock(128)(output)
    output=BasicBlock(256,2)(output)
    output=BasicBlock(256)(output)
    output=BasicBlock(512,2)(output)
    output=BasicBlock(512)(output)
    output=layers.GlobalAveragePooling2D()(output)
    output=layers.Dense(num_classes)(output)
    output-layers.Activation('relu')(output)
    return  keras.Model(inputs=input_image, outputs=output)

 

 

 resnet50:

import tensorflow as tf
import numpy as np
import os
from tensorflow import keras
from tensorflow.keras import layers,Sequential

class prepare(layers.Layer):
    
    def __init__(self):
        super(prepare, self).__init__()
        self.conv1=layers.Conv2D(64,(3,3),strides=1,padding="same")
        self.bn=layers.BatchNormalization()
        self.Relu=layers.Activation('relu')
        self.mp=layers.MaxPool2D(pool_size=(2,2),strides=2)
            
    def call(self,inputs):
        x=self.conv1(inputs)
        x=self.bn(x)
        x=self.Relu(x)
        x=self.mp(x)
        return x
class block(layers.Layer):    
    def __init__(self,filter_num,stride=1,is_first=False):
        super(block,self).__init__()
        self.conv1=layers.Conv2D(filter_num,(1,1),strides=1)
        self.bn1=layers.BatchNormalization()
        
        self.conv2=layers.Conv2D(filter_num,(3,3),strides=stride,padding='same')
        self.bn2=layers.BatchNormalization()
        
        self.conv3=layers.Conv2D(filter_num*4,(1,1),strides=1)
        self.bn3=layers.BatchNormalization()
        
        self.relu=layers.Activation('relu')
        if stride!=1 or is_first==True:
            self.downsample=Sequential()
            self.downsample.add(layers.Conv2D(filter_num*4,(1,1),strides=stride))
        else:
            self.downsample=lambda x:x
    def call(self,inputs):
        x=self.conv1(inputs)
        x=self.bn1(x)
        x=self.relu(x)
        
        x=self.conv2(x)
        x=self.bn2(x)
        x=self.relu(x)
        
        x=self.conv3(x)
        x=self.bn3(x)
        
        identity=self.downsample(inputs)
        output=layers.add([x,identity])
        output=tf.nn.relu(output)
        return output
        
def get_model(num_classes):
    input_image = layers.Input(shape=(112, 112, 3), dtype="float32")
    out=prepare()(input_image)
    out=block(64,is_first=True)(out)
    out=block(64)(out)
    out=block(64)(out)
    out=block(128,stride=2)(out)
    out=block(128)(out)
    out=block(128)(out)
    out=block(256,stride=2)(out)
    out=block(256)(out)
    out=block(256)(out)
    out=block(512,stride=2)(out)
    out=block(512)(out)
    out=block(512)(out)
    out=layers.GlobalAveragePooling2D()(out)
    out=layers.Dense(num_classes)(out)
    out-layers.Activation('relu')(out)
    return keras.Model(inputs=input_image, outputs=out)
 

需要注意的是,prepare類是對數據的預處理,論文是先使用7x7的過濾器的,我這裏使用的是3x3,因爲我輸入的圖片是

112*112大小的,如果需要改的話改prepare就行了

 

 

以上就是resnet的tensorflow1實現,代碼是不是可以接受呢,是不是能看懂呢,

只要輸入model=get_model(num_classes)就能得到模型拉,num_calsses是你分類的數量

之後定義好損失函數,使用fit訓練就可以了,

同時,因爲大多數數據集要麼是量大,要麼是分類的數量大,普通的筆記本基本是訓練不了的,

必須得專門的gpu訓練纔可,我這裏從別人那裏得到了一份1600張的4分類上下左右箭頭的圖片,如果需要的話私聊我哦

最後,附上一張resnet結構圖,

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章