1. 程式人生 > >Javascript實現BP神經網絡

Javascript實現BP神經網絡

BP神經網絡 機器學習 Javascript

BP神經網絡是一種按照誤差逆向傳播算法訓練的多層前饋神經網絡,是目前應用最廣泛的神經網絡。
BP神經網絡誤差反向傳播神經網絡:

  1. 置各權和閾值的初始化
  2. 給定P個訓練樣本Xp(p=1,2,...,p) 和對應的理想輸出Dp(p=1,2,...p)
  3. 信息前向傳遞:
    計算網絡各層的輸出
    技術分享圖片

4.誤差反向傳播
技術分享圖片
5.修改權和閾值
技術分享圖片
6.重復2~5步,直至P個樣本都訓練一邊
7.判斷是否滿足精度要求。若滿足,則停止訓練,否則重復第2步。

根據上述流程,編寫代碼:

class BPNet{
        constructor(layernum, n, fn, fd, miu, iter ,eps){
            if(!(n instanceof Array)) {
                throw ‘參數錯誤‘
            }
            if(!n.length == layernum) {
                throw ‘參數錯誤‘
            }
            this.layernum = layernum
            this.n = n
            //輸出函數
            if(!fn) {
                this.fn = function (x) {
                    return 1.0/(1.0 + Math.exp(-x))
                }
            }else {
                this.fn = fn
            }
            //誤差函數
            if(!fd) {
                this.fd = function(x) {
                    return x * (1 - x)
                }
            }else {
                this.fd = fd
            }
            this.w = new Array()//權值矩陣
            this.b = new Array() //閾值矩陣
            this.miu = miu    || 0.5 //學習速率
            this.iter = iter || 500 //叠代次數
            this.e = 0.0 //誤差
            this.eps = eps || 0.0001
            for(let l = 1; l < this.layernum;l++) {
                let item = new Array()
                let bitem = new Array()
                for(let j = 0;j < n[l]; j++) {
                    let temp = new Array()
                    for(let i = 0;i < n[l - 1];i++) {
                        temp[i] = Math.random()
                    }
                    item.push(temp)
                    bitem.push(Math.random())
                }
                this.w[l] = item
                this.b[l] = bitem
            }
        }
        //預測函數
        forward(x) {
            let y = new Array()
            y[0] = x
            for(let l = 1; l < this.layernum;l++) {
                y[l] = new Array()
                for(let j = 0;j < this.n[l]; j++) {
                    let u = 0.0
                    for(let i = 0;i < this.n[l - 1]; i++) {
                        u = u + this.w[l][j][i] * y[l - 1][i]
                    }
                    u = u + this.b[l][j]
                    y[l][j] = this.fn(u)
                }
            }
            return y
        }
        //計算誤差
        calcdelta(d, y) {
            let delta = new Array()
            let last = new Array()
            for(let j = 0;j < this.n[this.layernum - 1];j++){
                last[j] = (d[j] - y[this.layernum - 1][j]) * this.fd(y[this.layernum - 1][j])
            }
            delta[this.layernum - 1] = last
            for(let l = this.layernum - 2;l > 0; l--) {
                delta[l] = new Array()
                for(let j = 0;j < this.n[l]; j++) {
                    delta[l][j] = 0.0
                    for(let i = 0; i < this.n[l + 1];i++) {
                        delta[l][j] += delta[l + 1][i] * this.w[l+1][i][j]
                    }
                    delta[l][j] = this.fd(y[l][j])*delta[l][j]
                }
            }
            return delta
        }
        //調整權值和閾值
        update(y, delta) {
            for(let l = 0; l < this.layernum;l++) {
                for(let j = 0;j < this.n[l];j++) {
                    for(let i = 0;i < this.n[l - 1];i++) {
                        this.w[l][j][i] += this.miu * delta[l][j] * y[l-1][i]
                        this.b[l][j] += this.miu * delta[l][j]
                    }
                }
            }
        }
        //樣本訓練
        train(x, d) {
            for(let p = 0;p < this.iter;p++) {
                this.e = 0
                for(let i = 0;i < x.length;i++) {
                    let y = this.forward(x[i])
                    let delta = this.calcdelta(d[i], y)
                    this.update(y, delta)
                    let ep = 0.0
                    let l1 = this.layernum - 1
                    for(let l = 0;l < this.n[l1];l++) {
                        ep += (d[i][l] - y[l1][l]) * (d[i][l] - y[l1][l])
                    }
                    this.e += ep/2.0
                }
                if(this.e < this.eps) {
                    break;
                }
            }
        }
    }

使用方式:
用BP神經網絡實現異或邏輯:
技術分享圖片

let x = [[0,0],[0,1],[1,0],[1,1]]//輸入樣本
    let d = [[0],[1],[1],[0]]//理想輸出
    let bp = new BPNet(3, [2,6,1], undefined, undefined, 0.5, 5000 ,0.0001)
    bp.train(x,d)
   let y = bp.forward([0, 1])
    console.log(y[2][0])
    let y2 = bp.forward([0,0])
    console.log(y2[2][0])
    let y3 = bp.forward([1,1])
    console.log(y3[2][0])
    let y4 = bp.forward([1, 0])
    console.log(y4[2][0])

結果:
技術分享圖片

Javascript實現BP神經網絡