BP神经网络Python

    xiaoxiao2025-02-16  19

      参考这篇博客 BP神经网络:计算原理详解和MATLAB实现 用Python写了一个对二维坐标点二分类的代码。gif图如下,显示对应迭代次数对坐标点的分类情况


    具体实现代码如下:

    # -*- coding:utf-8 -*- import numpy as np from math import e, pow, fabs import matplotlib.pyplot as plt import copy class ANN: def __init__(self, layer_sizes, lr=0.05, epoch=100, batch_size=8): self.lr = lr self.epoch = epoch self.batch_size = batch_size self.weights = [np.random.randn(x, y) for x, y in zip(layer_sizes[:-1], layer_sizes[1:])] self.ys = [np.random.randn(x) for x in layer_sizes[1:]] self.deltas = [np.random.randn(x) for x in layer_sizes[1:]] def foreward(self): # 计算与输入层连接的隐层 for i in range(np.shape(self.ys[0])[0]): self.ys[0][i] = self.func(np.sum(self.weights[0][j, i] * self.inputs[j] for j in range(len(self.inputs)))) for i in range(1, len(self.ys)): for j in range(np.shape(self.ys[i])[0]): self.ys[i][j] = self.func( np.sum(self.weights[i][k, j] * self.ys[i - 1][k] for k in range(np.shape(self.ys[i - 1])[0]))) def back_propagation(self): self.deltas[-1][0] = self.label - self.ys[-1][0] for i in reversed(range(0, len(self.deltas) - 1)): for j in range(np.shape(self.deltas[i])[0]): self.deltas[i][j] = np.sum( [self.weights[i + 1][j, k] * self.deltas[i + 1][k] for k in range(np.shape(self.deltas[i + 1])[0])]) def weight_update(self): # 更新第一层 for i in range(np.shape(self.weights[0])[0]): for j in range(np.shape(self.weights[0])[1]): self.weights[0][i, j] += self.lr * self.deltas[0][j] * self.func_derivative( self.inputs[i]) * self.inputs[i] for i in range(1, len(self.weights)): for j in range(np.shape(self.weights[i])[0]): for k in range(np.shape(self.weights[i])[1]): self.weights[i][j, k] += self.lr * self.deltas[i][k] * self.func_derivative(self.ys[i][k]) * \ self.ys[i - 1][j] def func(self, x): """ 使用的函数 :param x: :return: """ return 1.0 / (1 + pow(e, 0 - x)) def func_derivative(self, x): """ 函数的导数 :param x: :return: """ return pow(e, 0 - x) * 1.0 / (1 + pow(e, 0 - x)) def train(self, train_x, train_y): # 归一化输入 max_x = np.asarray(train_x).max(axis=1).max() min_x = np.asarray(train_x).min(axis=1).min() for i in range(len(train_x)): for j in range(len(train_x[i])): train_x[i][j] = (train_x[i][j] - min_x) * 1.0 / (0.5 * (max_x - min_x)) + (-1) def scaler(in_x): return (in_x - min_x) * 1.0 / (0.5 * (max_x - min_x)) + (-1) for i in range(self.epoch): print('epoch#{}'.format(i + 1)) rand_index = np.random.choice(len(train_x), self.batch_size) for ind in rand_index: self.inputs = train_x[ind] self.label = train_y[ind] # 前向传递,反向传播 self.foreward() self.back_propagation() self.weight_update() # 验证 if i % 5 == 0: for j, test_x in enumerate(train_x): self.predict(test_x, train_y[j]) return scaler def predict(self, test_x, ans): self.inputs = test_x self.foreward() return self.ys[-1][0] def draw_split_line(scaler, xs, ys, ann: ANN, save_name): plt.figure() x_vals = np.asarray(xs)[:, 0] y_vals = np.asarray(xs)[:, 1] for i in range(np.shape(x_vals)[0]): plt.plot(x_vals[i], y_vals[i], 'b+' if ys[i] == 0 else 'rx') x_vals = np.linspace(-2, 2, num=100) y_vals = np.linspace(-2, 2, num=100) xv, yv = np.meshgrid(x_vals, y_vals) z_vals = [] for dt in np.asarray([dot for dot in zip(xv.flat, yv.flat)]): z_vals.append(ann.predict([scaler(dt[0]), scaler(dt[1])], -1)) # ans未使用 z_vals = np.asarray(z_vals).reshape(np.shape(xv)) plt.contourf(xv, yv, z_vals, 1, cmap='jet', alpha=0.2) plt.title('epoch={}'.format(save_name.split('_')[1])) plt.savefig(save_name + '.jpg') plt.close() if __name__ == '__main__': train_x = [[0, 0], [1, 0], [1, 1], [0, 2], [2, 2], [0, 0.5], [0.5, 0.5], [0.5, -1.5], [0, -2], [0, -1], [-0.5, -1.5], [-1, -1], [-0.5, 0], [-1, 1]] train_y = [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0] for i in range(10, 101, 10): ann = ANN([2, 50, 1], epoch=i) scaler = ann.train(copy.deepcopy(train_x), copy.deepcopy(train_y)) draw_split_line(scaler, train_x, train_y, ann, 'epoch_{}'.format(i))
    最新回复(0)