Tensorflow初探(1)--實現(xiàn)一個神經(jīng)網(wǎng)絡(luò)

今天我們來實現(xiàn)一個神經(jīng)網(wǎng)絡(luò),其中部分內(nèi)容參考
http://www.itdecent.cn/p/596a30d46f34
如有冒犯請私信我或者留言,希望一些小小的工作能為大家的學(xué)習(xí)和工作帶來便利。

一、神經(jīng)網(wǎng)絡(luò)

我在看Michael Nielsen 大神的 《Neural Networks and Deep Learning》這本書時第一次接觸到神經(jīng)網(wǎng)絡(luò)這個概念。這本書由淺入深,講述得細致而不失深度。有興趣的朋友可以看看,下面是中文版鏈接。
http://www.liuxiao.org/wp-content/uploads/2016/10/nndl-ebook.pdf
那么什么是神經(jīng)網(wǎng)絡(luò)?神經(jīng)網(wǎng)絡(luò)又能干什么呢?我相信有不少同學(xué)聽過這句話“神經(jīng)網(wǎng)絡(luò)可以計算任何函數(shù)”。神經(jīng)網(wǎng)絡(luò)擁有一種普遍性。這非常非常有吸引力。關(guān)于這點的證明(說是“解釋”可能更好)可以參考Approximation by superpositions of a sigmoidal function這篇文章?,F(xiàn)在我們更關(guān)心怎么實現(xiàn)一個神經(jīng)網(wǎng)絡(luò)。

二、實現(xiàn)步驟

先簡單說明一下待擬合的函數(shù)。畢竟咱們得先找個目標(biāo)嘛!先從擬合簡單的函數(shù)來說明下大概流程,后面再逐步復(fù)雜起來。
我們需要擬合的函數(shù)非常簡單——y = x^2 - 0.5,對!就是我們之前演示過的函數(shù)。我們通過numpy來生產(chǎn)模擬數(shù)據(jù)。

def createdata():
    x_data = np.linspace(-1,1,300)[:,np.newaxis]
    noise = np.random.normal(0,0.05,x_data.shape).astype(np.float32)
    y_data = np.square(x_data) - 0.5 + noise
    return x_data,y_data

我們需要關(guān)注的就是返回值,這個函數(shù)返回x_data,y_data。x_data相當(dāng)于原始inputs,y_data相當(dāng)于我們需要擬合的對象targets。至此數(shù)據(jù)便有了。
接下來我們需要做什么?是不是好多時候去實現(xiàn)一個東西的時候一臉懵逼?其實,覺得困惑是因為我們沒有理清思路。我們得多問問自己一些問題。
我們首先問問自己一個問題:

我們知不知道,這是 一個什么樣的函數(shù),我們有沒有先驗的知識?

我們?yōu)槭裁匆P(guān)注函數(shù)形態(tài)?因為這關(guān)系到我們需要怎么設(shè)置參數(shù)。比如y=kx+b只需要設(shè)置兩個函數(shù)擬合,而y=sin(kx)+b就需要三個。
我們再問一個問題:

我們怎么來擬合一個函數(shù)?或者說,函數(shù)怎么就三下兩下就出結(jié)果了?

其實我和大家一樣,一開始也很困惑,讀完梯度下降算法之后,稍微好了一些,但還是有些不太理解。
關(guān)于第一個問題,我們其實可以先通過假設(shè)的方式來解決一下,后面我們可以通過更高級的方式來探索“這可能是一個什么函數(shù)?”
第二個問題很關(guān)鍵:神經(jīng)網(wǎng)絡(luò)的普適性。
Michael Nielsen的書中提到了這個問題,在第四章講到了“神經(jīng)網(wǎng)絡(luò)可以計算任何函數(shù)的可視化證明”
下面我們簡單探討一下這個問題。有兩點需要注意:

一、一個網(wǎng)絡(luò)并不能準(zhǔn)確地計算任何函數(shù)。而是說,我們可以獲得盡可能好的一個近似。通過增加隱藏元的數(shù)量,可以提升近似的精度

二、近似的函數(shù)類是連續(xù)函數(shù),對于階躍函數(shù),我們使用連續(xù)函數(shù)進行模擬。

大家都學(xué)過微積分吧!對于任意函數(shù)我們都可以用一個個小方塊來擬合,對吧?那么在神經(jīng)網(wǎng)絡(luò)中我們的小方塊又是什么呢?先看下圖,這是一個特殊的sigmod函數(shù),w=999 幾乎就是個階躍函數(shù)了。

