Ng機器學習第五周神經(jīng)網(wǎng)絡反向傳播算法作業(yè)解析

在學完前面四周的視頻課程后挖垛,我學會了如何利用matlab和python的spyder編輯器做線性回歸擬合直線和邏輯回歸分類兩件事肢执,而神經(jīng)網(wǎng)絡的反向傳播算法的數(shù)學公式原理Ng老師沒有做詳細的推導和說明煎楣,在網(wǎng)上的各種資源的幫助下結合這一周的課后作業(yè)代碼既峡,小葵花媽媽課堂。


這周的作業(yè)干了這么一件事情匀归,小葵花媽媽在黑板上寫了5000個阿拉伯數(shù)字坑资,1到500個數(shù)字寫的10,501到1000寫的1穆端,以此類推袱贮,最后4501到5000寫的9,小葵花媽媽想要通過這5000個數(shù)字訓練小葵花認識1到10這個數(shù)字体啰,以后能通過它們的特征認出這10個數(shù)字攒巍,所以小葵花媽媽對每個數(shù)字提取出了400個特征點也就是用400個數(shù)來表示,這400個特征數(shù)共同決定在這個數(shù)字是1到10中的哪一個概率最大荒勇,概率最大就認為這個數(shù)字是幾柒莉。


好,現(xiàn)在題目給了我們一個5000乘以400的矩陣X沽翔,和一個5000乘以1的向量y(輸出結果兢孝,代碼中計算誤差時,處理成了y_onehot)仅偎,現(xiàn)在我們只看X其中一行的400個數(shù)怎么確定出最后的手寫數(shù)字是幾的西潘。

我們把這400個數(shù)叫這個神經(jīng)網(wǎng)絡的輸入層,題目再告訴我們隱藏層的也只有1層哨颂,并且這一層有25個數(shù),最后輸出層就是10個數(shù)相种,這10個數(shù)代表這個阿拉伯數(shù)字分別為1到10的概率威恼,選取概率最大的確定為結果y品姓。

這個決定過程是這樣的,把我們原始有的400個特征數(shù)最前面加一個1箫措,這個1先理解為除這400個特征數(shù)外的所有外界影響腹备,把401個數(shù)寫成一個1乘以401的矩陣a1(行向量),由題意得斤蔓,設theta1為401乘以25的矩陣植酥,a1乘以theta1得到1乘以25的矩陣z2(行向量),這個操作可以理解為通過theta1矩陣把400+1個特征數(shù)轉化為離最終結果更近的25個特征數(shù)弦牡,不過這個z2剛出生友驮,還沒得到認可,不具有特征這個阿拉伯數(shù)字的權利驾锰,需要進行激活一下卸留,所以a2=g(z2),函數(shù)g為sigmoid函數(shù):1 / (1 + exp(-z))椭豫,這是上一周邏輯回歸的內(nèi)容耻瑟,也就是說把z2中的25個數(shù)分別帶入上面(1+e的(-z)次方)分之1這個函數(shù)來得到新的25個數(shù),得到a2赏酥,這是1乘以25的行向量喳整,代表激活后的25個特征數(shù)。

image

再重復上面步驟裸扶,在a2前加一個1框都,(嗯,你懂的)姓言,得到這個1乘以26的矩陣(行向量)a2瞬项,由題意設theta2為 26乘以10 的矩陣,z3=a2乘以theta2何荚,z3就是1乘以10的矩陣(行向量)了囱淋,不要忘了激活一下,a3=g(z3)餐塘,(嗯妥衣,這個你也懂的),好戒傻,激活完成了税手,a3(1*10的哈)這10個數(shù)就是最終這個阿拉伯數(shù)字分別為1到10的10個概率了,哪個概率最大需纳,就是幾了芦倒。

image

好了,題目背景(也叫正向傳播)就是這樣了不翩,所以我們想要的就是我們設的未知數(shù)theta1和theta2了兵扬,求是不可能求出來的了麻裳,我們只能找到最好的她們倆讓最終結果的誤差最小,那這個誤差長成什么樣子呢器钟,

image

Ng的課堂上給的是這個樣子的津坑,是一個戴著很多層口罩的妹子(天冷),脫這個口罩很麻煩傲霸,只有暴力點了疆瑰。

