您好,登錄后才能下訂單哦!
這篇文章給大家介紹Python中怎么構(gòu)建神經(jīng)網(wǎng)絡(luò),內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。
神經(jīng)網(wǎng)絡(luò)的工作原理
在一個(gè)簡(jiǎn)單的神經(jīng)網(wǎng)絡(luò)中,神經(jīng)元是基本的計(jì)算單元。它們獲取輸入特征并將其作為輸出。以下是基本神經(jīng)網(wǎng)絡(luò)的外觀:
這里,“l(fā)ayer1”是輸入特征?!癓ayer1”進(jìn)入另一個(gè)節(jié)點(diǎn)layer2,最后輸出預(yù)測(cè)的類或假設(shè)。layer2是隱藏層。可以使用多個(gè)隱藏層。
你必須根據(jù)你的數(shù)據(jù)集和精度要求來(lái)設(shè)計(jì)你的神經(jīng)網(wǎng)絡(luò)。
從第1層移動(dòng)到第3層的過程稱為前向傳播。前向傳播的步驟:
為每個(gè)輸入特征初始化系數(shù)θ。比方說,我們有100個(gè)訓(xùn)練例子。這意味著100行數(shù)據(jù)。在這種情況下,如果假設(shè)有10個(gè)輸入特征,我們的輸入矩陣的大小是100x10。現(xiàn)在確定$θ_1$的大小。行數(shù)需要與輸入特征的數(shù)量相同。在這個(gè)例子中,是10。列數(shù)應(yīng)該是你選擇的隱藏層的大小。
將輸入特征X乘以相應(yīng)的θ,然后添加一個(gè)偏置項(xiàng)。通過激活函數(shù)傳遞結(jié)果。
有幾個(gè)激活函數(shù)可用,如sigmoid,tanh,relu,softmax,swish
我將使用一個(gè)sigmoid激活函數(shù)來(lái)演示神經(jīng)網(wǎng)絡(luò)。
這里,“a”代表隱藏層或第2層,b表示偏置。
g(z)是sigmoid激活函數(shù):
為隱藏層初始化$\theta_2$。大小將是隱藏層的長(zhǎng)度乘以輸出類的數(shù)量。在這個(gè)例子中,下一層是輸出層,因?yàn)槲覀儧]有更多的隱藏層。
然后我們需要按照以前一樣的流程。將θ和隱藏層相乘,通過sigmoid激活層得到預(yù)測(cè)輸出。
反向傳播是從輸出層移動(dòng)到第二層的過程。在這個(gè)過程中,我們計(jì)算了誤差。
首先,從原始輸出y減去預(yù)測(cè)輸出,這就是我們的$\delta_3$。
現(xiàn)在,計(jì)算$\theta_2$的梯度。將$\delta_3$乘以$\theta_2$。乘以“$a^2$”乘以“$1-a^2$”。在下面的公式中,“a”上的上標(biāo)2表示第2層。請(qǐng)不要把它誤解為平方。
用訓(xùn)練樣本數(shù)m計(jì)算沒有正則化版本的梯度$\delta$。
修正$\delta$。將輸入特征乘以$\delta_2$乘以學(xué)習(xí)速率得到$\theta_1$。請(qǐng)注意$\theta_1$的維度。
重復(fù)前向傳播和反向傳播的過程,并不斷更新參數(shù),直到達(dá)到最佳成本。這是成本函數(shù)的公式。只是提醒一下,成本函數(shù)表明,預(yù)測(cè)離原始輸出變量有多遠(yuǎn)。
如果你注意到的話,這個(gè)成本函數(shù)公式幾乎和邏輯回歸成本函數(shù)一樣。
我將使用Andrew Ng在Coursera的機(jī)器學(xué)習(xí)課程的數(shù)據(jù)集。請(qǐng)從以下鏈接下載數(shù)據(jù)集:
https://github.com/rashida048/Machine-Learning-With-Python/blob/master/ex3d1.xlsx
下面是一個(gè)逐步實(shí)現(xiàn)的神經(jīng)網(wǎng)絡(luò)。我鼓勵(lì)你自己運(yùn)行每一行代碼并打印輸出以更好地理解它。
首先導(dǎo)入必要的包和數(shù)據(jù)集。
import pandas as pd import numpy as np xls = pd.ExcelFile('ex3d1.xlsx') df = pd.read_excel(xls, 'X', header = None)
這是數(shù)據(jù)集的前五行。這些是數(shù)字的像素值。
在這個(gè)數(shù)據(jù)集中,輸入和輸出變量被組織在單獨(dú)的excel表格中。讓我們導(dǎo)入輸出變量:
y = pd.read_excel(xls, 'y', header=None)
這也是數(shù)據(jù)集的前五行。輸出變量是從1到10的數(shù)字。這個(gè)項(xiàng)目的目標(biāo)是使用存儲(chǔ)在'df'中的輸入變量來(lái)預(yù)測(cè)數(shù)字。
求輸入輸出變量的維數(shù)
df.shape y.shape
輸入變量或df的形狀為5000 x 400,輸出變量或y的形狀為5000 x 1。
定義神經(jīng)網(wǎng)絡(luò)
為了簡(jiǎn)單起見,我們將只使用一個(gè)由25個(gè)神經(jīng)元組成的隱藏層。
hidden_layer = 25
得到輸出類。
y_arr = y[0].unique()#輸出: array([10, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int64)
正如你在上面看到的,有10個(gè)輸出類。
初始化θ和偏置
我們將隨機(jī)初始化層1和層2的θ。因?yàn)槲覀冇腥龑?,所以?huì)有$\theta_1$和$\theta_2$。
$\theta_1$的維度:第1層的大小x第2層的大小
$\theta_2$的維度:第2層的大小x第3層的大小
從步驟2開始,“df”的形狀為5000 x 400。這意味著有400個(gè)輸入特征。所以,第1層的大小是400。當(dāng)我們指定隱藏層大小為25時(shí),層2的大小為25。我們有10個(gè)輸出類。所以,第3層的大小是10。
$\theta_1$的維度:400 x 25
$\theta_2$的維度:25×10
同樣,會(huì)有兩個(gè)隨機(jī)初始化的偏置b1和b2。
$b_1$的維度:第2層的大小(本例中為25)
$b_1$的維度:第3層的大小(本例中為10)
定義一個(gè)隨機(jī)初始化theta的函數(shù):
def randInitializeWeights(Lin, Lout): epi = (6**1/2) / (Lin + Lout)**0.5 w = np.random.rand(Lout, Lin)*(2*epi) -epi return w
使用此函數(shù)初始化theta
hidden_layer = 25 output =10 theta1 = randInitializeWeights(len(df.T), hidden_layer) theta2 = randInitializeWeights(hidden_layer, output) theta = [theta1, theta2]
現(xiàn)在,初始化我們上面討論過的偏置項(xiàng):
b1 = np.random.randn(25,) b2 = np.random.randn(10,)
實(shí)現(xiàn)前向傳播
使用前向傳播部分中的公式。
為了方便起見,定義一個(gè)函數(shù)來(lái)乘以θ和X
def z_calc(X, theta): return np.dot(X, theta.T)
我們也將多次使用激活函數(shù)。同樣定義一個(gè)函數(shù)
def sigmoid(z): return 1/(1+ np.exp(-z))
現(xiàn)在我將逐步演示正向傳播。首先,計(jì)算z項(xiàng):
z1 =z_calc(df, theta1) + b1
現(xiàn)在通過激活函數(shù)傳遞這個(gè)z1,得到隱藏層
a1 = sigmoid(z1)
a1是隱藏層。a1的形狀是5000 x 25。重復(fù)相同的過程來(lái)計(jì)算第3層或輸出層
z2 = z_calc(a1, theta2) + b2 a2 = sigmoid(z2)
a2的形狀是5000 x 10。10列代表10個(gè)類。a2是我們的第3層或最終輸出。如果在這個(gè)例子中有更多的隱藏層,在從一個(gè)層到另一個(gè)層的過程中會(huì)有更多的重復(fù)步驟。這種利用輸入特征計(jì)算輸出層的過程稱為前向傳播。
l = 3 #層數(shù) b = [b1, b2] def hypothesis(df, theta): a = [] z = [] for i in range (0, l-1): z1 = z_calc(df, theta[i]) + b[i] out = sigmoid(z1) a.append(out) z.append(z1) df = out return out, a, z
實(shí)現(xiàn)反向傳播
這是反向計(jì)算梯度和更新θ的過程。在此之前,我們需要修改'y'。我們?cè)凇皔”有10個(gè)類。但我們需要將每個(gè)類在其列中分開。例如,針對(duì)第10類的列。我們將為10替換1,為其余類替換0。這樣我們將為每個(gè)類創(chuàng)建一個(gè)單獨(dú)的列。
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] = 0 y1.head()
之前我一步一步地演示了向前傳播,然后把所有的都放在一個(gè)函數(shù)中,我將對(duì)反向傳播做同樣的事情。使用上述反向傳播部分的梯度公式,首先計(jì)算$\delta_3$。我們將使用前向傳播實(shí)現(xiàn)中的z1、z2、a1和a2。
del3 = y1-a2
現(xiàn)在使用以下公式計(jì)算delta2:
這里是delta2:
del2 = np.dot(del3, theta2) * a1*(1 - a1)
在這里我們需要學(xué)習(xí)一個(gè)新的概念。這是一個(gè)sigmoid梯度。sigmoid梯度的公式為:
如果你注意到了,這和delta公式中的**a(1-a)**完全相同。因?yàn)閍是sigmoid(z)。我們來(lái)寫一個(gè)關(guān)于sigmoid梯度的函數(shù):
def sigmoid_grad(z): return sigmoid(z)*(1 - sigmoid(z))
最后,使用以下公式更新θ:
我們需要選擇一個(gè)學(xué)習(xí)率。我選了0.003。我鼓勵(lì)你嘗試使用其他學(xué)習(xí)率,看看它的表現(xiàn):
theta1 = np.dot(del2.T, pd.DataFrame(a1)) * 0.003 theta2 = np.dot(del3.T, pd.DataFrame(a2)) * 0.003
這就是θ需要更新的方式。這個(gè)過程稱為反向傳播,因?yàn)樗蚝笠苿?dòng)。在編寫反向傳播函數(shù)之前,我們需要定義成本函數(shù)。因?yàn)槲視?huì)把成本的計(jì)算也包括在反向傳播方法中。但它是可以添加到前向傳播中,或者可以在訓(xùn)練網(wǎng)絡(luò)時(shí)將其分開的。
def cost_function(y, y_calc, l): return (np.sum(np.sum(-np.log(y_calc)*y - np.log(1-y_calc)*(1-y))))/m
這里m是訓(xùn)練實(shí)例的數(shù)量。綜合起來(lái)的代碼:
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
訓(xùn)練網(wǎng)絡(luò)
我將用20個(gè)epoch訓(xùn)練網(wǎng)絡(luò)。我在這個(gè)代碼片段中再次初始化theta。
theta1 = randInitializeWeights(len(df.T), hidden_layer) theta2 = randInitializeWeights(hidden_layer, output) theta = [theta1, theta2] cost_list = [] for i in range(20): theta, cost= backpropagation(df, theta, y1, 0.003) cost_list.append(cost) cost_list
我使用了0.003的學(xué)習(xí)率并運(yùn)行了20個(gè)epoch。但是請(qǐng)看文章末提供的GitHub鏈接。我有試著用不同的學(xué)習(xí)率和不同的epoch數(shù)訓(xùn)練模型。
我們得到了每個(gè)epoch計(jì)算的成本,以及最終更新的θ。用最后的θ來(lái)預(yù)測(cè)輸出。
預(yù)測(cè)輸出并計(jì)算精度
只需使用假設(shè)函數(shù)并傳遞更新后的θ來(lái)預(yù)測(cè)輸出:
out, a, z = hypothesis(df, theta)
現(xiàn)在計(jì)算一下準(zhǔn)確率,
accuracy= 0 for i in range(0, len(out)): for j in range(0, len(out[i])): if out[i][j] >= 0.5 and y1.iloc[i, j] == 1: accuracy += 1 accuracy/len(df)
關(guān)于Python中怎么構(gòu)建神經(jīng)網(wǎng)絡(luò)就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。