使用神經(jīng)網(wǎng)絡識別手寫數(shù)字

使用MNIST數(shù)據(jù)集訓練神經(jīng)網(wǎng)絡模型镶蹋。訓練數(shù)據(jù)由28*28的手寫數(shù)字的圖像組成,輸入層包含784=28*28個神經(jīng)元。輸入像素是灰度級的,值為0.0表示白色昼弟,值為1.0表示黑色,中間數(shù)值表示逐漸暗淡的灰色奕筐。

intro.png

Algorithm

algorithm.png

神經(jīng)網(wǎng)絡快速入門

Codes

mnist_loader.py: 加載數(shù)據(jù)

import numpy as np
import pickle
import gzip

def load_data():
    f = gzip.open('data/mnist.pkl.gz', 'rb')
    training_data, validation_data, test_data = pickle.load(f, encoding="latin1")
    f.close()
    return (training_data, validation_data, test_data)

def load_data_wrapper():
    tr_d, va_d, te_d = load_data()
    # tr_d[0]: x; 1*784
    # tr_d[1]: y; 0-9
    training_inputs = [np.reshape(x, (784, 1)) for x in tr_d[0]]
    training_results = [vectorized_result(y) for y in tr_d[1]]
    training_data = zip(training_inputs, training_results)
    validation_inputs = [np.reshape(x, (784, 1)) for x in va_d[0]]
    validation_data = zip(validation_inputs, va_d[1])
    test_inputs = [np.reshape(x, (784, 1)) for x in te_d[0]]
    test_data = zip(test_inputs, te_d[1])
    return (training_data, validation_data, test_data)

def vectorized_result(j):
    v = np.zeros((10, 1))
    v[j] = 1.0
    return v

network.py: 算法舱痘,包括小批量梯度下降、反向傳播算法

import numpy as np
import random

class Network(object):
    
    def __init__(self, sizes):
        """初始化權(quán)重和偏置
        
        :param sizes: 每一層神經(jīng)元數(shù)量离赫,類型為list
        
        weights:權(quán)重
        biases:偏置
        """
        
        self.sizes = sizes
        self.num_layers = len(sizes)
        self.weights = np.array([np.random.randn(x, y) for x, y in zip(sizes[1:], sizes[:-1])])
        self.biases = np.array([np.random.randn(y, 1) for y in sizes[1:]])
        
    
    def feedforward(self, a):
        """對一組樣本x進行預測芭逝,然后輸出"""
        
        for w, b in zip(self.weights, self.biases):
            a = sigmoid(np.dot(w, a) + b)
        return a
        
    
    def gradient_descent(self, training_data, epochs, mini_batch_size, alpha, test_data=None):
        """MBGD,運行一個或者幾個batch時更新一次
        
        :param training_data: 訓練數(shù)據(jù)笆怠,每一個樣本包括(x, y)铝耻,類型為zip
        :epochs: 迭代次數(shù)
        :mini_batch_size:每一個小批量數(shù)據(jù)的數(shù)量
        :alpha: 學習率
        :test_data: 測試數(shù)據(jù)
        """
        
        training_data = list(training_data)
        n = len(training_data)
        if test_data: 
            test_data = list(test_data)
            n_test = len(list(test_data))
        for i in range(epochs):
            random.shuffle(training_data)
            mini_batches = [training_data[k:k+mini_batch_size] for k in range(0, n, mini_batch_size)]
            for mini_batch in mini_batches:
                init_ws_derivative = np.array([np.zeros(w.shape) for w in self.weights])
                init_bs_derivative = np.array([np.zeros(b.shape) for b in self.biases])
                for x, y in mini_batch:
                    activations, zs = self.forwardprop(x) #前向傳播
                    delta = self.cost_deviation(activations[-1], zs[-1], y) #計算最后一層誤差
                    ws_derivative, bs_derivative = self.backprop(activations, zs, delta) #反向傳播,cost func對w和b求偏導
                    init_ws_derivative = init_ws_derivative + ws_derivative
                    init_bs_derivative = init_bs_derivative + bs_derivative
                self.weights = self.weights - alpha / len(mini_batch) * init_ws_derivative
                self.biases = self.biases - alpha / len(mini_batch) * init_bs_derivative
            if test_data:
                print("Epoch {} : {} / {}".format(i, self.evaluate(test_data), n_test)) #識別準確數(shù)量/測試數(shù)據(jù)集總數(shù)量
            else:
                print("Epoch {} complete".format(i))


    def forwardprop(self, x):
        """前向傳播"""
        
        activation = x
        activations = [x]
        zs = []
        for w, b in zip(self.weights, self.biases):
            z = np.dot(w, activation) + b
            zs.append(z)
            activation = sigmoid(z)
            activations.append(activation)
        return (activations, zs)


    def cost_deviation(self, output, z, y):
        """計算最后一層誤差"""
    
        return (output - y) * sigmoid_derivative(z)
    
    
    def backprop(self, activations, zs, delta):
        """反向傳播"""
        
        ws_derivative = np.array([np.zeros(w.shape) for w in self.weights])
        bs_derivative = np.array([np.zeros(b.shape) for b in self.biases])
        ws_derivative[-1] = np.dot(delta, activations[-2].transpose())
        bs_derivative[-1] = delta
        
        for l in range(2, self.num_layers):
            z = zs[-l]
            delta = np.dot((self.weights[-l+1]).transpose(), delta) * sigmoid_derivative(z)
            ws_derivative[-l] = np.dot(delta, activations[-l-1].transpose())
            bs_derivative[-l] = delta
        
        return (ws_derivative, bs_derivative)
     
        
    def evaluate(self, test_data):
        """評估"""
        
        test_results = [(np.argmax(self.feedforward(x)), y) for (x, y) in test_data]
        return sum(int(output == y) for (output, y) in test_results)
    

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