image

現(xiàn)在應該理解誤差(代價函數(shù))是什么意思了,通過前幾周的課程昙啄,知道還需要知道梯度穆役,才能進行梯度下降,讓誤差最小跟衅,這里的梯度不能像高數(shù)里面求出關于未知數(shù)的導函數(shù)式子孵睬,而是求出在確定theta1和theta2位置處的梯度值(導函數(shù)值)。

整個過程是這樣的伶跷,計算機隨機給出theta1和theta2的初始值掰读,因為是隨機給的,我們進行一遍正向傳播叭莫,求出結果a3概率預測蹈集,和實際y_onehot概率(或者實際的y值)對比,發(fā)現(xiàn)基本都預測錯了雇初,計算誤差J拢肆,發(fā)現(xiàn)誤差J的值非常大。

現(xiàn)在我們計算在確定的初始theta1和theta2處的梯度值靖诗,計算出的結果是兩個和theta1郭怪,theta2維數(shù)一致的矩陣,代表對應位置參數(shù)的梯度值刊橘,在最后的代碼中鄙才,將兩個梯度矩陣,按行展開為一整個行向量促绵,初始的theta輸入也展開為一整個行向量攒庵,連同誤差J的計算方法導入minimize優(yōu)化函數(shù)中,進行迭代優(yōu)化败晴,算出使J計算最小的最優(yōu)的theta(為一個行向量浓冒,最后按維數(shù)合成theta1和theta2)。(這一段需要結合代碼理解尖坤,正則化項可以先不管稳懒,理解好了最好再處理正則化,不會的回去復習Ng前面講正則化的部分)慢味。

image

上面的推導過程結合后面的python代碼理解场梆,最后把最優(yōu)的theta1和theta2進行一次正向傳播計算a3(h)發(fā)現(xiàn)佛致,預測基本準確,如果計算J也非常小辙谜,當我用5000組數(shù)據(jù)進行訓練,最后檢測這5000組預測 感昼,正確率有99.98%装哆。當我只用間隔的2500組數(shù)據(jù)訓練,檢測整體的5000組數(shù)據(jù)定嗓,正確率還有95%左右蜕琴。而只用2500數(shù)據(jù)訓練,檢測另外的2500組數(shù)據(jù)時宵溅,正確率跌倒91%凌简。

"""
Created on Tue Nov 21 16:30:57 2017

@author: leisure
"""

# -*- coding: utf-8 -*-

import numpy as np                                  #引用numpy庫,用np表示恃逻,方便矩陣運算
from scipy.io import loadmat                        #引用loadmat雏搂,讀取題目給的輸入和正確輸出的mat文件

def sigmoid(z):
    return 1 / (1 + np.exp(-z))

def forward_propagate(X, theta1, theta2):          #正向傳播程序
    m = X.shape[0] #5000組數(shù)據(jù)
    
    a1 = np.insert(X, 0, values=np.ones(m), axis=1)  #在X最前 面加一列5000*1的向量
    z2 = a1 * theta1                                 #得到5000*25的矩陣,400個特征轉化為25個隱藏特征
    a2 = np.insert(sigmoid(z2), 0, values=np.ones(m), axis=1) #取激活后的z2寇损,再加一列5000*1的向量
    z3 = a2 * theta2                                #得到5000*10的矩陣凸郑,最后10個特征
    h = sigmoid(z3)                                 #激活后得到10個概率
    
    return a1, z2, a2, z3, h

def sigmoid_gradient(z):
    return np.multiply(sigmoid(z), (1 - sigmoid(z)))  #s函數(shù)求導

