本文為吳恩達教授的Tensorflow實踐系列課程的學(xué)習(xí)記錄。
完整代碼:https://github.com/YvanYan/keras/tree/master/part1-cnn
關(guān)于tensorflow的安裝碘饼,網(wǎng)上有許多博客講解的十分詳細(xì)墙懂,本文不再敘述昵宇。
本文內(nèi)容:
1.搭建一個簡單的神經(jīng)網(wǎng)絡(luò)
2.實現(xiàn)簡單的卷積神經(jīng)網(wǎng)絡(luò)
3.使用卷積神經(jīng)網(wǎng)絡(luò)處理真實圖片
1.搭建一個簡單的神經(jīng)網(wǎng)絡(luò)
首先加載數(shù)據(jù)集乳规,由于國內(nèi)網(wǎng)絡(luò)環(huán)境問題,因此是通過數(shù)據(jù)集鏈接將數(shù)據(jù)下載到本地合蔽,再進行加載怀骤。本地數(shù)據(jù)集是IDX文件格式费封,因此可以通過項目中loaddata.py文件進行讀取。
mnist = tf.keras.datasets.fashion_mnist
(train_imgs, train_labels), (test_imgs, test_labels) = mnist.load_data()
對數(shù)據(jù)進行歸一化蒋伦,因為每個像素值是0-255弓摘,所以將像素值歸一化成0-1。歸一化使網(wǎng)絡(luò)更好的收斂痕届,準(zhǔn)確率更高韧献。
training_images = training_images / 255.0
test_images = test_images / 255.0
搭建訓(xùn)練模型。Flatten表示將二維數(shù)據(jù)變成1維研叫,圖像數(shù)據(jù)是 28* 28锤窑,通過Flatten層后就變成了 784* 1。Dense表示神經(jīng)網(wǎng)絡(luò)中的層嚷炉,每一層需要指定神經(jīng)元的數(shù)量和激活函數(shù)渊啰。神經(jīng)元的數(shù)量在一定程度上可以提高準(zhǔn)確性,但會花費更多的時間申屹。對于簡單的數(shù)據(jù)集绘证,增加神經(jīng)元的數(shù)量并不能很明顯的提高準(zhǔn)確率。激活函數(shù)可以非線性的改變上一層的輸出結(jié)果哗讥,從而更好的擬合各種函數(shù)嚷那。各種常用的激活函數(shù)模型可以參考這篇博客。最后一層輸出層的神經(jīng)元數(shù)量為10杆煞,因為在這個數(shù)據(jù)集中魏宽,圖像是十分類問題,所有需要最后有十個不同的神經(jīng)元對應(yīng)不同的類別索绪。如果最后輸出層的神經(jīng)元數(shù)量少于分類數(shù)湖员,會報錯贫悄。
model = tf.keras.models.Sequential([tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation=tf.nn.relu),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)])
編譯瑞驱、訓(xùn)練和評估模型。compile來編譯網(wǎng)絡(luò)窄坦,需要指明優(yōu)化器和損失函數(shù)唤反。fit來訓(xùn)練網(wǎng)絡(luò)凳寺,傳入訓(xùn)練圖像、訓(xùn)練圖像標(biāo)簽彤侍、訓(xùn)練輪次肠缨。輪次越多準(zhǔn)確率越高,耗時越多盏阶,但簡單的問題輪次越多并不表示越好晒奕,因為網(wǎng)絡(luò)可能會過擬合,即在訓(xùn)練集表現(xiàn)極好名斟,但對于測試集表現(xiàn)一般脑慧,這樣的結(jié)果表示網(wǎng)絡(luò)的泛化能力較差。evaluate來評估網(wǎng)絡(luò)砰盐,給網(wǎng)絡(luò)輸入測試集合闷袒,測試集表示網(wǎng)絡(luò)從沒有接觸過的新圖像。從而測試網(wǎng)絡(luò)的準(zhǔn)確率岩梳。
model.compile(optimizer = tf.train.AdamOptimizer(),
loss = 'sparse_categorical_crossentropy')
model.fit(training_images, training_labels, epochs=5)
model.evaluate(test_images, test_labels)
2.實現(xiàn)簡單的卷積神經(jīng)網(wǎng)絡(luò)
卷積神經(jīng)網(wǎng)絡(luò)主要的層是卷積層和池化層囊骤。Conv2D第一個參數(shù)是希望生成的濾波器的數(shù)量,可以任意設(shè)置冀值,但最好以32的倍數(shù)也物。第二個參數(shù)是濾波器的尺寸。第三個參數(shù)的激活函數(shù)池摧,激活函數(shù)采用relu是因為在圖像中像素不能為負(fù)數(shù)焦除,所有relu保證了將所有的負(fù)數(shù)置為0。第四個參數(shù)為輸入數(shù)據(jù)的尺寸作彤,第一層的尺寸為圖像的尺寸膘魄。MaxPooling2D池化層是將圖像進行壓縮,只保留每個池化塊中的最大值竭讳。
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(64, (3,3), activation='relu', input_shape=(28, 28, 1)),
tf.keras.layers.MaxPooling2D(2, 2),
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
通過下圖可以看到模型每層的參數(shù),第一層的卷積層輸入的是(28绢慢,28灿渴,1),但是輸出的(26胰舆,26骚露,1)。這是因為卷積時沒有進行邊緣填充缚窿,所有左右上下更少了一個像素棘幸。池化層是(2,2)倦零,所以圖像尺寸變?yōu)樵瓉淼囊话搿?/p>
3.使用卷積神經(jīng)網(wǎng)絡(luò)處理真實圖片
真實圖像相比數(shù)據(jù)集更加復(fù)雜误续,且像素更多吨悍,因此構(gòu)建一個5層的卷積網(wǎng)絡(luò),初始輸入尺寸為(300蹋嵌,300育瓜,3)。在這個數(shù)據(jù)集中栽烂,圖像為二分類問題躏仇,所以最后輸出層只需要一個神經(jīng)元,輸出的是0-1的之間的數(shù)腺办,表示概率钙态。概率越接近1,表示圖像為人的概率越大菇晃,概率越接近0册倒,表示圖像為馬的概率越大。輸出層的激活函數(shù)為sigmoid磺送。
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(16, (3,3), activation='relu', input_shape=(300, 300, 3)),
tf.keras.layers.MaxPooling2D(2, 2),
tf.keras.layers.Conv2D(32, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(512, activation='relu'),
tf.keras.layers.Dense(1, activation='sigmoid')
])
使用keras中的圖像處理類來處理圖像驻子,ImageDataGenerator是keras.preprocessing.image模塊中的圖片生成器,可以每一次給模型“喂”一個batch_size大小的樣本數(shù)據(jù)估灿,同時也可以在每一個批次中對這batch_size個樣本數(shù)據(jù)進行增強崇呵,擴充數(shù)據(jù)集大小,增強模型的泛化能力馅袁。比如進行旋轉(zhuǎn)域慷,變形,歸一化等等汗销。
因為神經(jīng)網(wǎng)絡(luò)的輸入尺寸定義為(300犹褒,300,3)弛针,所以這里需要將圖像的尺寸定義為(300叠骑,300)。每個batch定義為128張圖片削茁。因為上面神經(jīng)網(wǎng)絡(luò)采用的損失函數(shù)是binary_crossentropy宙枷,所以我們需要二分類的標(biāo)簽。
from tensorflow.keras.preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator(rescale=1/255)
train_generator = train_datagen.flow_from_directory(
'/tmp/horse-or-human/',
target_size=(300, 300),
batch_size=128,
class_mode='binary')
使用fit_generator訓(xùn)練模型茧跋。verbose:日志顯示慰丛。verbose = 0 為不在標(biāo)準(zhǔn)輸出流輸出日志信息。verbose = 1 為輸出進度條記錄瘾杭。verbose = 2 為每個epoch輸出一行記錄诅病。注意: 默認(rèn)為 1。
history = model.fit_generator(
train_generator,
steps_per_epoch=8,
epochs=15,
verbose=1)
最后使用model.predict來對需要檢測的圖片進行測試。對于輸出的概率使用0.5最為分解數(shù)值睬隶,大于0.5判斷為人,小于0.5判斷為馬页徐。