天天看點

深度學習 :神經網絡學習總結(上)sigmoid激活函數

  • 激活函數

    激活函數的存在,是神經網絡與感覺機不同的地方。

    神經網絡的激活函數必須使用非線性函數!

    1. sigmoid函數

g(x)=1/(1+exp(−x))g(x)=1/(1+exp(-x) ) g(x)=1/(1+exp(−x))

![sigmoid函數表達式為:g(x)=1/(1+e^(-x) );](https://secure1.wostatic.cn/static/81mgxiAPGXreqKe11SLQfY/sigmoid.jpg)

Sigmoid函數其定義域在全體實數,值域在[0,1]之間,并且在0點位置為0.5。 當x的取值為[-∞,0]時,g(x)<=0; 當x的取值為[0,+∞]時,g(x)>=0; Sigmoid函數具有兩個非常好的性質: (1):當x趨近于正無窮時,g(x)趨近于1,當x趨近于負無窮時,g(x)趨近于0.這一點非常适合做分類機率模型。 (2):除此之外,sigmoid函數還具有一個很到的導數性質,即sigmoid函數時任意階可導的凸函數。

** 2. ReLu函數**

ReLu函數是最近才開始使用的函數,**ReLu函數在輸入大于0時,直接輸出該值;在輸出小于等于0時,輸出0。**
           
  1. softmax函數

softmax函數一般用于神經網絡的輸出層,softmax函數的性質是:softmax函數的輸出是0.0~1.0之間的實數,并且softmax函數的輸出值的總和是1**。**是以我們可以把softmax函數的輸出解釋為“機率”。

即便是使用softmax函數,輸出值最大的神經元的位置也不會改變。

sigmoid激活函數

def sigmoid(x):

  return 1/(1+np.exp(-x))

#ReLu激活函數

def ReLu(x):

  if x < 0:

    return 0

  else:

    return x

#softmax激活函數(輸出層)

def softmax(x):

  exp_x = np.exp(x)

  sum_exp_x = np.sum(exp_x)

  y = exp_x/sum_exp_x

  return y
           
  • 損失函數

    神經網絡以某個名額為線索尋找最優權重參數。神經網絡的學習中所用的名額成為損失函數(loss function)。這個損失函數可以使用任意的函數表示,但是一般來說都使用均方誤差和交叉熵誤差等。

    在尋找最優參數(權重和偏置)時,要尋找使得損失函數的值盡可能小的參數。為了尋找到使得損失函數的值盡可能小的地方,需要計算參數的導數(确切地将時梯度),然後以這個導數為指引,逐漸更新參數的值。

#均方誤差損失函數

def mean_squared_error(y,t):

  return 0.5*np.sum((y-t)**2)

#交叉熵損失函數

def cross_entropy_error(y,t):

  delta = 1e-7

  return -np.sum(np.array(t)*np.log(np.array(y)+delta))
           
  • 梯度

    變量的偏導數彙總而成的向量稱為梯度(gradient)。

    機器學習的主要任務是在學習中尋找最優參數。同樣地,神經網絡也必須在學習時找到最優參數(權重和偏置)。這裡所說的最優參數是指損失函數取最小值時的參數。

    通過梯度來尋找函數最小值(或者盡可能小的值)的方法就是梯度法。

    尋找最小值的梯度法為梯度下降法,尋找最大值的梯度法稱為梯度上升法。(神經網絡學習中,梯度法主要是指梯度下降法)。

    ![](https://secure1.wostatic.cn/static/5dJy2FASPV6sm1b79jPcPU/捕獲 1.jpg)

其中η表示更新量,在神經網絡的學習中,稱為學習率(learning rate)。(學習率過大或者過小都無法得到好結果)

#求梯度

def numerical_gradient(f,x):

  h = 1e-4

  grad = np.zeros_like(x)

  for i in range(x.size):

    tmp = x[i]

    x[i] = tmp + h

    fxh1 = f(x)

    x[i] = tmp - h

    fxh2 = f(x)

    grad[i] = (fxh1 - fxh2) / (h*2)

    x[i] = tmp

  return grad

#梯度下降法

def gradient_descent(f, init_x, lr=0.01, step_num=100):

  x = init_x

  for i in range(step_num):

    grad = numerical_gradient(f, x)

    x -= lr * grad

  return x
           
  • 總結 學習算法的實作

    前提

    神經網絡存在合适的權重和偏置,調整權重和偏置以便拟合訓練資料的

    過程稱為“學習”。神經網絡的學習分成下面4個步驟。

    步驟1( mini-batch)

    從訓練資料中随機選出一部分資料,這部分資料稱為mini-batch。我們

    的目标是減小mini-batch的損失函數的值。

    步驟2(計算梯度)

    為了減小mini-batch的損失函數的值,需要求出各個權重參數的梯度。

    梯度表示損失函數的值減小最多的方向。

    步驟3(更新參數)

    将權重參數沿梯度方向進行微小更新。

    步驟4(重複)

    重複步驟1、步驟2、步驟3。

  • 兩層神經網絡程式設計實作(采用前向傳播)
變量 說明
params 儲存神經網絡的參數的字典型變量(執行個體變量)。 params['W1']是第1層的權重, params['b1']是第1層的偏置。 params['W2']是第2層的權重, params['b2']是第2層的偏置
grads 儲存梯度的字典型變量( numerical_gradient()方法的傳回值)。grads['W1']是第1層權重的梯度, grads['b1']是第1層偏置的梯度。grads['W2']是第2層權重的梯度, grads['b2']是第2層偏置的梯度。
方法 說明
init(self, input_size,hidden_size, output_size) 進行初始化。 參數從頭開始依次表示輸入層的神經元數、隐藏層的神經元數、輸出層的神經元數
predict(self, x) 進行識别(推理)。 參數x是圖像資料。
loss(self, x, t) 計算損失函數的值。 參數 x是圖像資料, t是正确解标簽(後面3個方法的參數也一樣)。
accuracy(self, x, t) 計算識别精度。
numerical_gradient(self, x, t) 計算權重參數的梯度。
gradient(self, x, t) 計算權重參數的梯度。
**權重的初始化使用符合高斯分布的随機數進行初始化,偏置使用0進行初始化**
           
  • mini-batch的實作

    mini-batch學習就是i從訓練資料中,随機選擇一部分資料(這部分資料稱之為mini-batch),再以這部分資料為對象,使用梯度法更新參數。

#2層神經網絡的分類
#輸入層激活函數sigmoid
def sigmoid(x):
    return 1/(1+np.exp(-x))
#輸出層激活函數softmax
def softmax(x):
    exp_x = np.exp(x)
    sum_exp_x = np.sum(exp_x)
    y = exp_x/sum_exp_x
    return y
#交叉熵損失函數
def cross_entropy_error(y,t):
    delta = 1e-7
    return -np.sum(np.array(t)*np.log(np.array(y)+delta))
#求梯度
def numerical_gradient(f,x):
  h = 1e-4
  grad = np.zeros_like(x)

  for i in range(x.size):
    tmp = x[i]
    x[i] = tmp + h
    fxh1 = f(x)

    x[i] = tmp - h
    fxh2 = f(x)

    grad[i] = (fxh1 - fxh2) / (h*2)
    x[i] = tmp
  return grad
class twolayernet:
    def __init__(self,input_size,hidden_size,output_size,weight_init_std=0.01):
        #初始化權重
        self.params = {}
        self.params['w1'] = weight_init_std * np.random.randn(input_size,hidden_size)
        self.params['b1'] = np.zeros(hidden_size)
        self.params['w2'] = weight_init_std * np.random.randn(hidden_size,output_size)
        self.params['b2'] = np.zeros(output_size)
    def predict(self,x):
        w1,w2 = self.params['w1'],self.params['w2']
        b1,b2 = self.params['b1'],self.params['b2']
        a1 = np.dot(x,w1)+b1
        z1 = sigmoid(a1)
        a2 = np.dot(z1,w2)+b2
        y = softmax(a2)
        return y
    def loss(self,x,t):
        y = self.predict(x)
        return cross_entropy_error(y,t)
    def accuracy(self,x,t):
        y = self.predict(x)
        y = np.argmax(y,axis=1)
        t = np.argmax(t,axis=1)
        accuracy = np.sum(y == t) / float(x.shape[0])
        return accuracy
    #x:輸入資料 y:監督資料
    def numerical_gradient(self,x,t):
        loss_w = lambda w:self.loss(x,t)

        grads = {}
        grads['w1'] = numerical_gradient(loss_w,self.params['w1'])
        grads['b1'] = numerical_gradient(loss_w, self.params['b1'])
        grads['w2'] = numerical_gradient(loss_w, self.params['w2'])
        grads['b2'] = numerical_gradient(loss_w, self.params['b2'])
        return grads
           

繼續閱讀