神經網絡學習——第一個代碼學習

學習的博客來自:人工神經網絡——反向傳播算法(BP)以及Python實現
一共分爲兩個py文件
1、BPNN

"""
輸入層:3
隱藏層:3
輸出層:2
"""
import numpy as np
import math
import matplotlib.pyplot as plt

# 激勵函數及相應導數
def sigmoid(x):
    return 1.0 / (1 + np.exp(-x))
def diff_sigmoid(x):
    fval = sigmoid(x)
    return fval * (1 - fval)
def linear(x):
    return x
def diff_linear(x):
    return np.ones_like(x)


class BP:
    def __init__(self, n_hidden=None, f_hidden='sigmoid', f_output='linear',
                 epsilon=0, maxstep=0, eta=0, alpha=0):
        """
        :param n_hidden: 輸入層神經元數目
        :param f_hidden: 隱藏層神經元數目
        :param f_output: 輸出層神經元數目
        :param epsilon: 閾值
        :param maxstep:
        :param eta: 學習率
        :param alpha: 動量因子
        :return:
        """
        self.n_input = None
        self.n_hidden = n_hidden
        self.n_output = None
        self.f_hidden = f_hidden
        self.f_output = f_output
        self.epsilon = epsilon
        self.maxstep = maxstep
        self.eta = eta
        self.alpha = alpha

        self.wih = None  # 輸入層到隱藏層權值矩陣
        self.who = None  # 隱藏層到輸出層權值矩陣
        self.bih = None  # 輸入層到隱藏層閾值
        self.bho = None  # 隱藏層到輸出層閾值
        self.N = None

    def init_param(self, X_data, y_data):
        # 初始化
        if len(X_data.shape) == 1:  # 若輸入數據爲一維數組,則進行轉置爲n維數組
            X_data = np.transpose([X_data])
        self.N = X_data.shape[0]
        # normalizer = np.linalg.norm(X_data, axis=0)
        # X_data = X_data / normalizer
        if len(y_data.shape) == 1:
            y_data = np.transpose([y_data])
        self.n_input = X_data.shape[1]
        self.n_output = y_data.shape[1]
        if self.n_hidden is None:
            self.n_hidden = int(math.ceil(math.sqrt(self.n_input + self.n_output)) + 2)
        self.wih = np.random.rand(self.n_input, self.n_hidden)  # i*h
        self.who = np.random.rand(self.n_hidden, self.n_output)  # h*o
        self.bih = np.random.rand(self.n_hidden)  # h
        self.bho = np.random.rand(self.n_output)  # o
        return X_data, y_data

    def inspirit(self, name):
        # 獲取相應的激勵函數
        if name == 'sigmoid':
            return sigmoid
        elif name == 'linear':
            return linear
        else:
            raise ValueError('the function is not supported now')

    def diff_inspirit(self, name):
        # 獲取相應的激勵函數的導數
        if name == 'sigmoid':
            return diff_sigmoid
        elif name == 'linear':
            return diff_linear
        else:
            raise ValueError('the function is not supported now')

    def forward(self, X_data):
        # 前向傳播
        x_hidden_in = np.dot(X_data, self.wih) + self.bih  # n*h
        x_hidden_out = self.inspirit(self.f_hidden)(x_hidden_in)  # n*h
        x_output_in = np.dot(x_hidden_out, self.who) + self.bho  # n*o
        x_output_out = self.inspirit(self.f_output)(x_output_in)  # n*o
        return x_output_out, x_output_in, x_hidden_out, x_hidden_in

    def fit(self, X_data, y_data):
        # 訓練主函數
        X_data, y_data = self.init_param(X_data, y_data)
        step = 0
        E = np.zeros_like(y_data)
        # 初始化動量項
        delta_wih = np.zeros_like(self.wih)
        delta_who = np.zeros_like(self.who)
        delta_bih = np.zeros_like(self.bih)
        delta_bho = np.zeros_like(self.bho)
        while step < self.maxstep:
            step += 1
            # 向前傳播
            x_output_out, x_output_in, x_hidden_out, x_hidden_in = self.forward(X_data)
            if np.sum(abs(x_output_out - y_data)) < self.epsilon:
                break
            # 計算誤差函數E = 0.5*(y_data - x_output_out)^2
            E = 0.5*(y_data - x_output_out)**2

            # 誤差反向傳播,依據權值逐層計算當層誤差
            err_output = y_data - x_output_out  # n*o, 輸出層上,每個神經元上的誤差
            delta_ho = -err_output * self.diff_inspirit(self.f_output)(x_output_in)  # n*o
            err_hidden = np.dot(delta_ho, self.who.T)  # n*h, 隱藏層(相當於輸入層的輸出),每個神經元上的誤差
            # 隱藏層到輸出層權值及閾值更新
            delta_bho = np.sum(self.eta * delta_ho + self.alpha * delta_bho, axis=0) / self.N
            self.bho -= delta_bho
            delta_who = np.dot(self.eta * x_hidden_out.T, delta_ho) + self.alpha * delta_who
            self.who -= delta_who
            # 輸入層到隱藏層權值及閾值的更新
            delta_ih = err_hidden * self.diff_inspirit(self.f_hidden)(x_hidden_in)  # n*h
            delta_bih = np.sum(self.eta * delta_ih + self.alpha * delta_bih, axis=0) / self.N
            self.bih -= delta_bih
            delta_wih = np.dot(self.eta * X_data.T, delta_ih) + self.alpha * delta_wih
            self.wih -= delta_wih
        return

    def predict(self, X):
        # 預測
        res = self.forward(X)
        return res[0]

