iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 8
1
AI & Data

30天只學U-net系列 第 8

[day-08] 番外 - U-net的程式碼實現 (1) - Conv2D

前言

受到end-to-end model 所賜,非資工領域的人可以很容易實現各種Model (例如我)。然而我們還是需要了解model的架構才能知道如何設計的。

架構與程式碼交叉解釋

以下我們會搭配圖與程式碼一同解釋別人如何實現Unet的。我參考的開源程式碼是這篇zhixuhao
的U-net
,實現的程式碼蠻簡潔的而且可讀性很是不錯。
https://ithelp.ithome.com.tw/upload/images/20200920/20112571sVJYDmgyLi.png

為了配合文章,我們從model.py這個檔案開始說明起:

import numpy as np 
import os
import skimage.io as io
import skimage.transform as trans
import numpy as np
from keras.models import *
from keras.layers import *
from keras.optimizers import *
from keras.callbacks import ModelCheckpoint, LearningRateScheduler
from keras import backend as keras

主要的import 包含 numpy, os, skimage, keras。

skimage: 也是個影像處理的庫,有點像OPENCV,庫也是超大的。
keras: 是tensorflow 的的高級API,所以如果要用keras,需要裝tensorflow。
os: 路徑控制庫
numpy: 數學運算庫/可以與keras, skimage等一起使用。

def unet(pretrained_weights = None,input_size = (256,256,1)):

首先這是一個2D U-net, 所以只能輸入一個channel的資料,大小是256*256

第一層 CNN

conv1 = Conv2D(64, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(inputs)

這是一個可讀性比較低的寫法,但學習這個其實還蠻簡單的。廢話不多說,直接讀文件

tf.keras.layers.Conv2D(
    filters, # 要產生 feature map 的數量
    kernel_size, # kernal size
    strides=(1, 1), # 卷積的步幅
    padding="valid", # 是否要填充邊界
    data_format=None, # 上一層的結構
    dilation_rate=(1, 1), # 卷積的擴張率
    groups=1, # 如果有多通道,要拆成幾組做convolution
    activation=None, # 激活函數
    use_bias=True, # 卷積的時候是否有常數項
    kernel_initializer="glorot_uniform", # 權重初始化
    bias_initializer="zeros", # 偏權初始化
    kernel_regularizer=None, # 是否要對kernal regularizer
    bias_regularizer=None, # 是否要對bias regularizer
    activity_regularizer=None, #是否要對 activity regularizer
    kernel_constraint=None, # 是否對kernel應用 constraint
    bias_constraint=None, # 是否對bias應用 constraint
    **kwargs # etc...
)

呵呵,捅了馬蜂窩啦~~~好多東西不會啊!!

開始解釋各參數的意義。
https://ithelp.ithome.com.tw/upload/images/20200922/20112571DQkVPP83Cn.png

filters: int
代表filters要應用的數量,代表會產生多少個feature map,如果數字是64,就代表第一次convolution 會產生64個feature map。
padding: string
代表周圍是否要補0,如果不補,size會變小,變小(keneral size -1)的大小,我們可以知道,paper與程式碼在這邊的策略不同,但是理論上不太影響訓練成果。
kernel_initializer:string
初始化方法,有一篇文章有詳細的介紹,這個方法是根據權重tensor的數量 (理解成矩陣/向量的元素數量) (fan_in)
標準差為 sqrt(2/fan_in) , 平均為0 的隨機亂數。

有一點要注意

inputs = Input((256,256,1))
conv1 = Conv2D(64, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')
print(type(conv1))
conv1 = Conv2D(64, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(inputs)
print(type(conv1))

output

<class 'keras.layers.convolutional.Conv2D'>
<class 'tensorflow.python.framework.ops.Tensor'>

第一種寫法代表我建立的一個convolution layer
第二種寫法代表建立了相對應的tensor

結語

Conv2D 這個function已經略懂略懂,接下來再來看看有那些值得注意的結構吧。

參考文獻

[1] zhixuhao's unet
[2] 2D Covolution layers
[3] henormal
[4] initializers


上一篇
[day-07] 第3段 introduction - 初探U-net
下一篇
[day-09] 番外 - U-net的程式碼實現 (2) - pooling
系列文
30天只學U-net30

尚未有邦友留言

立即登入留言