吳恩達深度學習課程之第一門課 神經網絡和深度學習 第二週課程筆記二

本文參考黃海廣主編針對吳恩達深度學習課程DeepLearning.ai 《深度學習課程 筆記 (V5.1 )》

第二週:神經網絡的編程基礎 (Basics of Neural Network rogramming)

2.9 邏輯迴歸中的梯度下降(Logistic Regression Gradient Descent )

怎樣通過計算偏導數來實現邏輯迴歸的梯度下降算法。它的關鍵點是幾個重要公式,其作用是用來實現邏輯迴歸中梯度下降算法。使用計算圖對梯度下降算法進行計算。

假設樣本只有兩個特徵x1 和x 2 ,爲了計算z,我們需要輸入參數w 1 、w 2 和b,除此之外
還有特徵值x 1 和x2 。因此z的計算公式爲:

 

通過反向計算出導數

 

 2.10 m 個樣本的梯度下降(Gradient Descent on m Examples)

在之前學到了如何計算導數,以及應用梯度下降在邏輯迴歸的一個訓練樣本上。現在我們想要把它應用在m個訓練樣本上。

J=0;dw1=0;dw2=0;db=0;
for i = 1 to m
    z(i) = wx(i)+b;
    a(i) = sigmoid(z(i));
    J += -[y(i)log(a(i))+(1-y(i))log(1-a(i));
    dz(i) = a(i)-y(i);
    dw1 += x1(i)dz(i);
    dw2 += x2(i)dz(i);
    db += dz(i);
J/= m;
dw1/= m;
dw2/= m;
db/= m;
w=w-alpha*dw
b=b-alpha*db

當你應用深度學習算法,你會發現在代碼中顯式地使用 for 循環使你的算法很低效,同時在深度學習領域會有越來越大的數據集。所以能夠應用你的算法且沒有顯式的 for 循環會是重要的,並且會幫助你適用於更大的數據集。所以這裏有一些叫做向量化技術,它可以允許你的代碼擺脫這些顯式的 for 循環。

2.11 向量化(Vectorization)

向量化是非常基礎的去除代碼中 for 循環的藝術,在深度學習安全領域、深度學習實踐中,你會經常發現自己訓練大數據集,因爲深度學習算法處理大數據集效果很棒,所以你的代碼運行速度非常重要,否則如果在大數據集上,你的代碼可能花費很長時間去運行,你將要等待非常長的時間去得到結果。所以在深度學習領域,運行向量化是一個關鍵的技巧。

非向量化方法去計算Wtx,你需要用如下方式

z=0
for i in range(n_x)
z+=w[i]*x[i]
z+=b

向量化計算Wtx,代碼如下:

z=np.dot(w,x)+b

這是向量化計算𝑥 𝑈 𝑦的方法,你將會發現這個非常快

在兩個方法中,向量化和非向量化計算了相同的值,如你所見,向量化版本花費了 1.5毫秒,非向量化版本的 for 循環花費了大約幾乎 500 毫秒,非向量化版本多花費了 300 倍時間。所以在這個例子中,僅僅是向量化你的代碼,就會運行 300 倍快。這意味着如果向量化方法需要花費一分鐘去運行的數據,for 循環將會花費 5 個小時去運行。一句話總結,以上都是再說和 for 循環相比,向量化可以快速得到結果。

2.12 向量化的更多例子(More Examples of Vectorization )

2.13 向量化邏輯迴歸(Vectorizing Logistic Regression)

如何實現邏輯迴歸的向量化計算。

結果發現,爲了計算Wtx + [bb...b] ,numpy 命令z=np.dot(w,x)+b。這裏在 Python 中有一個巧妙的地方,這裏 b是一個實數,或者你可以說是一個 1 × 1 矩陣,只是一個普通的實數。但是當你將這個向量加上這個實數時,Python 自動把這個實數 b擴展成一個 1 × m 的行向量,它在 Python 中被稱作廣播。總結一下,在這張幻燈片中我們已經看到,不需要要 for 循環,利用 m個訓練樣本一次性計算出小寫 z 和小寫 a,用一行代碼即可完成。

2.14 向量化 logistic 迴歸的梯度輸出(Vectorizing Logistic Regression's Gradient )

注:本節中大寫字母代表向量,小寫字母代表元素


現在我們利用前五個公式完成了前向和後向傳播,也實現了對所有訓練樣本進行預測和求導,再利用後兩個公式,梯度下降更新參數。我們的目的是不使用 for 循環,所以我們就通過一次迭代實現一次梯度下降,但如果你希望多次迭代進行梯度下降,那麼仍然需要 for循環,放在最外層。不過我們還是覺得一次迭代就進行一次梯度下降,避免使用任何循環比較舒服一些。

2.15 Python 中的廣播(Broadcasting in Python )

這是一個不同食物(每 100g)中不同營養成分的卡路里含量表格,表格爲 3 行 4 列,列表示不同的食物種類,從左至右依次爲蘋果,牛肉,雞蛋,土豆。行表示不同的營養成分,從上到下依次爲碳水化合物,蛋白質,脂肪。那麼,我們現在想要計算不同食物中不同營養成分中的卡路里百分比。

我們打算使用兩行代碼完成,第一行代碼對每一列進行求和,第二行代碼分別計算每種食物每種營養成分的百分比。

下面使用如下代碼計算每列的和,可以看到輸出是每種食物(100g)的卡路里總和。

(axis=0  豎向相加   axis=1  橫向相加)其中 sum 的參數 axis=0 表示求和運算按列執行

接下來計算百分比,這條指令將 3 × 4的矩陣A除以一個1 × 4的矩陣,得到了一個 3 × 4的結果矩陣,這個結果矩陣就是我們要求的百分比含量。

下面再來解釋一下 A.sum(axis = 0) 中的參數 axis 。axis 用來指明將要進行的運算是沿着哪個軸執行,在 numpy 中,0 軸是垂直的,也就是列,而 1 軸是水平的,也就是行。

而第二個 A/cal.reshape(1,4) 指令則調用了 numpy 中的廣播機制。這裏使用 3 × 4的矩陣𝐵除以 1 × 4的矩陣。技術上來講,其實並不需要再將矩陣 reshape (重塑)成1 × 4,因爲矩陣本身已經是 1 × 4了。但是當我們寫代碼時不確定矩陣維度的時候,通常會對矩陣進行重塑來確保得到我們想要的列向量或行向量。重塑操作 reshape 是一個常量時間的操作,時間複雜度是𝑃(1),它的調用代價極低。

更多的廣播的例子。

 在 numpy 中,當一個 4 × 1的列向量與一個常數做加法時,實際上會將常數擴展爲一個4 × 1的列向量的列向量,然後兩者做逐元素加法。結果就是右邊的這個向量。這種廣播機制對於行向量和列向量均可以使用。

再看下一個例子。

用一個 2 × 3的矩陣和一個 1 × 3 的矩陣相加,其泛化形式是 m × n 的矩陣和 1 × n的矩陣相加。在執行加法操作時,其實是將 1 × n 的矩陣複製成爲 m × mn的矩陣,然後兩者做逐元素加法得到結果。針對這個具體例子,相當於在矩陣的第一列加 100,第二列加 200,第三列加 300。

 numpy 廣播機制:如果兩個數組的後緣維度的軸長度相符或其中一方的軸長度爲 1,則認爲它們是廣播兼容的。廣播會在缺失維度和軸長度爲 1 的維度上進行。

總結一下 broadcasting ,可以看看下面的圖:

2.16 關於 python _ numpy 向量的說明(A note on python or numpy vectors)

Python 的特性允許你使用廣播(broadcasting)功能,這是 Python 的 numpy 程序語言庫中最靈活的地方。而我認爲這是程序語言的優點,也是缺點。

優點的原因在於它們創造出語言的表達性,Python 語言巨大的靈活性使得你僅僅通過一行代碼就能做很多事情。

但是這也是缺點,由於廣播巨大的靈活性,有時候你對於廣播的特點以及廣播的工作原理這些細節不熟悉的話,你可能會產生很細微或者看起來很奇怪的 bug。例如,如果你將一個列向量添加到一個行向量中,你會以爲它報出維度不匹配或類型錯誤之類的錯誤,但是實際上你會得到一個行向量和列向量的求和。

據結構。相反,如果你設置 a 爲(5,1),那麼這就將置於 5 行 1 列向量中。在先前的操作裏 a 和 a 的轉置看起來一樣,而現在這樣的 a 變成一個新的 a 的轉置,並且它是一個行向量。請注意一個細微的差別,在這種數據結構中,當我們輸出 a 的轉置時有兩對方括號,而之前只有一對方括號,所以這就是 1 行 5 列的矩陣和一維數組的差別。

如果你輸出 a 和 a 的轉置的乘積,然後會返回給你一個向量的外積,是吧?所以這兩個向量的外積返回給你的是一個矩陣。

 

如果你每次創建一個數組,你都得讓它成爲一個列向量,產生一個(5,1)向量或者你讓它成爲一個行向量,那麼你的向量的行爲可能會更容易被理解。所以在這種情況下,a.shape等同於(5,1)。這種表現很像 a,但是實際上卻是一個列向量。同時這也是爲什麼當它是一個列向量

我寫代碼時還有一件經常做的事,那就是如果我不完全確定一個向量的維度(dimension),我經常會扔進一個斷言語句(assertion statement)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章