def backprop(params, input_size, hidden_size, num_labels, X, y,learning_rate): #反向傳播算法計算梯度的函數(shù),最后得到誤差J和梯度grad(把兩個梯度矩陣按行展開合成一行)
    m = X.shape[0]
    X = np.matrix(X)
    y = np.matrix(y)
    
    # reshape the parameter array into parameter matrices for each layer
    theta1 = np.matrix(np.reshape(params[:hidden_size * (input_size + 1)], ((input_size + 1),hidden_size)))
    theta2 = np.matrix(np.reshape(params[hidden_size * (input_size + 1):], ((hidden_size + 1),num_labels)))
    
    # run the feed-forward pass
    a1, z2, a2, z3, h = forward_propagate(X, theta1, theta2)
    
    # initializations
    J = 0
    delta1 = np.zeros(theta1.shape)  # (401, 25)
    delta2 = np.zeros(theta2.shape)  # (26, 10)
    
    # compute the cost
    for i in range(m):
        first_term = np.multiply(-y[i,:], np.log(h[i,:])) #y_onehot的每一行和輸出概率h的每一行數(shù)據(jù)相乘
        second_term = np.multiply((1 - y[i,:]), np.log(1 - h[i,:]))
        J += np.sum(first_term - second_term) #乘出來的10*1的向量元素求和矛市,再累加5000組的數(shù)據(jù)
    
    J = J / m
    
    # add the cost regularization term
    J += (float(learning_rate) / (2 * m)) * (np.sum(np.power(theta1[1:,:], 2)) + np.sum(np.power(theta2[1:,:], 2))) #加上正則化的項
    
    # perform backpropagation
    for t in range(m):
        a1t = a1[t,:]  # (1, 401)
        z2t = z2[t,:]  # (1, 25)
        a2t = a2[t,:]  # (1, 26)
        ht = h[t,:]  # (1, 10)
        yt = y[t,:]  # (1, 10)
        
        d3t = ht - yt  # (1, 10) 最后的誤差向量
        
#        z2t = np.insert(z2t, 0, values=np.ones(1))  # 補1為(1, 26)
        d2t = np.multiply((d3t * theta2.T)[:,1:], sigmoid_gradient(z2t))  # (1, 25)
        
        delta1 = delta1 + a1t.T * d2t  #401*25
        delta2 = delta2 + a2t.T * d3t    #26*10
        
    delta1 = delta1 / m
    delta2 = delta2 / m
    
    # add the gradient regularization term
    delta1[1:,:] = delta1[1:,:] + (theta1[1:,:] * learning_rate) / m
    delta2[1:,:] = delta2[1:,:] + (theta2[1:,:] * learning_rate) / m
    
    # unravel the gradient matrices into a single array
    grad = np.concatenate((np.ravel(delta1), np.ravel(delta2)))
    
    return J, grad

from scipy.optimize import minimize

# initial setup
data = loadmat('ex4data1.mat') #字典形式的數(shù)據(jù)結構
X = data['X']
y = data['y']

from sklearn.preprocessing import OneHotEncoder
encoder = OneHotEncoder(sparse=False)
y_onehot = encoder.fit_transform(y) # 將y轉為y_onehot芙沥,每組數(shù)據(jù)中概率最大的為1,其余為0浊吏,5000*10

input_size = 400 #輸入層變量個數(shù)400
hidden_size = 25 #隱藏層變量個數(shù)為25
num_labels = 10  #輸出層10個代表分別為1到10的概率
learning_rate = 1#正則化的系數(shù)

# randomly initialize a parameter array of the size of the full network's parameters
params = (np.random.random(size=hidden_size * (input_size + 1) + num_labels * (hidden_size + 1)) - 0.5) * 0.25#隨機給的初始參數(shù)theta1和theta2而昨,現(xiàn)在為一個行向量,用時再按維數(shù)合成矩陣

m = X.shape[0] #m為5000找田,組數(shù)據(jù)
X = np.matrix(X)#轉為矩陣方便運算
y = np.matrix(y)

# minimize the objective function
fmin = minimize(fun=backprop, x0=params, args=(input_size, hidden_size, num_labels, X, y_onehot,learning_rate), #用minimize函數(shù)通過梯度grad優(yōu)化J得到最優(yōu)的theta1和theta2讓J最小
                method='TNC', jac=True, options={'maxiter': 250})

theta1 = np.matrix(np.reshape(fmin.x[:hidden_size * (input_size + 1)], ((input_size + 1),hidden_size ))) #優(yōu)化得到的行向量按維數(shù)合成theta1和theta2
theta2 = np.matrix(np.reshape(fmin.x[hidden_size * (input_size + 1):], ((hidden_size + 1),num_labels )))

