Python實現的人工神經網絡算法示例【基於反向傳播算法】

本文實例講述了Python實現的人工神經網絡算法。分享給大家供大家參考,具體如下:

注意:本程序使用Python3編寫,額外需要安裝numpy工具包用於矩陣運算,未測試python2是否可以運行。

本程序實現了《機器學習》書中所述的反向傳播算法訓練人工神經網絡,理論部分請參考我的讀書筆記。

在本程序中,目標函數是由一個輸入x和兩個輸出y組成,
x是在範圍【-3.14, 3.14】之間隨機生成的實數,而兩個y值分別對應 y1 = sin(x),y2 = 1。

隨機生成一萬份訓練樣例,經過網絡的學習訓練後,再用隨機生成的五份測試數據驗證訓練結果。

調節算法的學習速率,以及隱藏層個數、隱藏層大小,訓練新的網絡,可以觀察到參數對於學習結果的影響。

算法代碼如下:

#!usr/bin/env python3
# -*- coding:utf-8 -*-
import numpy as np
import math
# definition of sigmoid funtion
# numpy.exp work for arrays.
def sigmoid(x):
  return 1 / (1 + np.exp(-x))
# definition of sigmoid derivative funtion
# input must be sigmoid function's result
def sigmoid_output_to_derivative(result):
  return result*(1-result)
# init training set
def getTrainingSet(nameOfSet):
  setDict = {
    "sin": getSinSet(),
    }
  return setDict[nameOfSet]
def getSinSet():
  x = 6.2 * np.random.rand(1) - 3.14
  x = x.reshape(1,1)
  # y = np.array([5 *x]).reshape(1,1)
  # y = np.array([math.sin(x)]).reshape(1,1)
  y = np.array([math.sin(x),1]).reshape(1,2)
  return x, y
def getW(synapse, delta):
  resultList = []
  # 遍歷隱藏層每個隱藏單元對每個輸出的權值,比如8個隱藏單元,每個隱藏單元對兩個輸出各有2個權值
  for i in range(synapse.shape[0]):
    resultList.append(
      (synapse[i,:] * delta).sum()
      )
  resultArr = np.array(resultList).reshape(1, synapse.shape[0])
  return resultArr
def getT(delta, layer):
  result = np.dot(layer.T, delta)
  return result
def backPropagation(trainingExamples, etah, input_dim, output_dim, hidden_dim, hidden_num):
  # 可行條件
  if hidden_num < 1:
    print("隱藏層數不得小於1")
    return
  # 初始化網絡權重矩陣,這個是核心
  synapseList = []
  # 輸入層與隱含層1
  synapseList.append(2*np.random.random((input_dim,hidden_dim)) - 1)
  # 隱含層1與隱含層2, 2->3,,,,,,n-1->n
  for i in range(hidden_num-1):
    synapseList.append(2*np.random.random((hidden_dim,hidden_dim)) - 1)
  # 隱含層n與輸出層
  synapseList.append(2*np.random.random((hidden_dim,output_dim)) - 1)
  iCount = 0
  lastErrorMax = 99999
  # while True:
  for i in range(10000):
    errorMax = 0
    for x, y in trainingExamples:
      iCount += 1
      layerList = []
      # 正向傳播
      layerList.append(
        sigmoid(np.dot(x,synapseList[0]))
        )
      for j in range(hidden_num):
        layerList.append(
          sigmoid(np.dot(layerList[-1],synapseList[j+1]))
          )
      # 對於網絡中的每個輸出單元k,計算它的誤差項
      deltaList = []
      layerOutputError = y - layerList[-1]
      # 收斂條件
      errorMax = layerOutputError.sum() if layerOutputError.sum() > errorMax else errorMax
      deltaK = sigmoid_output_to_derivative(layerList[-1]) * layerOutputError
      deltaList.append(deltaK)
      iLength = len(synapseList)
      for j in range(hidden_num):
        w = getW(synapseList[iLength - 1 - j], deltaList[j])
        delta = sigmoid_output_to_derivative(layerList[iLength - 2 - j]) * w
        deltaList.append(delta)
      # 更新每個網絡權值w(ji)
      for j in range(len(synapseList)-1, 0, -1):
        t = getT(deltaList[iLength - 1 -j], layerList[j-1])
        synapseList[j] = synapseList[j] + etah * t
      t = getT(deltaList[-1], x)
      synapseList[0] = synapseList[0] + etah * t
    print("最大輸出誤差:")
    print(errorMax)
    if abs(lastErrorMax - errorMax) < 0.0001:
      print("收斂了")
      print("####################")
      break
    lastErrorMax = errorMax
  # 測試訓練好的網絡
  for i in range(5):
    xTest, yReal = getSinSet()
    layerTmp = sigmoid(np.dot(xTest,synapseList[0]))
    for j in range(1, len(synapseList), 1):
      layerTmp = sigmoid(np.dot(layerTmp,synapseList[j]))
    yTest = layerTmp
    print("x:")
    print(xTest)
    print("實際的y:")
    print(yReal)
    print("神經元網絡輸出的y:")
    print(yTest)
    print("最終輸出誤差:")
    print(np.abs(yReal - yTest))
    print("#####################")
  print("迭代次數:")
  print(iCount)
if __name__ == '__main__':
  import datetime
  tStart = datetime.datetime.now()
  # 使用什麼樣的訓練樣例
  nameOfSet = "sin"
  x, y = getTrainingSet(nameOfSet)
  # setting of parameters
  # 這裏設置了學習速率。
  etah = 0.01
  # 隱藏層數
  hidden_num = 2
  # 網絡輸入層的大小
  input_dim = x.shape[1]
  # 隱含層的大小
  hidden_dim = 100
  # 輸出層的大小
  output_dim = y.shape[1]
  # 構建訓練樣例
  trainingExamples = []
  for i in range(10000):
    x, y = getTrainingSet(nameOfSet)
    trainingExamples.append((x, y))
  # 開始用反向傳播算法訓練網絡
  backPropagation(trainingExamples, etah, input_dim, output_dim, hidden_dim, hidden_num)
  tEnd = datetime.datetime.now()
  print("time cost:")
  print(tEnd - tStart)

最後給大家推薦一個口碑不錯的python聚集地【點擊進入】,這裏有很多的老前輩學習技巧,學習心得,面試技巧,職場經歷等分享,更爲大家精心準備了零基礎入門資料,實戰項目資料,每天都有程序員定時講解Python技術,分享一些學習的方法和需要留意的小細節

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章