動手學深度學習學習筆記tf2.0版(5.7 使用重複元素的網絡(VGG))

在這裏插入圖片描述
在這裏插入圖片描述

import tensorflow as tf
import os

print(tf.__version__)

VGG塊的組成規律是:連續使用數個相同的填充爲1、窗口形狀爲 3×3 的卷積層後接上一個步幅爲2、窗口形狀爲 2×2 的最大池化層。卷積層保持輸入的高和寬不變,而池化層則對其減半。我們使用vgg_block函數來實現這個基礎的VGG塊,它可以指定卷積層的數量num_convs和輸出通道數num_channels

# 定義一個重複使用的vgg_block塊

def vgg_block(net, num_convs, num_channels):
    # 參數說明:num_convs:卷積的個數,num_channels爲卷積核的個數, num_convs個卷積核+maxpool2d
    for _ in range(num_convs):
        net.add(tf.keras.layers.Conv2D(num_channels,kernel_size=3,
                                    padding='same',activation='relu'))

    net.add(tf.keras.layers.MaxPool2D(pool_size=2, strides=2))
    return net

conv_arch = ((1, 64), (1, 128), (2, 256), (2, 512), (2, 512))
# 當然也可以自己自定義layer層,但是學會使用Sequential方式堆疊規範的層,更加簡單方便

def vgg_net(conv_arch):
    vgg = tf.keras.models.Sequential()
    for n, k in conv_arch:
        vgg_block(vgg,n, k)
    # 注意 sequential.add() 可以直接添加一個疊加層,但是這個疊加層會作爲一個整體,這裏就逐個添加了,方便展示模型結構
#         net.add(tf.keras.models.Sequential([tf.keras.layers.Flatten(),
#              tf.keras.layers.Dense(4096,activation='relu'),
#              tf.keras.layers.Dropout(0.5),
#              tf.keras.layers.Dense(4096,activation='relu'),
#              tf.keras.layers.Dropout(0.5),
#              tf.keras.layers.Dense(10,activation='sigmoid')]))
    vgg.add(tf.keras.layers.Flatten())
    vgg.add(tf.keras.layers.Dense(4096,activation='relu'))
    vgg.add(tf.keras.layers.Dropout(0.5))
    vgg.add(tf.keras.layers.Dense(4096,activation='relu'))
    vgg.add(tf.keras.layers.Dropout(0.5))
    vgg.add(tf.keras.layers.Dense(10,activation='sigmoid'))
    return vgg

vgg = vgg_net(conv_arch)
vgg
X = tf.random.uniform((1,224,224,1))
for blk in vgg.layers:
    X = blk(X)
    print(blk.name, 'output shape:\t', X.shape)

因爲VGG-11計算上比AlexNet更加複雜,出於測試的目的我們構造一個通道數更小,或者說更窄的網絡在Fashion-MNIST數據集上進行訓練。

ratio = 8
# 將每個卷積層的輸出通道數較少爲 1/ 8
small_conv_arch = [(pair[0], pair[1] // ratio) for pair in conv_arch]
net = vgg_net(small_conv_arch)
# 獲取數據
from tensorflow.keras.datasets import fashion_mnist
import matplotlib.pyplot as plt


(x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()

# 熟悉一下,tf.image.resize_with_pad 函數
def resize(x):
    x = tf.cast(x, tf.float32)
    x = tf.reshape(x, (x.shape[0], x.shape[1], 1))
    x = tf.image.resize_with_pad(image=x, target_height=100, target_width=100, method='bilinear')
    x = tf.squeeze(x)
    return x

img = x_train[0]
img2 = resize(img)
plt.imshow(img)
plt.figure(figsize=(5,5))
plt.show()
plt.figure(figsize=(5,5))
plt.imshow(img2)
plt.show()
# 數據預處理
def data_scale(x, y):
    x = tf.cast(x, tf.float32)
    x = x / 255.0
    x = tf.reshape(x, (x.shape[0], x.shape[1], 1))
    x = tf.image.resize_with_pad(image=x, target_height=224,target_width=224)
    
    return x, y
# 由於筆記本訓練太慢了,使用1000條數據,跑一下先,算力夠的可以直接使用全部數據更加明顯
train_db = tf.data.Dataset.from_tensor_slices((x_train[0:1000],y_train[0:1000])).shuffle(20).map(data_scale).batch(128)
test_db = tf.data.Dataset.from_tensor_slices((x_test[0:1000],y_test[0:1000])).shuffle(20).map(data_scale).batch(128)
# 定義優化器和損失函數
optimizer = tf.keras.optimizers.Adam(lr=1e-1)
loss = tf.keras.losses.sparse_categorical_crossentropy
net.compile(optimizer=optimizer, loss=loss, metrics=['accuracy'])
net.fit_generator(train_db, epochs=5, validation_data=test_db)    # 這裏就不跑太多輪了,有機器可以自己調參跑個好的結果
net.summary()
# net.save('vgg.h5')
X = tf.random.uniform((1,224,224,1))

for blk in vgg.layers:
    print('input shape:\t', X.shape)
    X = blk(X)
    print(blk.name, 'output shape:\t', X.shape)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章