def sigmoid_derivative(z):
    """sigmoid函數(shù)偏導"""
    
    return sigmoid(z) * (1 - sigmoid(z))

run.py: 運行蹬刷,訓練一個三層(1個輸入層、1個隱藏層频丘、1個輸出層)的神經(jīng)網(wǎng)絡模型

import mnist_loader
import network

if __name__ == '__main__':
    training_data, validation_data, test_data = mnist_loader.load_data_wrapper()
    net = network.Network([784, 30, 10]) #28*28
    net.gradient_descent(training_data, 30, 10, 3.0, test_data=test_data)

MNIST數(shù)據(jù)集及源碼下載


更多內(nèi)容:Github個人博客
備注:本文發(fā)表于 https://cnyangkui.github.io/2018/10/07/ML-NeuralNetwork/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末办成,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子搂漠,更是在濱河造成了極大的恐慌迂卢,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件桐汤,死亡現(xiàn)場離奇詭異而克,居然都是意外死亡,警方通過查閱死者的電腦和手機怔毛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進店門员萍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人拣度,你說我怎么就攤上這事碎绎。” “怎么了抗果?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵筋帖,是天一觀的道長。 經(jīng)常有香客問我冤馏,道長日麸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任逮光,我火速辦了婚禮代箭,結(jié)果婚禮上墩划,老公的妹妹穿的比我還像新娘。我一直安慰自己梢卸,他們只是感情好走诞,可當我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蛤高,像睡著了一般蚣旱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上戴陡,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天塞绿,我揣著相機與錄音,去河邊找鬼恤批。 笑死异吻,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的喜庞。 我是一名探鬼主播诀浪,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼延都!你這毒婦竟也來了雷猪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤晰房,失蹤者是張志新(化名)和其女友劉穎求摇,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體殊者,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡与境,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了猖吴。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片摔刁。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖距误,靈堂內(nèi)的尸體忽然破棺而出簸搞,到底是詐尸還是另有隱情,我是刑警寧澤准潭,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布趁俊,位于F島的核電站,受9級特大地震影響刑然,放射性物質(zhì)發(fā)生泄漏寺擂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望怔软。 院中可真熱鬧垦细,春花似錦、人聲如沸挡逼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽家坎。三九已至嘱能,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間虱疏,已是汗流浹背惹骂。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留做瞪,地道東北人对粪。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像装蓬,于是被迫代替她去往敵國和親著拭。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,514評論 2 348

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