deeplearning課后作業(yè)(課程一第二周作業(yè)2)

deeplearning.ai官網(wǎng)地址:https://www.deeplearning.ai/
coursera地址:https://www.coursera.org/specializations/deep-learning
網(wǎng)易視頻地址:https://163.lu/nPtn42
課程一第二周課后作業(yè)1-2

具有神經(jīng)網(wǎng)絡(luò)思維的邏輯回歸算法

本次作業(yè)师崎,將會構(gòu)建一個邏輯回歸分類器用以識別貓荞估, 通過完成這次作業(yè),也能了解一些神經(jīng)網(wǎng)絡(luò)的思維,并且能夠建立一個對神經(jīng)網(wǎng)絡(luò)的基本認(rèn)識贰健。

1. 導(dǎo)入相關(guān)包

首先,導(dǎo)入接剩,本此作業(yè)實(shí)現(xiàn)中所需要的所有相關(guān)包皆警,具體實(shí)現(xiàn)如下:

import numpy as np
import matplotlib.pyplot as plt
import h5py
import scipy
from PIL import Image
from scipy import ndimage
from lr_utils import load_dataset
  • 一些庫的簡單介紹:
    h5py是一個處理h5文件的交互包
    scipy是一個科學(xué)計算庫
    PIL是一個圖像處理庫

2.數(shù)據(jù)集的概述

作業(yè)所用到的數(shù)據(jù)集存儲在data.h5文件中,對于數(shù)據(jù)集溢十,有以下介紹:

  • 數(shù)據(jù)集中的訓(xùn)練集m_train圖像垮刹,被標(biāo)注為cat (y=1)non-cat (y=0)
  • 數(shù)據(jù)集中的測試集m_test圖像,同樣张弛,被標(biāo)注為catnon-cat
  • 每一幅圖像的都是(num_px,num_px,3)的形式荒典,其中3表示圖像是3通道的RGB形式酪劫,而長和寬都是num_pxnum_px的正方形圖片。
  • 加載數(shù)據(jù)前寺董,可以利用python查看數(shù)據(jù)集的存儲形式覆糟,具體實(shí)現(xiàn)代碼如下所示;
f = h5py.File('dataset/train_catvnoncat.h5','r')   #打開h5文件  
# 可以查看所有的主鍵  
for key in f.keys():      
    print(f[key].name)      #輸出數(shù)據(jù)集標(biāo)簽值,train_set_x,train_set_y
    print(f[key].shape)      #輸出數(shù)據(jù)集train_set_x,train_set_y的形式
    print(f[key].value)      #輸出數(shù)據(jù)集trian_set_x和train_set_y的具體值
   
訓(xùn)練集部分?jǐn)?shù)據(jù)信息
train_set_y部分?jǐn)?shù)據(jù)信息

根據(jù)以上數(shù)據(jù)形式遮咖,編寫loadset()函數(shù)加載數(shù)據(jù)集的代碼如下所示:

def load_dataset():
    train_dataset = h5py.File('datasets/train_catvnoncat.h5', "r")
    train_set_x_orig = np.array(train_dataset["train_set_x"][:]) #訓(xùn)練集數(shù)據(jù)特征
    train_set_y_orig = np.array(train_dataset["train_set_y"][:]) # 訓(xùn)練集數(shù)據(jù)標(biāo)簽

    test_dataset = h5py.File('datasets/test_catvnoncat.h5', "r")
    test_set_x_orig = np.array(test_dataset["test_set_x"][:]) # 測試集數(shù)據(jù)特征
    test_set_y_orig = np.array(test_dataset["test_set_y"][:]) #測試集數(shù)據(jù)標(biāo)簽

    classes = np.array(test_dataset["list_classes"][:]) # 數(shù)據(jù)類別構(gòu)成的列表
    
    train_set_y_orig = train_set_y_orig.reshape((1, train_set_y_orig.shape[0]))
    test_set_y_orig = test_set_y_orig.reshape((1, test_set_y_orig.shape[0]))
    
    return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes

簡單的測試下加載好的數(shù)據(jù)集滩字,可以看到相關(guān)的輸出信息如下所示:

index = 5
plt.imshow(train_set_x_orig[index])
print ("y = " + str(train_set_y[:, index]) + ", it's a '" + classes[np.squeeze(train_set_y[:, index])].decode("utf-8") +  "' picture.")

許多深度學(xué)習(xí)代碼存在bug的原因之一就是矩陣或者向量維數(shù)不匹配,在算法實(shí)現(xiàn)之前御吞,先進(jìn)行數(shù)據(jù)集的維度輸出是一個和明智的做法麦箍,具體實(shí)現(xiàn)算法如下代碼所示:

