生活随笔
收集整理的這篇文章主要介紹了
机器学习-神经网络
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
神經網絡
文章目錄
簡介
神經網絡是一個相當古老的算法,在支持向量機的統治時期,其效果備受質疑,但是,隨著機器學習的發展以及深度網絡的產生,深度神經網絡已經成為很多問題的首選模型(sota方法)。如果說之前的很多問題可以通過線性回歸或者邏輯回歸這類模型通過構建多項式特征達到非線性擬合效果,那么對于圖片(每個像素點就是一個特征)這樣的數據,邏輯回歸等模型構建的特征量是非常龐大的,而神經網絡則采用模擬人腦這一最為強大的學習器的方法建立層層非線性變換的模型,它可以自動學習任意的特征項的組合。
模型表示
神經網絡模型的建立依據動物的神經元反應機制,每個神經元將所有的輸入整合并通過激活函數(非線性函數,如S型函數)激活后輸出,多個神經元構成一個隱藏層(hidden layer),層與層之間的連接權重就是機器學習模型中常說的參數,每層神經元之外也可以增加一個節點,通常叫做偏置節點。通常數據特征輸入也表示為一層,稱為輸入層,輸出結果層(單個或者多個神經元)稱為輸出層,中間進行非線性變換的都稱為隱藏層。層間連線上的值就是需要學習的權重。
通過上述描述,可以看到每個神經元的運算就是一個比較簡單的邏輯回歸運算,不難推導,按照矩陣運算,下一層神經元的輸入為上一層神經元經過權重變換得到的結果激活后的結果。 Y=sigmoid(WX+bias)Y = sigmoid(WX + bias) Y = s i g m o i d ( W X + b i a s ) 上述的運算層層進行的過程稱為前向傳播,理論上只要堆疊的層數足夠深,神經網絡可以擬合任意分布的數據,然而,過深的網絡,訓練的難度也會增加。
神經網絡可以解決分類和回歸這兩種基本有監督學習的問題,當然,ANN(人工神經網絡)也可以用于處理其他的很多機器學習的基本問題。分類好一般分為二分類和多分類,二分類輸出層只需要一個神經元表示標簽為1的概率即可,多分類則需要多個神經元表示每個類別的概率。對于這樣的神經網絡,其損失函數的一般化形式如下。
J(Θ)=?1m∑i=1m∑k=1K[yk(i)log?((hΘ(x(i)))k)+(1?yk(i))log?(1?(hΘ(x(i)))k)]+λ2m∑l=1L?1∑i=1sl∑j=1sl1(Θj,i(l))2J(\Theta)=-\frac{1}{m} \sum_{i=1}^{m} \sum_{k=1}^{K}\left[y_{k}^{(i)} \log \left(\left(h_{\Theta}\left(x^{(i)}\right)\right)_{k}\right)+\left(1-y_{k}^{(i)}\right) \log \left(1-\left(h_{\Theta}\left(x^{(i)}\right)\right)_{k}\right)\right]+\frac{\lambda}{2 m} \sum_{l=1}^{L-1} \sum_{i=1}^{s_{l}} \sum_{j=1}^{s l_{1}}\left(\Theta_{j, i}^{(l)}\right)^{2} J ( Θ ) = ? m 1 ? i = 1 ∑ m ? k = 1 ∑ K ? [ y k ( i ) ? log ( ( h Θ ? ( x ( i ) ) ) k ? ) + ( 1 ? y k ( i ) ? ) log ( 1 ? ( h Θ ? ( x ( i ) ) ) k ? ) ] + 2 m λ ? l = 1 ∑ L ? 1 ? i = 1 ∑ s l ? ? j = 1 ∑ s l 1 ? ? ( Θ j , i ( l ) ? ) 2
模型訓練
上面說明了神經網絡中常用的代價函數(交叉熵代價函數),訓練神經網絡的目標就是最小化代價函數。在神經網絡的運算中,利用權重矩陣一步步計算出輸出層的輸出的過程稱為前向傳播(forward),而想要通過梯度下降更新參數就需要求解出各個參數的梯度。而這個梯度的計算算法稱為反向傳播算法(Backpropagation algorithm),它的思想簡單看來就是假設每個神經元節點都存在一個誤差值,這個值是通過權重矩陣的逆運算從下一層計算得到的。具體的就是,計算輸出層各神經元的誤差,將誤差通過權重矩陣傳回上一層,一次類推,得到除了輸入層的各隱層神經元誤差值。
模型應用
神經網絡這種模型既可以用于監督學習又可以用于非監督模型,只是調整損失函數而已。之前,對于多分類問題,主要使用one vs all策略,即構建多個分類器,而在神經網絡中則可以將最后一層的輸出設置為類別個數,這樣每個輸出層節點的值就是相應類別的得分(score)或者概率(softmax)激活,將得分最高的作為最終預測類別,計算損失,依據反向傳播算法更新權重。 下面,構建一個只包含一個隱藏層的神經網絡用于手寫體分類。數據集采用一個手寫數字數據集。
"""
Author: Zhou Chen
Date: 2019/11/13
Desc: About
"""
import numpy
as np
import scipy
. io
as scio
from sklearn
. preprocessing
import LabelBinarizer
import matplotlib
. pyplot
as plt
plt
. style
. use
( 'fivethirtyeight' ) def sigmoid ( x
) : return 1 / ( 1 + np
. exp
( - x
) ) def sigmoid_grad ( x
) : return x
* ( 1 - x
) def one_hot ( x
) : array
= np
. zeros
( shape
= [ 10 , 1 ] ) array
[ x
- 1 , 0 ] = 1 return array
def plot_his ( his
) : """繪制訓練過程:param his::return:""" plt
. plot
( np
. arange
( len ( his
[ 'loss' ] ) ) , his
[ 'loss' ] , label
= 'loss' ) plt
. plot
( np
. arange
( len ( his
[ 'accuracy' ] ) ) , his
[ 'accuracy' ] , label
= 'accuracy' ) plt
. title
( 'training history' ) plt
. legend
( loc
= 0 ) plt
. show
( ) def mse ( y_label
, y_pred
) : y_pred
= np
. squeeze
( y_pred
, axis
= - 1 ) if y_label
. shape
== y_pred
. shape
: return np
. sum ( ( y
- y_pred
) ** 2 / y
. shape
[ 0 ] ) else : print ( "no match shape" ) return None class BPNet ( object ) : def __init__ ( self
) : """構建單隱層神經網絡""" self
. weights
= None self
. bias
= None self
. history
= { 'loss' : [ ] , 'accuracy' : [ ] } def train ( self
, x
, y
, trained_weights
= None , learning_rate
= 1e - 3 , epochs
= 100 ) : if trained_weights
: self
. weights
= [ trained_weights
[ 0 ] [ : , 1 : ] , trained_weights
[ 1 ] [ : , 1 : ] ] self
. bias
= [ trained_weights
[ 0 ] [ : , 0 ] , trained_weights
[ 1 ] [ : , 0 ] ] else : print ( "init weights" ) self
. weights
= [ np
. random
. normal
( size
= [ 25 , 400 ] ) , np
. random
. normal
( size
= [ 10 , 25 ] ) ] self
. bias
= [ np
. random
. normal
( size
= [ 25 , 1 ] ) , np
. random
. normal
( size
= [ 10 , 1 ] ) ] for epoch
in range ( epochs
) : for i
in range ( x
. shape
[ 0 ] ) : img
= x
[ i
] . reshape
( - 1 , 1 ) label
= y
[ i
] . reshape
( - 1 , 1 ) input_hidden
= self
. weights
[ 0 ] @ img
+ self
. bias
[ 0 ] . reshape
( - 1 , 1 ) output_hidden
= sigmoid
( input_hidden
) input_output
= self
. weights
[ 1 ] @ output_hidden
+ self
. bias
[ 1 ] . reshape
( - 1 , 1 ) output_output
= sigmoid
( input_output
) output_error
= sigmoid_grad
( output_output
) * ( label
- output_output
) hidden_error
= sigmoid_grad
( output_hidden
) * ( self
. weights
[ 1 ] . T @ output_error
) self
. weights
[ 1 ] += ( output_error @ output_hidden
. T
) * learning_rateself
. bias
[ 1 ] += output_error
* learning_rateself
. weights
[ 0 ] += ( hidden_error @ img
. T
) * learning_rateself
. bias
[ 0 ] += hidden_error
* learning_ratepred_epoch
= np
. argmax
( np
. squeeze
( self
. predict
( x
) , axis
= - 1 ) , axis
= 1 ) y_true
= np
. argmax
( y
, axis
= 1 ) acc
= np
. sum ( pred_epoch
. reshape
( - 1 , 1 ) == y_true
. reshape
( - 1 , 1 ) ) / y
. shape
[ 0 ] loss
= mse
( y
, self
. predict
( x
) ) self
. history
[ 'loss' ] . append
( loss
) self
. history
[ 'accuracy' ] . append
( acc
) print ( "epoch {}, loss {}, accuracy {}" . format ( epoch
, loss
, acc
) ) if epoch
> 10 and abs ( self
. history
[ 'loss' ] [ - 1 ] - self
. history
[ 'loss' ] [ - 2 ] ) < 1e - 5 : break return self
. history
def predict ( self
, x
, trained_weights
= None ) : if trained_weights
: self
. weights
= [ trained_weights
[ 0 ] [ : , 1 : ] , trained_weights
[ 1 ] [ : , 1 : ] ] self
. bias
= [ trained_weights
[ 0 ] [ : , 0 ] , trained_weights
[ 1 ] [ : , 0 ] ] if self
. weights
is None : print ( "no weights, cannot predict" ) result
= [ ] for i
in range ( x
. shape
[ 0 ] ) : img
= x
[ i
] . reshape
( - 1 , 1 ) input_hidden
= self
. weights
[ 0 ] @ img
+ self
. bias
[ 0 ] . reshape
( - 1 , 1 ) output_hidden
= sigmoid
( input_hidden
) input_output
= self
. weights
[ 1 ] @ output_hidden
+ self
. bias
[ 1 ] . reshape
( - 1 , 1 ) output_output
= sigmoid
( input_output
) result
. append
( output_output
) return np
. array
( result
) if __name__
== '__main__' : data
= scio
. loadmat
( '../data/ex3data1.mat' ) pretrained_weights
= scio
. loadmat
( '../data/ex3weights.mat' ) X
, y
= data
[ 'X' ] , data
[ 'y' ] y
= LabelBinarizer
( ) . fit_transform
( y
) w_hidden
, w_output
= pretrained_weights
[ 'Theta1' ] , pretrained_weights
[ 'Theta2' ] net
= BPNet
( ) pred_result
= net
. predict
( X
, [ w_hidden
, w_output
] ) pred_result
= np
. argmax
( np
. squeeze
( pred_result
, axis
= - 1 ) , axis
= 1 ) y_true
= np
. argmax
( y
, axis
= 1 ) print ( "載入參數前向傳播準確率" , np
. sum ( pred_result
. reshape
( - 1 , 1 ) == y_true
. reshape
( - 1 , 1 ) ) / y
. shape
[ 0 ] ) his
= net
. train
( X
, y
, learning_rate
= 1e - 1 , epochs
= 200 ) plot_his
( his
)
可視化訓練過程,結果如下。
補充說明
本文簡單敘述了神經網絡的簡單思想并進行簡單的單隱層網絡實驗,思路參照吳恩達的機器學習課程(Coursera)。 本系列相關的博文和代碼開放于Github,歡迎訪問項目。同時博客也同步在我的個人博客網站,歡迎訪問查看其他文章。 由于能力有限,如有錯誤,歡迎評論指正。
總結
以上是生活随笔 為你收集整理的机器学习-神经网络 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。