a1, z2, a2, z3, h = forward_propagate(X, theta1, theta2)#最優(yōu)的theta1和theta2正向傳播一次歌憨,看看預測下效果
y_pred = np.array(np.argmax(h, axis=1) + 1)#因為h索引從0開始,需要加1午阵,得到y(tǒng)_pred為我們的預測結果

correct = [1 if a == b else 0 for (a, b) in zip(y_pred, y)]#比較預測和實際的結果躺孝。正確為1,錯誤為0
accuracy = (sum(map(int, correct)) / float(len(correct)))#累加求和底桂,除以總個數(shù)植袍,得到正確率
print ('accuracy = {0}%'.format(accuracy * 100))

由于python的主流性,只貼上python的代碼籽懦,spyder編輯器也可和matlab一樣以矩陣形式實時查看變量的值很方便于个,matlab的代碼網(wǎng)上也有,更多機器學習資源可以加群:514649411暮顺。代碼修改于群主黃博的共享厅篓,推導過程借鑒于博客園秀存,初始數(shù)據(jù)mat文件可以在群里下載。
我們都是初學者羽氮,希望更多人可以更快邁過這道坎或链,繼續(xù)學習下去。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末档押,一起剝皮案震驚了整個濱河市澳盐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌令宿,老刑警劉巖叼耙,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異粒没,居然都是意外死亡筛婉,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進店門癞松,熙熙樓的掌柜王于貴愁眉苦臉地迎上來爽撒,“玉大人,你說我怎么就攤上這事拦惋〈艺悖” “怎么了?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵厕妖,是天一觀的道長首尼。 經(jīng)常有香客問我,道長言秸,這世上最難降的妖魔是什么软能? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮举畸,結果婚禮上查排,老公的妹妹穿的比我還像新娘。我一直安慰自己抄沮,他們只是感情好跋核,可當我...
    茶點故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著叛买,像睡著了一般砂代。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上率挣,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天刻伊,我揣著相機與錄音,去河邊找鬼。 笑死捶箱,一個胖子當著我的面吹牛智什,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播丁屎,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼荠锭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了晨川?” 一聲冷哼從身側響起节沦,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎础爬,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吼鳞,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡看蚜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了赔桌。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片供炎。...
    茶點故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖疾党,靈堂內(nèi)的尸體忽然破棺而出音诫,到底是詐尸還是另有隱情,我是刑警寧澤雪位,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布竭钝,位于F島的核電站,受9級特大地震影響雹洗,放射性物質發(fā)生泄漏香罐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一时肿、第九天 我趴在偏房一處隱蔽的房頂上張望庇茫。 院中可真熱鬧,春花似錦螃成、人聲如沸旦签。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宁炫。三九已至,卻和暖如春击吱,著一層夾襖步出監(jiān)牢的瞬間淋淀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留朵纷,地道東北人炭臭。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像袍辞,于是被迫代替她去往敵國和親鞋仍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,870評論 2 361

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

  • 目錄 [TOC] 引言 量化交易是指以先進的數(shù)學模型替代人為的主觀判斷搅吁,利用計算機技術從龐大的歷史數(shù)據(jù)中海選能帶來...
    雷達熊閱讀 985評論 0 2
  • 引 向量求導在當前線性系統(tǒng)的優(yōu)化問題中經(jīng)常用到威创,比如最小二乘:$$\hat{\mathbf{x}{\rm LS}}...
    hiloki閱讀 983評論 0 1
  • 高血壓是一種慢性病界拦,是經(jīng)過長時間的飲食不正確所導致的吸申,所以,我們必需調(diào)整自己不健康的飲食狀況享甸,菜寶寶提示截碴,高血壓患...
    鑫的傳說閱讀 389評論 0 0
  • 我們都在忙碌日丹,成年人在忙,孩子在忙蚯嫌,整個社會都處在熱氣騰騰的忙碌之中哲虾。 男人忙,忙得忘了家庭择示,忘了為人子妒牙、為人夫、...
    夏雨青春閱讀 946評論 0 0
  • 下次見面不知道會是何時摩瞎?愿你安好,后會有期!
    szmChris閱讀 195評論 1 1