m_train = train_set_x_orig.shape[0]
m_test = test_set_x_orig.shape[0]
num_px = train_set_x_orig.shape[1]


print ("Number of training examples: m_train = " + str(m_train))
print ("Number of testing examples: m_test = " + str(m_test))
print ("Height/Width of each image: num_px = " + str(num_px))
print ("Each image is of size: (" + str(num_px) + ", " + str(num_px) + ", 3)")
print ("train_set_x shape: " + str(train_set_x_orig.shape))
print ("train_set_y shape: " + str(train_set_y.shape))
print ("test_set_x shape: " + str(test_set_x_orig.shape))
print ("test_set_y shape: " + str(test_set_y.shape))

上述代碼實(shí)現(xiàn)結(jié)果如下所示:

在圖像處理過程中,數(shù)據(jù)集中的圖像數(shù)據(jù)是一個(num_px,num_px,3)的矩陣陶珠,需要將其轉(zhuǎn)換為(num_px×num_px×3,1)的矩陣挟裂,在python中有一個實(shí)現(xiàn)技巧如下所示,可輕松實(shí)現(xiàn)矩陣形式的轉(zhuǎn)化揍诽。

X_flatten = X.reshape(X.shape[0], -1).T   

綜上所述诀蓉,具體實(shí)現(xiàn)代碼可以如下所示:

train_set_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0], -1).T
test_set_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0], -1).T
print ("train_set_x_flatten shape: " + str(train_set_x_flatten.shape))
print ("train_set_y shape: " + str(train_set_y.shape))
print ("test_set_x_flatten shape: " + str(test_set_x_flatten.shape))
print ("test_set_y shape: " + str(test_set_y.shape))
print ("sanity check after reshaping: " + str(train_set_x_flatten[0:5,0]))

以上代碼結(jié)果如下所示:


為了表示圖片中的顏色,由RGB通道表示圖片顏色寝姿,即每個像素的值實(shí)際上是由三個0-255的數(shù)組成的向量交排。

機(jī)器學(xué)習(xí)中一種通用的處理數(shù)據(jù)集的方法稱之為標(biāo)準(zhǔn)化,對于圖像數(shù)據(jù)集而言饵筑,一種簡單而又方便的處理數(shù)據(jù)的方法是對每一行數(shù)據(jù)除以255埃篓,即其RGB的最大值。具體實(shí)現(xiàn)可以如以下代碼所示:

train_set_x = train_set_x_flatten/255.
test_set_x = test_set_x_flatten/255.

3. 學(xué)習(xí)算法的一般體系架構(gòu)

有了如上的數(shù)據(jù)預(yù)處理流程根资,是時候構(gòu)建一個具有神經(jīng)網(wǎng)絡(luò)思維的算法了架专,其算法實(shí)現(xiàn)過程基本如下圖所示:


對于一個樣本 x^{(i)}:
z^{(i)} = w^T x^{(i)} + b \tag{1}
\hat{y}^{(i)} = a^{(i)} = sigmoid(z^{(i)})\tag{2}
\mathcal{L}(a^{(i)}, y^{(i)}) = - y^{(i)} \log(a^{(i)}) - (1-y^{(i)} ) \log(1-a^{(i)})\tag{3}

所有樣本的損失可以由以下公式計算:
J = \frac{1}{m} \sum_{i=1}^m \mathcal{L}(a^{(i)}, y^{(i)})\tag{6}

實(shí)現(xiàn)這個算法的關(guān)鍵步驟是:

  • 初始化模型的學(xué)習(xí)參數(shù)
  • 通過最小化損失函數(shù)得到模型的學(xué)習(xí)參數(shù)
  • 根據(jù)模型的學(xué)習(xí)參數(shù)做出相關(guān)預(yù)測
  • 分析預(yù)測結(jié)果并得出相關(guān)結(jié)論

4. 算法的構(gòu)建過程

構(gòu)建分類算法的主要步驟可以如下步驟所示:

  • 構(gòu)建模型架構(gòu),例如特征的個數(shù)
  • 初始化模型參數(shù)
  • 循環(huán):
    • 計算當(dāng)前損失
    • 利用反向傳播算法計算當(dāng)前的梯度
    • 通過梯度下降更新參數(shù)
4.1 sigmoid函數(shù)

邏輯回歸中的激活函數(shù)是sigmoid函數(shù)玄帕,其實(shí)現(xiàn)方式可以由以下代碼所示:

def sigmoid(z):
    s = 1 / (1 + np.exp(-z)) 
    return s
4.2 初始化參數(shù)

初始化權(quán)重參數(shù)w并使其為0部脚,參數(shù)b = 0,具體實(shí)現(xiàn)代碼如下所示:

def initialize_with_zeros(dim): 
    w = np.zeros((dim, 1))
    b = 0
   #確保參數(shù)w的維數(shù)和數(shù)據(jù)類型正確
    assert(w.shape == (dim, 1))
    assert(isinstance(b, float) or isinstance(b, int))
    
    return w, b
4.3 前向和反向傳播算法

初始化參數(shù)之后裤纹,通過傳播算法計算學(xué)習(xí)參數(shù)了委刘,關(guān)于參數(shù)的計算其公式如下是所示:
前向傳播算法:
通過輸入變量X計算:
A = \sigma(w^T X + b) = (a^{(0)}, a^{(1)}, ..., a^{(m-1)}, a^{(m)})\tag{7}
計算損失函數(shù):
J = -\frac{1}{m}\sum_{i=1}^{m}y^{(i)}\log(a^{(i)})+(1-y^{(i)})\log(1-a^{(i)})\tag{8}
可以通過以下兩個公式計算相關(guān)參數(shù):
\frac{\partial J}{\partial w} = \frac{1}{m}X(A-Y)^T\tag{9}
\frac{\partial J}{\partial b} = \frac{1}{m} \sum_{i=1}^m (a^{(i)}-y^{(i)})\tag{10}

根據(jù)以上公式,算法實(shí)現(xiàn)的代碼如下所示:

def propagate(w, b, X, Y):
  m = X.shape[1]
  A = sigmoid(np.dot(w.T, X) + b)           
  cost = -1 / m * np.sum(Y * np.log(A) + (1 - Y) * np.log(1 - A))         
  dw = 1 / m * np.dot(X, (A - Y).T)
  db = 1 / m * np.sum(A - Y)
  assert(dw.shape == w.shape)
  assert(db.dtype == float)
  cost = np.squeeze(cost)
  assert(cost.shape == ())
  grads = {"dw": dw,  "db": db}
  return grads, cost
4.4 利用梯度下降優(yōu)化算法

有了前向傳播算法對參數(shù)的計算鹰椒,接下來需要做的就是利用反向傳播算法中的梯度下降算法更新參數(shù)锡移,具體實(shí)現(xiàn)代碼如下所示:

def optimize(w, b, X, Y, num_iterations, learning_rate, print_cost = False):
    costs = []
    for i in range(num_iterations):
        grads, cost = propagate(w, b, X, Y)
        dw = grads["dw"]
        db = grads["db"]
        w = w - learning_rate * dw
        b = b - learning_rate * db
        if i % 100 == 0:
            costs.append(cost)
        if print_cost and i % 100 == 0:
            print ("Cost after iteration %i: %f" %(i, cost))
    
    params = {"w": w,
              "b": b}
    
    grads = {"dw": dw,
             "db": db}
    
    return params, grads, costs

有了通過反向傳播算法得到的參數(shù)wb,可以根據(jù)公式:
\hat{y} = \delta(w^Tx+b)\tag{11}做出預(yù)測了漆际,具體實(shí)現(xiàn)代碼如下所示:

def predict(w, b, X):
    m = X.shape[1]
    Y_prediction = np.zeros((1,m))
    w = w.reshape(X.shape[0], 1)
    A = sigmoid(np.dot(w.T, X) + b)
    for i in range(A.shape[1]):
        if A[0, i] <= 0.5:
            Y_prediction[0, i] = 0
        else:
            Y_prediction[0, i] = 1
    assert(Y_prediction.shape == (1, m))
    return Y_prediction

5. 將所有函數(shù)合并在一起搭建模型

通過以上淆珊,已經(jīng)分模塊實(shí)現(xiàn)了算法的所有部分,現(xiàn)在可以通過構(gòu)建一個模型函數(shù)將所有的函數(shù)合并在一起奸汇,用以實(shí)現(xiàn)模型的參數(shù)更新和預(yù)測施符,具體實(shí)現(xiàn)代碼如下所示:

def model(X_train, Y_train, X_test, Y_test, num_iterations = 2000, learning_rate = 0.5, print_cost = False):
    w, b = initialize_with_zeros(X_train.shape[0])
    parameters, grads, costs = optimize(w, b, X_train, Y_train, num_iterations, learning_rate, print_cost)
    w = parameters["w"]
    b = parameters["b"]
    Y_prediction_test = predict(w, b, X_test)
    Y_prediction_train = predict(w, b, X_train)
    print("train accuracy: {} %".format(100 - np.mean(np.abs(Y_prediction_train - Y_train)) * 100))
    print("test accuracy: {} %".format(100 - np.mean(np.abs(Y_prediction_test - Y_test)) * 100))
    d = {"costs": costs,
         "Y_prediction_test": Y_prediction_test, 
         "Y_prediction_train" : Y_prediction_train, 
         "w" : w, 
         "b" : b,
         "learning_rate" : learning_rate,
         "num_iterations": num_iterations}
    return d

