乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      【TensorFlow2.0】如何搭建網(wǎng)絡(luò)模型?

       有三AI 2020-11-27

      大家好,這是專欄《TensorFlow2.0》的第四篇文章,講述網(wǎng)絡(luò)模型的搭建。

      我們知道在不考慮輸入層的情況下,一個(gè)典型的卷積神經(jīng)網(wǎng)絡(luò)通常由若干個(gè)卷積層、激活層、池化層及全連接層組成,無論是最經(jīng)典的LeNet5,還是前兩天剛出現(xiàn)的MobileNet V3,無一不都包含這些層。今天就帶大家學(xué)習(xí)下如何使用TensorFlow2.0搭建卷積神經(jīng)網(wǎng)絡(luò)模型。

      作者&編輯 | 湯興旺 

      上一期,我們講解了如何使用TensorFlow2.0從自己的磁盤讀取數(shù)據(jù),今天我們就來看看如何使用層來搭建網(wǎng)絡(luò)。

      1 使用Keras API構(gòu)建網(wǎng)絡(luò)模型架構(gòu)

      在Keras API中,定義網(wǎng)絡(luò)是比較簡單的,我們主要用到的就是Sequential類下面看看如何具體使用它來定義網(wǎng)絡(luò):

      from tensorflow.keras import Sequential

      conv_net = Sequential([

              layers.Dense(32,activation = "relu",input_shape = (784,)),

              layers.Dense(10,activation = "softmax")])

      我們可以把Sequential理解為一個(gè)容器,然后把layers搭建的每層模型都送進(jìn)這個(gè)容器中,構(gòu)成整個(gè)網(wǎng)絡(luò)模型。值得注意的layers搭建的每層模型要想放進(jìn)這個(gè)容器中必須是list結(jié)構(gòu)。

      另外我們需要搭建的卷積層,全連接層,池化層等都在layers這個(gè)類中。下面我們看一個(gè)包含卷積層,全連接層,池化層比較完整的結(jié)構(gòu),如下:

      from tensorflow.keras import Sequential

      conv_layers = [
         #units1
         layers.Conv2D(64, kernel_size=[3,3],padding="same",activation = tf.nn.relu),
         layers.Conv2D(64, kernel_size=[3,3],padding="same",activation = tf.nn.relu),
         layers.MaxPool2D(pool_size=[2,2],strides=2,padding="same"),

         #units2
         layers.Conv2D(128, kernel_size=[3,3],padding="same",activation = tf.nn.relu),
         layers.Conv2D(128, kernel_size=[3,3],padding="same",activation = tf.nn.relu),
         layers.MaxPool2D(pool_size=[2,2],strides=2,padding="same"),

         #units3
         layers.Conv2D(256, kernel_size=[3,3],padding="same",activation = tf.nn.relu),
         layers.Conv2D(256, kernel_size=[3,3],padding="same",activation = tf.nn.relu),
         layers.Conv2D(256, kernel_size=[3,3],padding="same",activation = tf.nn.relu),
         layers.MaxPool2D(pool_size=[2,2],strides=2,padding="same"),

         #units4
         layers.Conv2D(512, kernel_size=[3,3],padding="same",activation = tf.nn.relu),
         layers.Conv2D(512, kernel_size=[3,3],padding="same",activation = tf.nn.relu),
         layers.Conv2D(512, kernel_size=[3,3],padding="same",activation = tf.nn.relu),
         layers.MaxPool2D(pool_size=[2,2],strides=2,padding="same"),

         #units5
         layers.Conv2D(512, kernel_size=[3,3],padding="same",activation = tf.nn.relu),
         layers.Conv2D(512, kernel_size=[3,3],padding="same",activation = tf.nn.relu),
         layers.Conv2D(512, kernel_size=[3,3],padding="same",activation = tf.nn.relu),
         layers.MaxPool2D(pool_size=[2,2],strides=2,padding="same")]

      conv_net =Sequential(conv_layers)

      fc_net = Sequential([
         layers.Dense(4096,activation=tf.nn.relu),
         layers.Dense(4096, activation=tf.nn.relu),
         layers.Dense(1000, activation=None),
      ])

      上面的模型中我們首先通過layers.Conv2D()、layers.MaxPool2D()構(gòu)建模型的卷積網(wǎng)絡(luò)層conv_layers,注意看我是把這個(gè)層放在了一個(gè)list中的,然后我把這個(gè)list即conv_layers放進(jìn)了Sequential這個(gè)容器構(gòu)建成了卷積網(wǎng)絡(luò)conv_net。

      卷積層完成構(gòu)建后,我們通過layers.Dense添加全連接層,這樣一個(gè)完整的結(jié)構(gòu)就完成了。

      基本的模型完成了搭建后,我們看前向處理是怎么做的,即數(shù)據(jù)如何從卷積層一步步傳到最后的全連接層,最后輸出一個(gè)預(yù)測值。

      out = conv_net(x)

      out = tf.reshape(out, [-1, 512])

      logits = fc_net(out)

      上面我們假設(shè)輸入x是[1,32,32,3],即1張3通道大小為32*32的圖片,經(jīng)過卷積層后的輸出為out,現(xiàn)在我們看看out是多少,查看方法如下:

      x = tf.random.normal([1,32,32,3])
      out = conv_net(x)
      print(out.shape)

      我們通過上面的代碼很容易得到out.shape = [1,1,1,512]

      為了能將卷積后的結(jié)果與全連接層相連,我們需要將它展平,即out = tf.reshape(out, [-1, 512]),最后我們將打平后的結(jié)果傳遞到全連接層網(wǎng)絡(luò)fc_net得到預(yù)測值。

      上面我們通過Sequential類完成了一個(gè)完整的模型搭建,你掌握了嗎?

      2 定義自己的網(wǎng)絡(luò)層架構(gòu)

      上面我們通過Sequential類完成了一個(gè)簡單的線性模型的搭建,下面我們看如何搭建自己的一個(gè)模型(非線性模型)。這里我們以ResNet系列網(wǎng)絡(luò)為例。

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

      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,inputs,training=None):
             out = self.conv1(inputs)
             out = self.bn1(out)
             out =self.relu(out)
             out = self.conv2(out)
             out = self.bn2(out)
             identity = self.downsample(inputs)
             output = layers.add([out,identity])
             output = tf.nn.relu(output)
             return output

      class ResNet(keras.Model):
         def __init__(self,layer_dims,num_classe=100):
             super(ResNet,self).__init__()

            #預(yù)處理層
             self.stem = Sequential([layers.Conv2D(64,(3,3),strides=(1,1)),
                                     layers.BatchNormalization(),
                                     layers.Activation("relu"),
                                     layers.MaxPool2D(pool_size=(2,2),strides=(1,1),padding="same")])
             self.layer1 = self.build_resblock(64,layer_dims[0])
             self.layer2 = self.build_resblock(128, layer_dims[1],stride=2)
             self.layer3 = self.build_resblock(256, layer_dims[2], stride=2)
             self.layer4 = self.build_resblock(512, layer_dims[3], stride=2)
             self.avgpool = layers.GlobalAveragePooling2D()
             self.fc = layers.Dense(num_classe)

         def call(self, inputs, training=None):
             x = self.stem(inputs)
             x = self.layer1(x)
             x = self.layer2(x)
             x = self.layer3(x)
             x = self.layer4(x)
             x = self.avgpool(x)
             x = self.fc(x)
             return x

         def build_resblock(self,filter_num,blocks,stride=1):
             #filter_num是卷積核的數(shù)量,blocks是basic_block的數(shù)量
             res_blocks=Sequential()
             res_blocks.add(BasicBlock(filter_num,stride))
             for _ in range(1,blocks):
                 res_blocks.add(BasicBlock(filter_num,stride=1))
             return res_blocks
      def resnet18():
         return ResNet([2,2,2,2])

      def resnet34():
         return ResNet([3,4,6,3])

      我們知道在ResNet中有一個(gè)基本的單元叫做basicBlock

      多個(gè)basicBlock的疊加就組成了resblock,而ResNet系列網(wǎng)絡(luò)就是由多個(gè)不同resBlock組成的。

      上面的代碼中我們定義了一個(gè)基本的類basicBlock,它必須繼承l(wèi)ayers.Layer或者keras.Model這個(gè)類,也就是說所有的網(wǎng)絡(luò)自定義都會繼承這個(gè)類中的一個(gè),并實(shí)現(xiàn)super方法,如下:

      super(BasicBlock,self).__init__()

      basicBlock基本結(jié)構(gòu)完成后,我們需要實(shí)現(xiàn)前向運(yùn)算,即call函數(shù),如下:

      def call(self,inputs,training=None):
             out = self.conv1(inputs)
             out = self.bn1(out)
             out =self.relu(out)
             out = self.conv2(out)
             out = self.bn2(out)
             identity = self.downsample(inputs)
             output = layers.add([out,identity])
             output = tf.nn.relu(output)
             return output

      從上面的代碼可以看出call函數(shù)是比較簡單的,串接各個(gè)網(wǎng)絡(luò)層就可以了,這里不再詳細(xì)說明。這樣我們r(jià)esnet的基本結(jié)構(gòu)basicBlock就完成了構(gòu)建。后面的resBlock實(shí)際上就是BasicBlock的疊加,實(shí)現(xiàn)的方法是一樣的,就是定義個(gè)基本的類,并繼承l(wèi)ayers.Layer或者keras.Model這個(gè)類,再實(shí)現(xiàn)super方法。最后通過call函數(shù)完成前向運(yùn)算。

      總結(jié)

      本期我們詳細(xì)介紹了如何使用TensorFlow2.0完成網(wǎng)絡(luò)模型的搭建。

      下期預(yù)告:使用TensorFlow2.0完成從模型自定義到測試。

        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多