image.png

現(xiàn)在我們有兩個參數(shù)w,b實際上我們可以用s = ?b/w簡化我們描述隱藏神經(jīng)元的方式,這就是階躍位置。
image.png

越來越接近我們的目標(biāo)了.
下邊的繪圖是隱藏層的加權(quán)輸出 w1a1 + w2a2 。這里 a1 和 a2 各自是頂部和底部神經(jīng)元的輸出。這些輸出由a表示,是因為它們通常被稱為神經(jīng)元的 激活值(activations)。
image.png

我們再看一張圖,我相信看完這張圖,你就會發(fā)現(xiàn)"小方塊"在哪里了。
image.png

詳細內(nèi)容可以參考上文提到的資料。這里不多說了,再說下去大家可能沒興致看了。
我們回到正題。先用tensorflow構(gòu)建一個簡單的層,輸入的參數(shù)是該層輸入,輸入數(shù)據(jù)的大小,輸出數(shù)據(jù)的大小,以及使用的激活函數(shù),激活函數(shù)在默認(rèn)情況下是None,即不適用激活函數(shù):

def add_layer(inputs,in_size,out_size,activation_function=None):
    Weights = tf.Variable(tf.random_normal([in_size,out_size]))
    biases = tf.Variable(tf.zeros([1,out_size])+0.1)
    Wx_plus_b = tf.add(tf.matmul(inputs,Weights),biases)
    if activation_function is None:
        outputs = Wx_plus_b
    else:
        outputs = activation_function(Wx_plus_b)
    return outputs

這里,我們定義輸入層-隱藏層-輸出層的三層神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu),其中輸入層和輸出層僅有一個神經(jīng)元,而隱藏層有10個神經(jīng)元。同時,我們定義我們的損失是平方損失函數(shù),通過梯度下降法來最小化我們的損失。

def createnet():
    xs = tf.placeholder(tf.float32,[None,1])
    ys = tf.placeholder(tf.float32,[None,1])

    l1 = add_layer(xs,1,10,activation_function=tf.nn.relu)
    prediction = add_layer(l1,10,1,activation_function=None)

    loss = tf.reduce_mean(tf.reduce_sum(tf.square(ys - prediction),
                                reduction_indices = [1]))
    train_step = tf.train.GradientDescentOptimizer(0.1).minimize(loss)

    init = tf.global_variables_initializer()

    x_data,y_data = createdata()
    with tf.Session() as sess:
        sess.run(init)
        for i in range(1000):
            sess.run(train_step,feed_dict={xs:x_data,ys:y_data})
            if i % 50 == 0:
                print(sess.run(loss,feed_dict={xs:x_data,ys:y_data}))

非常簡單的一個例子動手敲一下就會明白了,有些內(nèi)容在之前的博客里做了記錄,比如reduce_sum的用法等等。不多做贅述了。
完整代碼如下

import tensorflow as tf 
import numpy as np 

def add_layer(inputs,in_size,out_size,activation_function=None):
    Weights = tf.Variable(tf.random_normal([in_size,out_size]))
    biases = tf.Variable(tf.zeros([1,out_size])+0.1)
    Wx_plus_b = tf.add(tf.matmul(inputs,Weights),biases)
    if activation_function is None:
        outputs = Wx_plus_b
    else:
        outputs = activation_function(Wx_plus_b)
    return outputs

def createdata():
    x_data = np.linspace(-1,1,300)[:,np.newaxis]
    noise = np.random.normal(0,0.05,x_data.shape).astype(np.float32)
    y_data = np.square(x_data) - 0.5 + noise
    return x_data,y_data

def createnet():
    xs = tf.placeholder(tf.float32,[None,1])
    ys = tf.placeholder(tf.float32,[None,1])

    l1 = add_layer(xs,1,10,activation_function=tf.nn.relu)
    prediction = add_layer(l1,10,1,activation_function=None)

    loss = tf.reduce_mean(tf.reduce_sum(tf.square(ys - prediction),
                                reduction_indices = [1]))
    train_step = tf.train.GradientDescentOptimizer(0.1).minimize(loss)

    init = tf.global_variables_initializer()

    x_data,y_data = createdata()
    with tf.Session() as sess:
        sess.run(init)
        for i in range(1000):
            sess.run(train_step,feed_dict={xs:x_data,ys:y_data})
            if i % 50 == 0:
                print(sess.run(loss,feed_dict={xs:x_data,ys:y_data}))

createnet()
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容