可以簡單繪制模型訓(xùn)練過程中損失函數(shù)和梯度的變化曲線往声,如下所示:

costs = np.squeeze(d['costs'])
plt.plot(costs)
plt.ylabel('cost')
plt.xlabel('iterations (per hundreds)')
plt.title("Learning rate =" + str(d["learning_rate"]))
plt.show()

如上圖所示,可以看到戳吝,隨著迭代次數(shù)的增加浩销,模型的損失正在下降,當(dāng)?shù)虼螖?shù)增加骨坑,將會看到訓(xùn)練集的損失逐漸上升撼嗓,而測試集的損失逐漸下降。

6. 進(jìn)一步的分析

學(xué)習(xí)率的大小對于模型的訓(xùn)練也是至關(guān)重要的欢唾,當(dāng)學(xué)習(xí)率的大小決定著參數(shù)更新的速度且警,當(dāng)學(xué)習(xí)率過大時,模型不容易收斂礁遣,而當(dāng)學(xué)習(xí)率過小時斑芜,模型的需要迭代很多次才能收斂,可以用以下代碼驗(yàn)證學(xué)習(xí)率對模型訓(xùn)練的影響祟霍。

learning_rates = [0.01, 0.001, 0.0001]
models = {}
for i in learning_rates:
    print ("learning rate is: " + str(i))
    models[str(i)] = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 1500, learning_rate = i, print_cost = False)
    print ('\n' + "-------------------------------------------------------" + '\n')

for i in learning_rates:
    plt.plot(np.squeeze(models[str(i)]["costs"]), label= str(models[str(i)]["learning_rate"]))

plt.ylabel('cost')
plt.xlabel('iterations')

legend = plt.legend(loc='upper center', shadow=True)
frame = legend.get_frame()
frame.set_facecolor('0.90')

綜上杏头,可以得到如下結(jié)論:

  • 不同的學(xué)習(xí)率會得到不同的預(yù)測結(jié)果和損失
  • 如果模型的學(xué)習(xí)率過大,可能會導(dǎo)致模型的損失上下振蕩沸呐,如上圖所示醇王,學(xué)習(xí)率取0.001可能是一個不錯的選擇。
  • 過小的損失不一定意味著該模型是一個好模型崭添,能做出很好的預(yù)測寓娩,很可能是過擬合原因造成的。這種過擬合情況通常發(fā)生在訓(xùn)練集的精確度比測試集高很多的情況下呼渣。
  • 對于深度學(xué)習(xí)棘伴,通常有如下建議:
    • 為模型選擇一個合適的學(xué)習(xí)率以得到更好的模型參數(shù)
    • 如果模型過擬合,通常要采取其他措施消除這種過擬合屁置,一種行之有效的方法是正則化方法焊夸。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蓝角,隨后出現(xiàn)的幾起案子阱穗,更是在濱河造成了極大的恐慌,老刑警劉巖使鹅,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件颇象,死亡現(xiàn)場離奇詭異,居然都是意外死亡并徘,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進(jìn)店門扰魂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來麦乞,“玉大人蕴茴,你說我怎么就攤上這事〗阒保” “怎么了倦淀?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長声畏。 經(jīng)常有香客問我撞叽,道長,這世上最難降的妖魔是什么插龄? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任愿棋,我火速辦了婚禮,結(jié)果婚禮上均牢,老公的妹妹穿的比我還像新娘糠雨。我一直安慰自己,他們只是感情好徘跪,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布甘邀。 她就那樣靜靜地躺著,像睡著了一般垮庐。 火紅的嫁衣襯著肌膚如雪松邪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天哨查,我揣著相機(jī)與錄音逗抑,去河邊找鬼。 笑死解恰,一個胖子當(dāng)著我的面吹牛锋八,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播护盈,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼挟纱,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了腐宋?” 一聲冷哼從身側(cè)響起紊服,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎胸竞,沒想到半個月后欺嗤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡卫枝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年煎饼,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片校赤。...
    茶點(diǎn)故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡吆玖,死狀恐怖筒溃,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情沾乘,我是刑警寧澤怜奖,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站翅阵,受9級特大地震影響歪玲,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜掷匠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一滥崩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧槐雾,春花似錦夭委、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至擎值,卻和暖如春慌烧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鸠儿。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工屹蚊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人进每。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓汹粤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親田晚。 傳聞我的和親對象是個殘疾皇子嘱兼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容