【小白學(xué)PyTorch】擴(kuò)展之Tensorflow2.0 | 21 Keras的API詳解(上)卷積、激活、初始化、正則
擴(kuò)展之Tensorflow2.0 | 20 TF2的eager模式與求導(dǎo)
擴(kuò)展之Tensorflow2.0 | 19 TF2模型的存儲與載入
擴(kuò)展之Tensorflow2.0?| 18 TF2構(gòu)建自定義模型
擴(kuò)展之Tensorflow2.0?| 17 TFrec文件的創(chuàng)建與讀取
擴(kuò)展之Tensorflow2.0?| 16 TF2讀取圖片的方法
擴(kuò)展之Tensorflow2.0?| 15 TF2實(shí)現(xiàn)一個簡單的服裝分類任務(wù)
小白學(xué)PyTorch | 14 tensorboardX可視化教程
小白學(xué)PyTorch | 13 EfficientNet詳解及PyTorch實(shí)現(xiàn)
小白學(xué)PyTorch | 12 SENet詳解及PyTorch實(shí)現(xiàn)
小白學(xué)PyTorch | 11 MobileNet詳解及PyTorch實(shí)現(xiàn)
小白學(xué)PyTorch | 10 pytorch常見運(yùn)算詳解
小白學(xué)PyTorch | 9 tensor數(shù)據(jù)結(jié)構(gòu)與存儲結(jié)構(gòu)
小白學(xué)PyTorch | 8 實(shí)戰(zhàn)之MNIST小試牛刀
小白學(xué)PyTorch | 7 最新版本torchvision.transforms常用API翻譯與講解
小白學(xué)PyTorch | 6 模型的構(gòu)建訪問遍歷存儲(附代碼)
小白學(xué)PyTorch | 5 torchvision預(yù)訓(xùn)練模型與數(shù)據(jù)集全覽
小白學(xué)PyTorch | 4 構(gòu)建模型三要素與權(quán)重初始化
小白學(xué)PyTorch | 3 淺談Dataset和Dataloader
小白學(xué)PyTorch | 2 淺談訓(xùn)練集驗(yàn)證集和測試集
小白學(xué)PyTorch | 1 搭建一個超簡單的網(wǎng)絡(luò)
小白學(xué)PyTorch | 動態(tài)圖與靜態(tài)圖的淺顯理解
參考目錄:
1 Keras卷積層
1.1 Conv2D
1.2 SeparableConv2D
1.3 Conv2DTranspose
2 Keras參數(shù)初始化
2.1 正態(tài)分布
2.2 均勻分布
2.3 截尾正態(tài)分布
2.4 常數(shù)
2.5 Xavier/Glorot
2.6 自定義初始化
3 Keras激活函數(shù)
3.1 relu
3.2 sigmoid
3.3 softmax
3.4 softplus
3.5 softsign
3.6 tanh
3.7 selu
4 Keras的L1/L2正則
4.1 L1/L2正則
4.2 自定義正則化
我們對Keras應(yīng)該已經(jīng)有了一個直觀、宏觀的認(rèn)識了?,F(xiàn)在,我們來系統(tǒng)的學(xué)習(xí)一下Keras的一些關(guān)于網(wǎng)絡(luò)層的API,本文的主要內(nèi)容是圍繞卷積展開的,包含以下的內(nèi)容:
不同類型的卷積層; 不同的參數(shù)初始化方式; 不同的激活函數(shù); 增加L1/L2正則; 不同的池化層; 多個Normalization層; 其他的常用層。
本文內(nèi)容較多,對于API的學(xué)習(xí)了解即可。
1 Keras卷積層
Keras的卷積層和PyTorch的卷積層,都包括1D、2D和3D的版本,1D就是一維的,2D是圖像,3D是立體圖像。這里就用最常見的2D圖像來做講解,1D和3D和2D基本相同,不多贅述。
1.1 Conv2D
先看Conv2D的所有參數(shù):
tf.keras.layers.Conv2D(
????filters,
????kernel_size,
????strides=(1,?1),
????padding="valid",
????data_format=None,
????dilation_rate=(1,?1),
????groups=1,
????activation=None,
????use_bias=True,
????kernel_initializer="glorot_uniform",
????bias_initializer="zeros",
????kernel_regularizer=None,
????bias_regularizer=None,
????activity_regularizer=None,
????kernel_constraint=None,
????bias_constraint=None,
????**kwargs
)
先看一個簡單的例子:
import tensorflow as tf
input_shape = (4, 28, 28, 3)
x = tf.random.normal(input_shape)
y = tf.keras.layers.Conv2D(
filters=2,kernel_size=3,
activation='relu',padding='same'
)
print(y(x).shape)
>>> (4, 28, 28, 2)
現(xiàn)在來看參數(shù)含義:
filter: 一個int整數(shù),輸出特征圖的通道數(shù); kernel_size:一個int整數(shù),卷積核大?。?/section> strides:一個整數(shù)或者是(a,b)這樣的list,表示卷積核是否跳步; padding: 'valid'表示沒有padding,'same'表示輸出和輸入特征圖的尺寸相同;只有這兩種選擇data_format: 'channels_last'或者是'channels_first'。默認(rèn)是'channels_last',表示特征圖的最后一個維度是通道,(batch_size, height, width, channels) ;如果選擇了'channels_first'表示每一個樣本的第一個維度是通道,所以特征圖的格式和PyTorch的格式相同,(batch_size, channels, height, width)。dilation_rate:碰撞卷積的設(shè)置,默認(rèn)是1,1就是一般的卷積。需要注意的是dilation_rate和stride目前不支持同時不為1,換句話說,如果要膨脹卷積的話,那么stride必須是1; groups;分組卷積; activation:這個表示,可以直接在卷積層后面設(shè)置一個激活層,比方說 'relu',這個在后面的章節(jié)會詳細(xì)講解目前Keras支持的所有激活層,如果什么都不填入,則不使用激活層use_bias:一個bool參數(shù),True表示使用bias,默認(rèn)是True; kernel_initializer:卷積核的初始化的方法,這個會在后面的章節(jié)詳細(xì)講解; bias_initializer:偏置的初始化的方法,這個會在后面的章節(jié)詳細(xì)講解; kernel_regularizer:卷積核的正則化的方法,在后面的章節(jié)會詳細(xì)講解; bias_regularizer:偏置的正則化的方法,在后面的章節(jié)會詳細(xì)講解;
1.2 SeparableConv2D
Keras直接提供了深度可分離卷積層,這個層其實(shí)包含兩個卷積層(了解深度可分離卷積的應(yīng)該都知道這個吧),一層是depthwise,一層是pointwise。
這個SeparableConv2D的參數(shù)也很多,與Conv2D有很多重復(fù)的參數(shù),就不多加贅述了:
tf.keras.layers.SeparableConv2D(
????filters,
????kernel_size,
????strides=(1,?1),
????padding="valid",
????data_format=None,
????dilation_rate=(1,?1),
????depth_multiplier=1,
????activation=None,
????use_bias=True,
????depthwise_initializer="glorot_uniform",
????pointwise_initializer="glorot_uniform",
????bias_initializer="zeros",
????depthwise_regularizer=None,
????pointwise_regularizer=None,
????bias_regularizer=None,
????activity_regularizer=None,
????depthwise_constraint=None,
????pointwise_constraint=None,
????bias_constraint=None,
????**kwargs
)
參數(shù)詳解:
depth_multiplier:depthwise卷積之后,一般會增多通道數(shù)。比方說輸入通道是16個,那么輸出通道數(shù)64個,然后再輸入到pointwise卷積層。這個depth_multiplier就是depthwise卷積層的通道數(shù)的擴(kuò)增系數(shù),在上面的例子中這個擴(kuò)增系數(shù)是4; depthwise_initializer和pointwise_initializer不用多說,就是兩個卷積層的卷積核的初始化的方法。
但是這個深度可分離卷積完全可以用一般的Conv2D來構(gòu)建,所以其實(shí)在用到深度可分離卷積的時候,自己會重新構(gòu)建一個這樣的網(wǎng)絡(luò)層
1.3 Conv2DTranspose
對于上采樣,這種方法應(yīng)該并不陌生。Transposed convolution有的時候也被稱為Deconvolution去卷積
tf.keras.layers.Conv2DTranspose(
????filters,
????kernel_size,
????strides=(1,?1),
????padding="valid",
????output_padding=None,
????data_format=None,
????dilation_rate=(1,?1),
????activation=None,
????use_bias=True,
????kernel_initializer="glorot_uniform",
????bias_initializer="zeros",
????kernel_regularizer=None,
????bias_regularizer=None,
????activity_regularizer=None,
????kernel_constraint=None,
????bias_constraint=None,
????**kwargs
)
參數(shù)詳解:
output_padding:一個整數(shù)或者list,用來給輸出的特征圖增加一個padding的效果,默認(rèn)是None,不添加padding;
對于去卷積,可能會比較生疏,這里多講幾個例子
1.3.1 去卷積的例子1
import?tensorflow?as?tf
from?tensorflow?import?keras
input_shape?=?(4,?28,?28,?3)
x?=?tf.random.normal(input_shape)
y?=?keras.layers.Conv2DTranspose(
????filters=10,kernel_size=3,strides=1,padding='same')
print(y(x).shape)
>>>?(4,?28,?28,?10)
但是假如我們?nèi)サ袅?code style="padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 100, 65);">padding=‘same’
input_shape?=?(4,?28,?28,?3)
x?=?tf.random.normal(input_shape)
y?=?keras.layers.Conv2DTranspose(
????filters=10,kernel_size=3,strides=1)
print(y(x).shape)
>>>?(4,?30,?30,?10)
這是因?yàn)槿ゾ矸e的卷積核的中心是從原特征圖的邊界之外開始計(jì)算的。一個3乘3的卷積核,那么當(dāng)卷積核的右下角與原特征圖的左上角重合的時候,去卷積的就已經(jīng)進(jìn)行了一次運(yùn)算,而一般的卷積是只有當(dāng)卷積核的全部都與原特征圖重合的時候,才進(jìn)行計(jì)算的。(這里的講解不太細(xì)致,因?yàn)橹霸谄渌奈恼轮幸呀?jīng)講過去卷積的詳細(xì)過程了)。
1.3.2 去卷積的例子2
現(xiàn)在把stride改成2
input_shape?=?(4,?28,?28,?3)
x?=?tf.random.normal(input_shape)
y?=?keras.layers.Conv2DTranspose(
????filters=10,kernel_size=3,strides=2)
print(y(x).shape)
>>>?(4,?57,?57,?10)
假如加上padding='same'
input_shape?=?(4,?28,?28,?3)
x?=?tf.random.normal(input_shape)
y?=?keras.layers.Conv2DTranspose(
????filters=10,kernel_size=3,strides=2,padding='same')
print(y(x).shape)
>>>?(4,?56,?56,?10)
所以一般情況下,使用的參數(shù)是strides=2,padding='same',這樣特征圖的尺寸就剛好放大一倍。
2 Keras參數(shù)初始化
把之前提到的簡單的例子,增加卷積核和偏置的初始化:
import?tensorflow?as?tf
input_shape?=?(4,?28,?28,?3)
initializer?=?tf.keras.initializers.RandomNormal(mean=0.,?stddev=1.)
x?=?tf.random.normal(input_shape)
y?=?tf.keras.layers.Conv2D(
????filters=2,kernel_size=3,
????activation='relu',padding='same',
????kernel_initializer=initializer,
????bias_initializer=initializer
)
print(y(x).shape)
>>>?(4,?28,?28,?2)
簡單的說,就是先定義一個初始化器initializer,然后把這個初始化器作為參數(shù)傳給Keras.Layers就行了。
2.1 正態(tài)分布
tf.keras.initializers.RandomNormal(mean=0.0, stddev=0.05, seed=None)
2.2 均勻分布
tf.keras.initializers.RandomUniform(minval=-0.05, maxval=0.05, seed=None)
2.3 截尾正態(tài)分布
tf.keras.initializers.TruncatedNormal(mean=0.0, stddev=0.05, seed=None)
基本和正態(tài)分布一樣,但是如果隨機(jī)的取值是在距離均值兩個標(biāo)準(zhǔn)差的這個范圍之外的,那么會重新取值。
換句話說,初始化的數(shù)值會被限制在均值正負(fù)兩個標(biāo)準(zhǔn)差的范圍內(nèi)
2.4 常數(shù)
tf.keras.initializers.Zeros()
tf.keras.initializers.Ones()
2.5 Xavier/Glorot
tf.keras.initializers.GlorotNormal(seed=None)
這個本質(zhì)是一個截尾正態(tài)分布,但是GlorotNormal(又稱Xavier),是一個以0為均值,標(biāo)準(zhǔn)差計(jì)算公式是:
是in和out表示輸入和輸出神經(jīng)元數(shù)目的數(shù)目。如果是之前已經(jīng)學(xué)習(xí)過或者看過我寫的關(guān)于Xavier初始化的論文筆記的朋友,可能會發(fā)現(xiàn)論文中使用的是一個均勻分布而不是正態(tài)分布。
均勻分布的初始化如下:tf.keras.initializers.GlorotUniform(seed=None)
這個均勻分布是我們講的:
這個Xavier方法,也是Keras默認(rèn)的初始化的方法
2.6 自定義初始化
當(dāng)然,Keras也是支持自定義初始化的方法的。
import?tensorflow?as?tf
class?ExampleRandomNormal(tf.keras.initializers.Initializer):
def?__init__(self,?mean,?stddev):
??self.mean?=?mean
??self.stddev?=?stddev
def?__call__(self,?shape,?dtype=None)`:
??return?tf.random.normal(
??????shape,?mean=self.mean,?stddev=self.stddev,?dtype=dtype)
def?get_config(self):??#?To?support?serialization
??return?{'mean':?self.mean,?'stddev':?self.stddev}
關(guān)鍵就是在__call__中返回一個和輸入?yún)?shù)shape大小相同的一個tf張量就行了。
3 Keras激活函數(shù)
基本支持了所有的常見激活函數(shù)。在卷積層的參數(shù)activation中,可以輸入relu,sigmoid,softmax等下面的字符串的形式,全部小寫。
3.1 relu
tf.keras.activations.relu(x, alpha=0.0, max_value=None, threshold=0)
alpha就是斜率,如果是0.1,則變成leakyReLU; max_value是ReLU的上界,如果是None則沒有上界; threshold是ReLU的下界,小于下界的都會被置0,一般默認(rèn)是0.
3.2 sigmoid
tf.keras.activations.sigmoid(x)
函數(shù)方程:
3.3 softmax
tf.keras.activations.softmax(x, axis=-1)
3.4 softplus
tf.keras.activations.softplus(x)
計(jì)算公式:
3.5 softsign
tf.keras.activations.softsign(x)
計(jì)算公式:
3.6 tanh
tf.keras.activations.tanh(x)
計(jì)算公式:
3.7 selu
tf.keras.activations.selu(x)
如果,返回; 如果,返回; scale和是事先設(shè)置的數(shù)值,alpha=1.67216214,scale=1.05070098 與elu激活函數(shù)類似,但是多了有個scale系數(shù), 2017年的一篇論文提出selu,elu是2016年提出的
4 Keras的L1/L2正則
正則化就比較簡單,不是L1就是L2,再或者兩者都有。
4.1 L1/L2正則
from?tensorflow.keras?import?layers
from?tensorflow.keras?import?regularizers
layer?=?layers.Dense(
????units=64,
????kernel_regularizer=regularizers.l1_l2(l1=1e-5,?l2=1e-4),
)
這里的正則化,可以使用:
tf.keras.regularizers.l1_l2(l1=1e-5, l2=1e-4)tf.keras.regularizers.l2(1e-4)tf.keras.regularizers.l1(1e-5)
關(guān)于L1和L2的計(jì)算細(xì)節(jié):
L1:L1正則就是 L2:L1正則就是
4.2 自定義正則化
class?MyRegularizer(tf.keras.regularizers.Regularizer):
????def?__init__(self,?strength):
????????self.strength?=?strength
????def?__call__(self,?x):
????????return?self.strength?*?tf.reduce_sum(tf.square(x))
????????
????def?get_config(self):
????????return?{'strength':?self.strength}
這個實(shí)現(xiàn)的是L2正則的。其中的get_config是用來保存模型數(shù)據(jù)的,不要的話也沒事,只是不能序列化的保存模型(不用使用config或者json來存儲模型)。
- END -往期精彩回顧
