![]() 神經(jīng)網(wǎng)絡(luò)已經(jīng)被開發(fā)用來模擬人腦。雖然我們還沒有做到這一點,但神經(jīng)網(wǎng)絡(luò)在機器學(xué)習方面是非常有效的。它在上世紀80年代和90年代很流行,最近越來越流行。計算機的速度足以在合理的時間內(nèi)運行一個大型神經(jīng)網(wǎng)絡(luò)。在本文中,我將討論如何實現(xiàn)一個神經(jīng)網(wǎng)絡(luò)。 我建議你仔細閱讀“神經(jīng)網(wǎng)絡(luò)的思想”部分。但如果你不太清楚,不要擔心。可以轉(zhuǎn)到實現(xiàn)部分。我把它分解成更小的碎片幫助理解。 神經(jīng)網(wǎng)絡(luò)的工作原理在一個簡單的神經(jīng)網(wǎng)絡(luò)中,神經(jīng)元是基本的計算單元。它們獲取輸入特征并將其作為輸出。以下是基本神經(jīng)網(wǎng)絡(luò)的外觀: ![]() 這里,“l(fā)ayer1”是輸入特征。“Layer1”進入另一個節(jié)點layer2,最后輸出預(yù)測的類或假設(shè)。layer2是隱藏層。可以使用多個隱藏層。
前向傳播從第1層移動到第3層的過程稱為前向傳播。前向傳播的步驟:
我將使用一個sigmoid激活函數(shù)來演示神經(jīng)網(wǎng)絡(luò)。 ![]() 這里,“a”代表隱藏層或第2層,b表示偏置。 g(z)是sigmoid激活函數(shù): ![]()
反向傳播反向傳播是從輸出層移動到第二層的過程。在這個過程中,我們計算了誤差。
![]()
![]()
訓(xùn)練網(wǎng)絡(luò)修正δ。將輸入特征乘以δ_2乘以學(xué)習速率得到θ_1。請注意θ_1的維度。 ![]() 重復(fù)前向傳播和反向傳播的過程,并不斷更新參數(shù),直到達到最佳成本。這是成本函數(shù)的公式。只是提醒一下,成本函數(shù)表明,預(yù)測離原始輸出變量有多遠。 ![]() 如果你注意到的話,這個成本函數(shù)公式幾乎和邏輯回歸成本函數(shù)一樣。 神經(jīng)網(wǎng)絡(luò)的實現(xiàn)我將使用Andrew Ng在Coursera的機器學(xué)習課程的數(shù)據(jù)集。 下面是一個逐步實現(xiàn)的神經(jīng)網(wǎng)絡(luò)。我鼓勵你自己運行每一行代碼并打印輸出以更好地理解它。
import pandas as pdimport numpy as npxls = pd.ExcelFile('ex3d1.xlsx')df = pd.read_excel(xls, 'X', header = None)![]() 這是數(shù)據(jù)集的前五行。這些是數(shù)字的像素值。 在這個數(shù)據(jù)集中,輸入和輸出變量被組織在單獨的excel表格中。讓我們導(dǎo)入輸出變量: ![]() 這也是數(shù)據(jù)集的前五行。輸出變量是從1到10的數(shù)字。這個項目的目標是使用存儲在'df'中的輸入變量來預(yù)測數(shù)字。
df.shapey.shape輸入變量或df的形狀為5000 x 400,輸出變量或y的形狀為5000 x 1。
為了簡單起見,我們將只使用一個由25個神經(jīng)元組成的隱藏層。 得到輸出類。 y_arr = y[0].unique()#輸出:array([10, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int64)正如你在上面看到的,有10個輸出類。
我們將隨機初始化層1和層2的θ。因為我們有三層,所以會有θ_1和θ_2。 θ_1的維度:第1層的大小x第2層的大小 θ_2的維度:第2層的大小x第3層的大小 從步驟2開始,“df”的形狀為5000 x 400。這意味著有400個輸入特征。所以,第1層的大小是400。當我們指定隱藏層大小為25時,層2的大小為25。我們有10個輸出類。所以,第3層的大小是10。 θ_1的維度:400 x 25 θ_2的維度:25×10 同樣,會有兩個隨機初始化的偏置b1和b2。 b_1的維度:第2層的大小(本例中為25) b_1的維度:第3層的大小(本例中為10) 定義一個隨機初始化theta的函數(shù): 使用此函數(shù)初始化theta hidden_layer = 25output =10theta1 = randInitializeWeights(len(df.T), hidden_layer)theta2 = randInitializeWeights(hidden_layer, output)theta = [theta1, theta2]現(xiàn)在,初始化我們上面討論過的偏置項:
使用前向傳播部分中的公式。 ![]() 為了方便起見,定義一個函數(shù)來乘以θ和X def z_calc(X, theta): return np.dot(X, theta.T)我們也將多次使用激活函數(shù)。同樣定義一個函數(shù) 現(xiàn)在我將逐步演示正向傳播。首先,計算z項: z1 =z_calc(df, theta1) + b1現(xiàn)在通過激活函數(shù)傳遞這個z1,得到隱藏層 a1是隱藏層。a1的形狀是5000 x 25。重復(fù)相同的過程來計算第3層或輸出層 z2 = z_calc(a1, theta2) + b2a2 = sigmoid(z2)a2的形狀是5000 x 10。10列代表10個類。a2是我們的第3層或最終輸出。如果在這個例子中有更多的隱藏層,在從一個層到另一個層的過程中會有更多的重復(fù)步驟。這種利用輸入特征計算輸出層的過程稱為前向傳播。
這是反向計算梯度和更新θ的過程。在此之前,我們需要修改'y'。我們在“y”有10個類。但我們需要將每個類在其列中分開。例如,針對第10類的列。我們將為10替換1,為其余類替換0。這樣我們將為每個類創(chuàng)建一個單獨的列。 y1 = np.zeros([len(df), len(y_arr)])y1 = pd.DataFrame(y1)for i in range(0, len(y_arr)): for j in range(0, len(y1)): if y[0][j] == y_arr[i]: y1.iloc[j, i] = 1 else: y1.iloc[j, i] = 0y1.head()之前我一步一步地演示了向前傳播,然后把所有的都放在一個函數(shù)中,我將對反向傳播做同樣的事情。使用上述反向傳播部分的梯度公式,首先計算$\delta_3$。我們將使用前向傳播實現(xiàn)中的z1、z2、a1和a2。 現(xiàn)在使用以下公式計算delta2: ![]() 這里是delta2: del2 = np.dot(del3, theta2) * a1*(1 - a1)在這里我們需要學(xué)習一個新的概念。這是一個sigmoid梯度。sigmoid梯度的公式為: ![]() 如果你注意到了,這和delta公式中的a(1-a)完全相同。因為a是sigmoid(z)。我們來寫一個關(guān)于sigmoid梯度的函數(shù): 最后,使用以下公式更新θ: ![]() 我們需要選擇一個學(xué)習率。我選了0.003。我鼓勵你嘗試使用其他學(xué)習率,看看它的表現(xiàn): theta1 = np.dot(del2.T, pd.DataFrame(a1)) * 0.003theta2 = np.dot(del3.T, pd.DataFrame(a2)) * 0.003這就是θ需要更新的方式。這個過程稱為反向傳播,因為它向后移動。在編寫反向傳播函數(shù)之前,我們需要定義成本函數(shù)。因為我會把成本的計算也包括在反向傳播方法中。但它是可以添加到前向傳播中,或者可以在訓(xùn)練網(wǎng)絡(luò)時將其分開的。 這里m是訓(xùn)練實例的數(shù)量。綜合起來的代碼: m = len(df)def backpropagation(df, theta, y1, alpha): out, a, z = hypothesis(df, theta) delta = [] delta.append(y1-a[-1]) i = l - 2 while i > 0: delta.append(np.dot(delta[-i], theta[-i])*sigmoid_grad(z[-(i+1)])) i -= 1 theta[0] = np.dot(delta[-1].T, df) * alpha for i in range(1, len(theta)): theta[i] = np.dot(delta[-(i+1)].T, pd.DataFrame(a[0])) * alpha out, a, z = hypothesis(df, theta) cost = cost_function(y1, a[-1], 1) return theta, cost
我將用20個epoch訓(xùn)練網(wǎng)絡(luò)。我在這個代碼片段中再次初始化theta。 我使用了0.003的學(xué)習率并運行了20個epoch。但是請看文章末提供的GitHub鏈接。我有試著用不同的學(xué)習率和不同的epoch數(shù)訓(xùn)練模型。 我們得到了每個epoch計算的成本,以及最終更新的θ。用最后的θ來預(yù)測輸出。
只需使用假設(shè)函數(shù)并傳遞更新后的θ來預(yù)測輸出: out, a, z = hypothesis(df, theta)現(xiàn)在計算一下準確率, 準確率為100%。完美,對吧?但我們并不是一直都能得到100%的準確率。有時獲得70%的準確率是很好的,這取決于數(shù)據(jù)集。 恭喜!你剛剛開發(fā)了一個完整的神經(jīng)網(wǎng)絡(luò)! |
|
|