BP神經網路演算法程式實現鳶尾花(iris)資料集分類
阿新 • • 發佈:2020-10-07
作者有話說
最近學習了一下BP神經網路,寫篇隨筆記錄一下得到的一些結果和程式碼,該隨筆會比較簡略,對一些簡單的細節不加以說明。
目錄
- BP演算法簡要推導
- 應用例項
- PYTHON程式碼
BP演算法簡要推導
該部分用一個$2\times3\times 2\times1$的神經網路為例簡要說明BP演算法的步驟。
- 向前計算輸出
- 反向傳播誤差
- 權重更新
應用例項
鳶尾花資料集一共有150個樣本,分為3個類別,每個樣本有4個特徵,(資料集連結:http://archive.ics.uci.edu/ml/datasets/Iris)。針對該資料集,選取如下神經網路結構和啟用函式
- 神經網路組成
- 隱含層神經元個數對準確率的影響
調節隱含層神經元的個數,得到模型分類準確率的變化影象如下:
- 梯度更新步長對準確率的影響
調節梯度更新步長(學習率)的大小,得到模型分類準確率的變化影象如下:
可見準確率最高可達98.6666666666667%
PYTHON程式碼
BPNeuralNetwork.py
# coding=utf-8 import numpy as np def tanh(x): return np.tanh(x) def tanh_deriv(x): return 1.0 - np.tanh(x) * np.tanh(x) def logistic(x): return 1.0 / (1.0 + np.exp(-x)) def logistic_derivative(x): return logistic(x) * (1.0 - logistic(x)) class NeuralNetwork: def __init__(self, layers, activation='tanh'): """ """ if activation == 'logistic': self.activation = logistic self.activation_deriv = logistic_derivative elif activation == 'tanh': self.activation = tanh self.activation_deriv = tanh_deriv self.weights = [] self.weights.append((2 * np.random.random((layers[0] + 1, layers[1] - 1)) - 1) * 0.25) for i in range(2, len(layers)): self.weights.append((2 * np.random.random((layers[i - 1], layers[i])) - 1) * 0.25) # self.weights.append((2*np.random.random((layers[i]+1,layers[i+1]))-1)*0.25) def fit(self, X, y, learning_rate=0.2, epochs=10000): X = np.atleast_2d(X) # atlest_2d函式:確認X至少二位的矩陣 temp = np.ones([X.shape[0], X.shape[1] + 1]) # 初始化矩陣全是1(行數,列數+1是為了有B這個偏向) temp[:, 0:-1] = X # 行全選,第一列到倒數第二列 X = temp y = np.array(y) # 資料結構轉換 for k in range(epochs): # 抽樣梯度下降epochs抽樣 i = np.random.randint(X.shape[0]) a = [X[i]] # print(self.weights) for l in range(len(self.weights) - 1): b = self.activation(np.dot(a[l], self.weights[l])) b = b.tolist() b.append(1) b = np.array(b) a.append(b) a.append(self.activation(np.dot(a[-1], self.weights[-1]))) # 向前傳播,得到每個節點的輸出結果 error = y[i] - a[-1] # 最後一層錯誤率 deltas = [error * self.activation_deriv(a[-1])] for l in range(len(a) - 2, 0, -1): deltas.append(deltas[-1].dot(self.weights[l].T) * self.activation_deriv(a[l])) deltas.reverse() for i in range(len(self.weights) - 1): layer = np.atleast_2d(a[i]) delta = np.atleast_2d(deltas[i]) delta = delta[:, : -1] self.weights[i] += learning_rate * layer.T.dot(delta) layer = np.atleast_2d(a[-2]) delta = np.atleast_2d(deltas[-1]) # print('w=',self.weights[-1]) # print('l=',layer) # print('d=',delta) self.weights[-1] += learning_rate * layer.T.dot(delta) def predict(self, x): x = np.atleast_2d(x) # atlest_2d函式:確認X至少二位的矩陣 temp = np.ones(x.shape[1] + 1) # 初始化矩陣全是1(行數,列數+1是為了有B這個偏向) temp[:4] = x[0, :] a = temp # print(self.weights) for l in range(len(self.weights) - 1): b = self.activation(np.dot(a, self.weights[l])) b = b.tolist() b.append(1) b = np.array(b) a = b a = self.activation(np.dot(a, self.weights[-1])) return (a)
Text.py
from BPNeuralNetwork import NeuralNetwork import numpy as np from openpyxl import load_workbook import xlrd nn = NeuralNetwork([4, 12, 3], 'tanh') x = np.array([[0, 0], [0, 1], [1, 0], [1, 1]]) y = np.array([0, 1, 1, 0]) import openpyxl # 開啟excel檔案,獲取工作簿物件 data = xlrd.open_workbook('BbezdekIris.xlsx') table = data.sheets()[0] nrows = table.nrows # 行數 ncols = table.ncols # 列數 datamatrix = np.zeros((nrows, ncols - 1)) for k in range(ncols - 1): cols = table.col_values(k) minVals = min(cols) maxVals = max(cols) cols1 = np.matrix(cols) # 把list轉換為矩陣進行矩陣操作 ranges = maxVals - minVals b = cols1 - minVals normcols = b / ranges # 資料進行歸一化處理 datamatrix[:, k] = normcols # 把資料進行儲存 # print(datamatrix) datalabel = table.col_values(ncols - 1) for i in range(nrows): if datalabel[i] == 'Iris-setosa': datalabel[i] = [1, 0, 0] if datalabel[i] == 'Iris-versicolor': datalabel[i] = [0, 1, 0] if datalabel[i] == 'Iris-virginica': datalabel[i] = [0, 0, 1] datamatrix1 = table.col_values(0) for i in range(nrows): datamatrix1[i] = datamatrix[i] x = datamatrix1 y = datalabel nn.fit(x, y) CategorySet = ['Iris-setosa', 'Iris-versicolor', 'Iris-virginica'] P = np.zeros((1, len(y))) P = y a = [0, 1, 3, 5, 4, 7, 8, 1, 5, 1, 5, 5, 1] print(a.index(max(a))) b = nn.predict(x[1]) b = b.tolist() print(b.index(max(b))) for i in range(len(y)): Predict = nn.predict(x[i]) Predict = Predict.tolist() Index = Predict.index(max(Predict, key=abs)) Real = y[i] Category = Real.index(max(Real, key=abs)) if Index == Category: P[i] = 1 print('樣本', i + 1, ':', x[i], ' ', '實際類別', ':', CategorySet[Category], ' ', '預測類別', ':', CategorySet[Index], ' ', '預測正確') else: P[i] = 0 print('樣本', i + 1, ':', x[i], ' ', '實際類別', ':', CategorySet[Category], ' ', '預測類別', ':', CategorySet[Index], ' ', '預測錯誤') print('準確率', ':', sum(P) / len(P))