【寫(xiě)在前面】
作為一名終身學(xué)習(xí)實(shí)踐者,我持之以恒地學(xué)習(xí)各種深度學(xué)習(xí)和機(jī)器學(xué)習(xí)的新知識(shí)。一個(gè)無(wú)聊的假日里我突然想到:反正一樣要記筆記,為什么不把我學(xué)習(xí)的筆記寫(xiě)成博客供大家一起交流呢?于是,我就化身數(shù)據(jù)女俠,打算用博客分享的方式開(kāi)啟我的深度學(xué)習(xí)深度學(xué)習(xí)之旅。本文僅供學(xué)習(xí)交流使用,侵權(quán)必刪,不用于商業(yè)目的,轉(zhuǎn)載須注明出處。
【學(xué)習(xí)筆記】
之前我們以邏輯回歸 (logistic regression) 為例介紹了神經(jīng)網(wǎng)絡(luò)(吳恩達(dá)Coursera Deep Learning學(xué)習(xí)筆記 1 (上)),但它并沒(méi)有隱藏層,所以并不算嚴(yán)格意義上的神經(jīng)網(wǎng)絡(luò)。在本文中,讓我們隨著Andrew一起深化神經(jīng)網(wǎng)絡(luò),在sigmoid之前再增加一些ReLU神經(jīng)元。最后我們會(huì)以瘋狂收到AI科學(xué)家迷戀的可愛(ài)貓咪圖案為例,用深度學(xué)習(xí)建立一個(gè)貓咪圖案的識(shí)別模型。不過(guò)在這之前,讓我們來(lái)看一下除了上次說(shuō)到的sigmoid和ReLU之外,還有什么激活函數(shù)、他們之間又各有什么優(yōu)劣——
激活函數(shù) Activation Functions
1) sigmoid
除了在輸出層(當(dāng)輸出是{0,1}的binary classification時(shí))可能會(huì)用到之外,隱藏層中很少用到sigmoid,因?yàn)樗膍ean是0.5,同等情況下用均值為0的tanh函數(shù)取代。
2) tanh
其實(shí)就是sigmoid的shifted版本,但輸出從(0, 1)變?yōu)?-1, 1),所以下一層的輸入是centered,更受歡迎。
3) ReLU (Rectified Linear Unit)
在吳恩達(dá)Coursera Deep Learning學(xué)習(xí)筆記 1 (上)中提到過(guò)ReLU激活函數(shù),它在深度學(xué)習(xí)中比sigmoid和tanh更常用。這是因?yàn)楫?dāng)激活函數(shù)的輸入z的值很大或很小的時(shí)候,sigmoid和tanh的梯度非常小,這會(huì)大大減緩梯度下降的學(xué)習(xí)速度。所以與sigmoid和tanh相比,ReLU的訓(xùn)練速度要快很多。
4) Leaky ReLU
Leaky ReLU比ReLU要表現(xiàn)得稍微好一丟丟但是實(shí)踐中大家往往都用ReLU。
從淺神經(jīng)網(wǎng)絡(luò)到深神經(jīng)網(wǎng)絡(luò)
最開(kāi)始的邏輯回歸的例子中,并沒(méi)有隱藏層。在接下來(lái)的課程中,Andrew分別介紹了1個(gè)隱藏層、2個(gè)隱藏層和L個(gè)隱藏層的神經(jīng)網(wǎng)絡(luò)。但是只要把前向傳播和反向傳播搞明白了,再加上之后會(huì)講述的一些小撇步,就會(huì)發(fā)現(xiàn)其實(shí)都是換湯不換藥。大家準(zhǔn)備好了嗎?和我一起深呼吸再一頭扎進(jìn)深度學(xué)習(xí)的海洋吧~
一般輸入層是不計(jì)入神經(jīng)網(wǎng)絡(luò)的層數(shù)的,如果一個(gè)神經(jīng)網(wǎng)絡(luò)有L層,那么就意味著它有L-1個(gè)隱藏層和1個(gè)輸出層。我們可以觀察到輸入層和輸出層,但是不容易觀察到中間數(shù)據(jù)是怎么變化的,因此在輸入和輸出層之間的部分叫隱藏層。
訓(xùn)練一個(gè)深神經(jīng)網(wǎng)絡(luò)大致分為以下步驟(吳恩達(dá)Coursera Deep Learning學(xué)習(xí)筆記 1 (上)也有詳細(xì)說(shuō)明):
1. 定義神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)(超參數(shù))
2. 初始化參數(shù)
3. 循環(huán)迭代
? ? 3.1 在前向傳播中,分為linear forward和activation forward。在linear forward中,Z[l]=W[l]A[l?1]+b[l],其中A[0]=X;在activation forward中,A[l]=g(Z[l])。期間要儲(chǔ)存W、b、Z的值。最后算出當(dāng)前的Loss。
? ? 3.2 在反向傳播中,分為activation backward和linear backward。
? ? 3.3 更新參數(shù)。
下圖展現(xiàn)了一個(gè)L層的深度神經(jīng)網(wǎng)絡(luò)、其中L-1個(gè)隱藏層都用的是ReLU激活函數(shù)的訓(xùn)練步驟和過(guò)程。
標(biāo)注聲明 Notations:
隨著神經(jīng)網(wǎng)絡(luò)的模型越來(lái)越深,我們會(huì)有L-1個(gè)隱藏層,每一層都用小寫(xiě)的L即[l]標(biāo)注為上標(biāo)。z是上一層的輸出(即這一層的輸入)的線(xiàn)性組合,a是這一層通過(guò)激活函數(shù)對(duì)z的非線(xiàn)性變化,也叫激活值 (activation values)。訓(xùn)練數(shù)據(jù)中有m個(gè)樣本,每一個(gè)樣本都用(i)來(lái)標(biāo)注為上標(biāo)。每一個(gè)隱藏層l里都有n[l](上標(biāo)內(nèi)是小寫(xiě)的L不是1)個(gè)神經(jīng)元,每一個(gè)神經(jīng)元都用i標(biāo)注為下標(biāo)。
超參數(shù)
隨著我們的深度學(xué)習(xí)模型越來(lái)越復(fù)雜,我們要學(xué)習(xí)區(qū)分普通參數(shù) (Parameters) 和超參數(shù) (Hyperparameters)。 在上圖的標(biāo)注聲明中出現(xiàn)的W和b是普通的參數(shù),而超參數(shù)是指:
學(xué)習(xí)速率 (learning rate) alpha、循環(huán)次數(shù) (# iterations)、隱藏層層數(shù) (# hidden layers) L、每隱藏層中的神經(jīng)元數(shù)量 (size of the hidden layers) n[l] ——上標(biāo)內(nèi)是小寫(xiě)的L不是1、激活函數(shù) (choice of activation functions) g[l] ——上標(biāo)內(nèi)是小寫(xiě)的L不是1。除了這些超參數(shù)之外,之后還會(huì)學(xué)習(xí)到以下超參數(shù):動(dòng)量 (momentum)、小批量更新的樣本數(shù) (minibatch size)、正則化系數(shù) (regularization weight),等等。
隨機(jī)初始化 Random Initialization
吳恩達(dá)Coursera Deep Learning學(xué)習(xí)筆記 1 (上)中的邏輯回歸 (logistic regression) 中沒(méi)有隱藏層,所以將W直接初始化為0并無(wú)大礙。但是在初始化隱藏層的W時(shí)如果將每個(gè)神經(jīng)元的權(quán)重都初始化為0,那么在之后的梯度下降中,每一個(gè)神經(jīng)元的權(quán)重都會(huì)有相同的梯度和更新,這樣的對(duì)稱(chēng)在梯度下降中永遠(yuǎn)無(wú)法打破,如此就算隱藏層中有一千一萬(wàn)個(gè)神經(jīng)元,也只同于一個(gè)神經(jīng)元。所以,為了打破這種對(duì)稱(chēng)的魔咒,在初始化參數(shù)時(shí)往往會(huì)加入一些微小的抖動(dòng),即用較小的隨機(jī)數(shù)來(lái)初始化W,偏置項(xiàng)b可以初始化為0或者同樣是較小的隨機(jī)數(shù)。在Python中,可以用np.random.randn(a,b) * 0.01來(lái)隨機(jī)地初始化a*b的W矩陣,并用np.zeros((a, 1))來(lái)初始化a*1的b矩陣。
為什么是0.01呢?同sigmoid和tanh中所說(shuō),數(shù)據(jù)科學(xué)家通常會(huì)從將W initialize為很小的隨機(jī)數(shù),防止訓(xùn)練的速度過(guò)緩。但是如果神經(jīng)網(wǎng)絡(luò)很深的話(huà),0.01這樣小的數(shù)字未必最理想。但是總體來(lái)說(shuō),人們還是傾向于從較小的參數(shù)開(kāi)始訓(xùn)練。
承接上面的超參數(shù),對(duì)于每個(gè)隱藏層中的神經(jīng)元數(shù)量,我們可以將這幾個(gè)超參數(shù)設(shè)定為layer_dims的array,如layer_dims = [n_x, 4,3,2,1] 說(shuō)明輸入的X有n_x個(gè)特征,第一層有4個(gè)神經(jīng)元,第二層有3個(gè)神經(jīng)元,第三層有2個(gè),最后一個(gè)輸出單元。有一個(gè)容易搞錯(cuò)的地方,就是W[l]是n[l]*n[l-1]的矩陣,b[l]是n[l]*1的矩陣。所以初始化W和b就可以寫(xiě)成:
for l in range(1, L):
parameters["W"+str(l)] = np.random.randn(layer_dims[l],layer_dims[l-1])*0.01
parameters["b"+str(l)] =np.zeros((layer_dims[l],1))
詳見(jiàn)例2中的initialize_parameters_deep函數(shù)。
并不是很復(fù)雜有沒(méi)有!那么,下面我們一起跟著Andrew來(lái)看幾個(gè)神經(jīng)網(wǎng)絡(luò)的例子——
【例 1】用單個(gè)隱藏層的神經(jīng)網(wǎng)絡(luò)來(lái)分類(lèi)平面數(shù)據(jù)
第三課的例子是Planar data classification with one hidden layer,即幫助大家搭建一個(gè)上圖所示的淺神經(jīng)網(wǎng)絡(luò)(Shallow Neural Networks):一個(gè)4個(gè)單元的隱藏層 (tanh) 加一個(gè)sigmoid的輸出層。
最后一步的prediction是用了0.5的cutoff,很簡(jiǎn)單:
最后的決策邊界如下圖,在訓(xùn)練數(shù)據(jù)上的精確度為90%,是不是比logistic regression表現(xiàn)強(qiáng)多啦?可見(jiàn)logistic regression不能學(xué)習(xí)到數(shù)據(jù)中的非線(xiàn)性關(guān)系,而神經(jīng)網(wǎng)絡(luò)可以(哪怕是本例中一個(gè)非常淺的神經(jīng)網(wǎng)絡(luò))。
其實(shí)本例中的模型也很簡(jiǎn)單,如果再?gòu)?fù)雜些可以做到更精確,但是可能會(huì)overfit,畢竟從上圖中可以看出現(xiàn)有的模型已經(jīng)抓住了數(shù)據(jù)中的大趨勢(shì)。下面嘗試了在隱藏層中設(shè)置不同個(gè)數(shù)的神經(jīng)元,來(lái)看模型的精確度和決策邊界是如何變化的:
Accuracy for 1 hidden units: 67.5 %
Accuracy for 2 hidden units: 67.25 %
Accuracy for 3 hidden units: 90.75 %
Accuracy for 4 hidden units: 90.5 %
Accuracy for 5 hidden units: 91.25 %
Accuracy for 20 hidden units: 90.0 %
Accuracy for 50 hidden units: 90.25 %
可以看到,在訓(xùn)練數(shù)據(jù)上,5個(gè)神經(jīng)元的精確度是最高的,而當(dāng)神經(jīng)元數(shù)超過(guò)20時(shí),決策邊界就顯示有overfitting的情況了。不過(guò)沒(méi)事,之后會(huì)學(xué)習(xí)正則化 (regularization),能使很復(fù)雜的神經(jīng)網(wǎng)絡(luò)都不會(huì)出現(xiàn)overfitting。
這個(gè)例子的代碼很簡(jiǎn)單,就不貼了。
【例 2】L層深度神經(jīng)網(wǎng)絡(luò)
第四節(jié)課的例子有三個(gè):第一是一個(gè)ReLU+sigmoid的淺層神經(jīng)網(wǎng)絡(luò),是為了后面的例子做鋪墊;第二個(gè)將其深化,用了L-1個(gè)ReLU層,輸出層也是sigmoid;第三個(gè)例子就是用前兩個(gè)神經(jīng)網(wǎng)絡(luò)訓(xùn)練貓咪識(shí)別模型[吐血]。我將L層的模型和其貓咪識(shí)別器的訓(xùn)練過(guò)程精簡(jiǎn)地說(shuō)一下。
設(shè)計(jì)神經(jīng)網(wǎng)絡(luò)與隨機(jī)初始化參數(shù)
下圖就是我們要搭建的L層神經(jīng)網(wǎng)絡(luò),不過(guò)在這之前,讓我們先挑個(gè)lucky number方便以后重復(fù)訓(xùn)練結(jié)果^_^
np.random.seed(1)
其次,讓我們?cè)O(shè)計(jì)一下我們的神經(jīng)網(wǎng)絡(luò)。因?yàn)榧せ詈瘮?shù)已經(jīng)確定用ReLU了,所以在本例中我們只需設(shè)計(jì)layer_dims,就能確定輸入的維度、層數(shù)和每層的神經(jīng)元數(shù)。
def initialize_parameters_deep(layer_dims):
? ? parameters = {}
? ? L = len(layer_dims) ? ? ? ? ? ? ? ? ? ? ?# 根據(jù)我們一開(kāi)始設(shè)計(jì)的模型超參數(shù),讀取L(其實(shí)是L+1)
? ? for l in range(1, L): ? ? ? ? ? ? ? ? ? ? ? # 設(shè)定W1到W(L-1)和b1和b(L-1),一共有L-1層(其實(shí)是L)
? ? ? ? parameters['W' + str(l)] = np.random.randn(layer_dims[l], layer_dims[l-1]) * 0.01
? ? ? ? parameters['b' + str(l)] = np.zeros((layer_dims[l], 1))
? ? assert(parameters['W' + str(l)].shape == (layer_dims[l], layer_dims[l-1]))
? ? assert(parameters['b' + str(l)].shape == (layer_dims[l], 1))
? ? return parameters
和具體的數(shù)據(jù)結(jié)合,就知道了輸入的維度和樣本的數(shù)量。假設(shè)我們的訓(xùn)練數(shù)據(jù)中有209張圖片,每張都是64*64像素,那么輸入特征數(shù)n_x就是64*64*3 = 12288,m就是209,如下圖:
如果我們將W和b參數(shù)設(shè)為parameters,每一個(gè)初始化的W和b都是parameters這個(gè)list中的一個(gè)元素,那么L-1個(gè)循環(huán)隱藏層其實(shí)就是len(parameters)//2。下圖是一個(gè)ReLU層加一個(gè)sigmoid層的一個(gè)loop,怎么將同樣的計(jì)算復(fù)制到我們的L層深度神經(jīng)網(wǎng)絡(luò)中呢?
前向傳播
前向傳播分為linear forward和activation forward,前者計(jì)算Z,后者計(jì)算A=g(Z),g視激活函數(shù)的不同而不同。因?yàn)閍ctivation forward這步中包括了linear的值,所以名為linear_activation_forward函數(shù)。由于反向傳播的梯度計(jì)算中會(huì)用到W、b、A的值,所以我們將每一個(gè)iteration中將每個(gè)神經(jīng)元的這些值暫時(shí)儲(chǔ)存在caches這個(gè)大列表中,再在下一輪循環(huán)中覆蓋掉。代碼如下:
def linear_forward(A, W, b):
? ? Z = np.dot(W, A) + b
? ? assert(Z.shape == (W.shape[0], A.shape[1]))
? ? cache = (A, W, b)
? ? return Z, cachedef linear_activation_forward(A_prev, W, b, activation):
? ? if activation == "sigmoid":
? ? ? ? Z, linear_cache = linear_forward(A_prev, W, b)
? ? ? ? A, activation_cache = sigmoid(Z)
? ? elif activation == "relu":
? ? ? ? Z, linear_cache = linear_forward(A_prev, W, b)
? ? ? ? A, activation_cache = relu(Z)
? ? assert (A.shape == (W.shape[0], A_prev.shape[1]))
? ? cache = (linear_cache, activation_cache)
? ? return A, cache
在定義了每一個(gè)神經(jīng)單元的linear-activation forward之后,我們來(lái)定義這個(gè)L層神經(jīng)網(wǎng)絡(luò)的前向傳播:
def L_model_forward(X, parameters):
? ? caches = []
? ? A = X
? ? L = len(parameters) // 2? ? ? ? ? ? ? ? ? # 因?yàn)橹霸O(shè)定的parameters包含了每一層W和b的初始值,所以層數(shù)是這個(gè)列表長(zhǎng)度的一半
? ? for l in range(1, L): ? ? ? ? ? ? ? ? ? ? ? ? ?# L-1個(gè)隱藏層用ReLU激活函數(shù)
? ? ? ? A_prev = A
? ? ? ? A, cache = linear_activation_forward(A_prev, parameters['W' + str(l)], parameters['b' + str(l)], activation = "relu")
? ? ? ? caches.append(cache)
? ? AL, cache = linear_activation_forward(A, parameters['W' + str(L)], parameters['b' + str(L)], activation = "sigmoid") ? ? ? ? ? ?# 第L個(gè)層用sigmoid函數(shù)
? ? caches.append(cache)
? ? assert(AL.shape == (1,X.shape[1]))
? ? return AL, caches
前向傳播的盡頭是計(jì)算當(dāng)前參數(shù)下的損失~不過(guò)正如在后面L_model_backward函數(shù)中看到的,我們這里直接計(jì)算dL/dAL,并不計(jì)算L,這里計(jì)算cost是為了在訓(xùn)練過(guò)程檢查代價(jià)是不是在穩(wěn)定下降,以確保我們使用了合適的學(xué)習(xí)率。
def compute_cost(AL, Y):
? ? m = Y.shape[1]
? ? cost = -np.sum(Y*np.log(AL) + (1-Y)*np.log(1-AL))/m
? ? cost = np.squeeze(cost) ? ? ? ? ? ? ? ? ? ? ? ? ? ?# 將類(lèi)似于?[[17]] 的cost變成 17
? ? assert(cost.shape == ())
? ? return cost
反向傳播
反向傳播和前向傳播的函數(shù)設(shè)計(jì)是對(duì)稱(chēng)的,但是會(huì)比前向傳播復(fù)雜一丟丟,需要小心各種線(xiàn)性代數(shù)中的運(yùn)算規(guī)則——這也是為什么在前向傳播中我們都在return前加入了維度檢查(assert + shape)。下圖顯示了每一個(gè)神經(jīng)元在反向傳播中的輸入和輸出。現(xiàn)在我們看到之前在前向傳播中緩存的用處了。如果我不儲(chǔ)存W和Z的值,我就沒(méi)有辦法在反向線(xiàn)性傳播中計(jì)算dW,db同理。
def linear_backward(dZ, cache):
? ? A_prev, W, b = cache
? ? m = A_prev.shape[1]
? ? dW = np.dot(dZ, A_prev.T)/m
? ? db = np.sum(dZ, axis=1, keepdims=True)/m
? ? dA_prev = np.dot(W.T, dZ)
? ? assert (dA_prev.shape == A_prev.shape)
? ? assert (dW.shape == W.shape)
? ? assert (db.shape == b.shape)
? ? return dA_prev, dW, db
上述的公式用線(xiàn)性代數(shù)表示為下圖:
Andrew貼心地為大家提供了寫(xiě)好的函數(shù):relu_backward和sigmoid_backward,如果我們自己寫(xiě)的話(huà),需要在前向傳播中儲(chǔ)存A的值,否則在很多反向傳播中就不知道dA/dZ,因?yàn)橛行┘せ詈瘮?shù)的導(dǎo)數(shù)是A的函數(shù),比如sigmoid函數(shù)和tanh函數(shù)。
def linear_activation_backward(dA, cache, activation):
? ? linear_cache, activation_cache = cache
? ? if activation == "relu":
? ? ? ? dZ = relu_backward(dA, activation_cache)
? ? ? ? dA_prev, dW, db = linear_backward(dZ, linear_cache)
? ? elif activation == "sigmoid":
? ? ? ? dZ = sigmoid_backward(dA, activation_cache)
? ? ? ? dA_prev, dW, db = linear_backward(dZ, linear_cache)
? ? return dA_prev, dW, db
同前向傳播一樣,我們將dL/dAL反向傳播,通過(guò)每一層的linear-activation backward構(gòu)建整個(gè)完整的反向傳播體系:
def L_model_backward(AL, Y, caches):
? ? grads = {}
? ? L = len(caches) # 層數(shù)
? ? m = AL.shape[1]
? ? Y = Y.reshape(AL.shape) # 改變Y的維度,確保其與AL的維度統(tǒng)一
? ? dAL = - (np.divide(Y, AL) - np.divide(1 - Y, 1 - AL)) # 代價(jià)函數(shù)對(duì)輸出層輸出AL的導(dǎo)數(shù),就不計(jì)算具體的cost了
? ? current_cache = caches[L-1]
? ? grads["dA" + str(L)], grads["dW" + str(L)], grads["db" + str(L)] = linear_activation_backward(dAL, current_cache, activation = "sigmoid")
? ? for l in reversed(range(L-1)):
? ? ? ? current_cache = caches[l]
? ? ? ? dA_prev_temp, dW_temp, db_temp = linear_activation_backward(grads["dA"+str(l+2)], current_cache, activation = "relu")
? ? ? ? grads["dA" + str(l + 1)] = dA_prev_temp
? ? ? ? grads["dW" + str(l + 1)] = dW_temp
? ? ? ? grads["db" + str(l + 1)] = db_temp
? ? return grads
一般現(xiàn)實(shí)工作中不會(huì)用線(xiàn)性代數(shù)如此折磨你,就算要自己一步一步這么寫(xiě),也可以加入梯度檢查等等來(lái)為你增添信心,具體以后再分享~
參數(shù)更新
至此我們已經(jīng)在一個(gè)循環(huán)中計(jì)算出了當(dāng)前W和b的梯度,最后就是用梯度下降的定義更新參數(shù)。在下一個(gè)例子中我們會(huì)看到如何用我們已經(jīng)寫(xiě)好的每一步的函數(shù),使用for loop執(zhí)行梯度下降,最后得到訓(xùn)練好的模型。
def update_parameters(parameters, grads, learning_rate):
? ? L = len(parameters) // 2
? ? for l in range(L):
? ? ? ? parameters["W" + str(l+1)] = parameters["W" + str(l+1)] - learning_rate*grads["dW" + str(l + 1)]
? ? ? ? parameters["b" + str(l+1)] = parameters["b" + str(l+1)] - learning_rate*grads["db" + str(l + 1)]
? ? return parameters
【例 3】繼續(xù)AI科學(xué)家對(duì)貓的執(zhí)念……
下面我們用例2中的L層深度神經(jīng)網(wǎng)絡(luò)來(lái)識(shí)別一張圖是不是貓咪[捂臉],因?yàn)榇a有點(diǎn)多所以分成了2和3的兩個(gè)例子。
假設(shè)train_x_orig是我們?cè)嫉妮斎耄呀?jīng)將圖片像素?cái)?shù)據(jù)提取并flatten為適合訓(xùn)練的數(shù)據(jù),這里我們將每一個(gè)樣本從64*64*3的輸入變成一個(gè)12288*1的矢量,然后將值標(biāo)準(zhǔn)化到0-1之間:
train_x_flatten = train_x_orig.reshape(train_x_orig.shape[0], -1).T
train_x = train_x_flatten/255.
設(shè)計(jì)一個(gè)神經(jīng)網(wǎng)絡(luò):layers_dims = [12288, 20, 7, 5, 1],即每個(gè)樣本有12288個(gè)像素輸入,第一層20個(gè)ReLU神經(jīng)元,第二層7個(gè),第三層5個(gè),最后一個(gè)sigmoid。
終于可以調(diào)用我們之前辛辛苦苦寫(xiě)好的函數(shù)啦!之前寫(xiě)的函數(shù)都是每一個(gè)iteration中的每一步驟,現(xiàn)在我們將每一個(gè)loop循環(huán)num_iterations次。
parameters = initialize_parameters_deep(layers_dims)
for i in range(0, num_iterations):
? ? AL, caches = L_model_forward(X, parameters)
? ? cost = compute_cost(AL, Y)
? ? grads = L_model_backward(AL, Y, caches)
? ? parameters = update_parameters(parameters, grads, learning_rate)
這里的parameters就是訓(xùn)練好的參數(shù),我們就可以用它來(lái)預(yù)測(cè)新的萌萌噠貓貓啦。
讀取一張num_px*num_px圖片的像素再將其RGB轉(zhuǎn)換為num_px*num_px*3的方法,請(qǐng)注意這里的圖片尺寸需和訓(xùn)練數(shù)據(jù)中的一樣:
fname = "images/" + my_image
np.array(ndimage.imread(fname, flatten=False))
scipy.misc.imresize(image, size=(num_px,num_px)).reshape((num_px*num_px*3,1))
最后我們的模型在訓(xùn)練數(shù)據(jù)上的精確度為98.6%。然后我們就可以用類(lèi)似于predict(test_x, test_y, parameters)這樣的方法就能預(yù)測(cè)這個(gè)圖片是不是一個(gè)喵喵啦!最后得到在訓(xùn)練數(shù)據(jù)上的精確度為80%,但是讓我們來(lái)看看剩下20%沒(méi)有正確預(yù)測(cè)的樣本是什么樣子的……
除了第五張姿勢(shì)扭捏的貓貓外,2和4中的貓貓我們也沒(méi)有很好地識(shí)別出來(lái)。不過(guò)不用擔(dān)心,卷積神經(jīng)網(wǎng)絡(luò) (Convolutional Neural Networks) 會(huì)比image2vector更適合于處理圖片數(shù)據(jù),所以敬請(qǐng)期待以后的更新!