2、Mytest

"""
Input: 訓練數據集X_data和y_data, 神經網絡必要參數,誤差閾值epsilon,最大迭代次數maxstep
Output: 神經網絡權值W
Step1: 初始化權值矩陣W,閾值b
Step2: 迭代訓練直到誤差小於閾值epsilon或達到最大迭代次數maxstep。訓練步驟包括前向傳播和誤差反向傳播。

"""

import matplotlib.pyplot as plt
import numpy as np
import BPNN
N = 100
X_data = np.linspace(-1, 1, N)
X_data = np.transpose([X_data])
y_data = np.exp(-X_data) * np.sin(2 * X_data)
plt.plot(X_data, y_data, color='red', label='trainning data',linewidth=3)

bp100 = BPNN.BP(n_hidden=None, f_hidden='sigmoid',f_output='linear',
             maxstep=100,epsilon=1e-3, eta=0.01, alpha=0.1)
bp100.fit(X_data, y_data)
pred100 = bp100.predict(X_data)

bp500 = BPNN.BP(n_hidden=None, f_hidden='sigmoid',f_output='linear',
             maxstep=500,epsilon=1e-3, eta=0.01, alpha=0.1)
bp500.fit(X_data, y_data)
pred500 = bp500.predict(X_data)

bp1000 = BPNN.BP(n_hidden=None, f_hidden='sigmoid',f_output='linear',
             maxstep=1000,epsilon=1e-3, eta=0.01, alpha=0.1)
bp1000.fit(X_data, y_data)
pred1000 = bp1000.predict(X_data)

bp2000 = BPNN.BP(n_hidden=None, f_hidden='sigmoid',f_output='linear',
             maxstep=2000,epsilon=1e-3, eta=0.01, alpha=0.1)
bp2000.fit(X_data, y_data)
pred2000 = bp2000.predict(X_data)

plt.plot(X_data, pred100, color='gold', label='maxstep=100')
plt.plot(X_data, pred500, color='blue', label='maxstep=500')
plt.plot(X_data, pred1000, color='purple', label='maxstep=1000')
plt.plot(X_data, pred2000, color='green', label='maxstep=2000')
plt.legend()

plt.show()

3、結果
a. maxstep越大,預測值越靠近實際
在這裏插入圖片描述

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