1. 程式人生 > >用numpy構造的一個簡單BP

用numpy構造的一個簡單BP

# -*- coding: utf-8 -*-
"""
Created on Thu Oct  4 08:28:15 2018

@author: 37989
"""

import numpy as np
import pandas as pd
from matplotlib import pyplot


# 標準化
def Standard(X):
    X_mean = X.mean(axis=0)
    X_std = (((X - X_mean) ** 2).sum(axis=0) / len(X)) ** 0.5
    return (X - X_mean) / X_std

# 歸一化
def MaxMin(X):
    X_min = X.min(axis=0)
    X_max = X.max(axis=0)
    return (X - X_min) / (X_max - X_min)

# 啟用函式
def sigmod(X):
    return 1 / (1 + np.power(np.e, -X))

# 正切函式
def tanh(X):
    return 1 - 2 / (np.power(np.e, 2 * X) + 1)


# 建立模型
# 預設隨機[-1,1]初始化權值閾值
def build(netNum):
    W, Q= [],[]
    for i in range(len(netNum) - 1):
        W.append((np.random.rand(netNum[i], netNum[i+1]) - 0.5) * 2)
        Q.append((np.random.rand(1, netNum[i+1]) - 0.5) * 2)
    return W, Q

# 預測模型
def predict(W, Q, X):
    for i in range(len(W)):
        X = np.dot(X, W[i]) - Q[i]
        X = sigmod(X)
    return X

# 訓練集,測試集劃分
def dataSplit(X, Y, testPer):
    testNum = int(len(X) * testPer)
    rand = np.random.permutation(len(X))
    x_test = X[rand[:testNum]]
    y_test = Y[rand[:testNum]]
    x_train = X[rand[testNum:]]
    y_train = Y[rand[testNum:]]
    return x_train, y_train, x_test, y_test



if __name__ == '__main__':

    # maxmin 歸一化
    # sigmod 啟用函式
    #

    # 載入資料
    data = pd.read_csv(r'F:\Temp\Python\scrapy\myspider\myspider\tensorflow\DataBase\data_continuous.csv')
    X_label = ['F1', 'F2', 'F3', 'F4']
    Y_label = ['R']
    X = data[X_label].values
    Y = data[Y_label].values
    netNum = [len(X_label)]

    # 相關引數設定
    learnRate = 0.05 # 學習率
    echos = 100     # 迭代次數
    netNum += [10]  # 隱層節點
    testPer = 0.3   # 測試集比例

    # 標準化
    X = MaxMin(X)
    Y = MaxMin(Y)

    # 建立模型
    netNum.append(len(Y_label))
    W, Q = build(netNum)

    x_train, y_train, x_test, y_test = dataSplit(X, Y, testPer)

    # 訓練
    for num in range(echos):
        for position in range(len(x_train)):
            x = x_train[position].reshape(1,netNum[0])
            y = y_train[position]

            out_x = [x]
            for i in range(len(W)):
                # 隱層結果
                temp = np.dot(x, W[i]) - Q[i]
                x = sigmod(temp)
                out_x.append(x)

            # 最終輸出
            output_y = out_x[-1]

            # 更新
            e = output_y * (1 - output_y) * (y - output_y)
            for i in range(len(W)-1,-1,-1):
                x = out_x[i]
                n = netNum[i]
                W[i] += learnRate * np.dot(x.reshape(n, 1), e)
                Q[i] -= learnRate * e
                e = (W[i] * e).sum(axis=1) * x * (1 - x)

        # 驗證網路模型
        predict_y = predict(W, Q, x_train)
        mse = ((y_train - predict_y) ** 2).sum() / len(x_train)
        print("第 %d 次訓練,均方誤差為:%f" % (num+1, mse))

    # 模型評估
    predict_y = predict(W, Q, x_test)
    mse = ((y_test - predict_y) ** 2).sum() / len(y_test)
    print("測試集均方誤差為:%f" % mse)
    pyplot.scatter(predict_y, y_test)
    pyplot.show()

一個簡單的BP迴歸模型,

資料格式:

    F1     F2     F3     F4  .......    R1    R2     R3

    21.5  4.5     5       6  .......     2        5       4

可以構造多層神經網路,隱層結構和引數netNum中設定:

     比如netNum = [8,6,9],那麼網路結構為  inputnum -> 8 -> 6 -> 9 -> outputnum

可以設定迭代次數 echos 、學習率learnrate、測試集比重testPer

訓練效果一般,僅供練習程式碼。