这次把代码封装了下,并加上了一些注释
import numpy as np
class BP:
def __init__(self, w, b, x, y, lr):
self.__w = w # 参数θ
self.__b = b # 偏置项
self.__x = x # 特征向量
self.__y = y # label标签
self.__lr = lr # 学习率
def w(self, index):
return self.__w[index - 1]
def set_w(self, index, gd):
self.__w[index - 1] = self.__w[index - 1] - self.__lr * gd
def get_w(self):
return self.__w
def b(self, index):
return self.__b[index - 1]
def get_b(self):
return self.__b
def set_b(self, index, gd):
self.__b[index - 1] = self.__b[index - 1] - self.__lr * gd
def x(self, index):
return self.__x[index - 1]
def y(self, index):
return self.__y[index - 1]
def sigmoid(self, z):
return 1.0 / (1 + np.exp(-z))
def training(self):
# 1. FP前向过程 计算损失
h1 = self.sigmoid(self.w(1) * self.x(1) + self.w(2) * self.x(2) + self.b(1))
h2 = self.sigmoid(self.w(3) * self.x(1) + self.w(4) * self.x(2) + self.b(1))
h3 = self.sigmoid(self.w(5) * self.x(1) + self.w(6) * self.x(2) + self.b(1))
o1 = self.sigmoid(self.w(7) * h1 + self.w(9) * h2 + self.w(11) * h3 + self.b(2))
o2 = self.sigmoid(self.w(8) * h1 + self.w(10) * h2 + self.w(12) * h3 + self.b(2))
loss = 0.5 * (self.y(1) - o1) ** 2 + 0.5 * (self.y(2) - o2) ** 2
# print(h1, h2, h3)
# 2. BP反向过程 参数更新
# 基于求导的链式法则进行loss对w1的梯度求解
# 梯度的简化写法:loss/w1 = loss/h1 * h1/ w1 = (loss/o1*o1/h1 + loss/o2*o2/h1) * h1/w1
# loss / w2 = loss / h1 * h1 / w2 = (loss / o1 * o1 / h1 + loss / o2 * o2 / h1) * h1 / w2
# loss / w3 = loss / h2 * h2 / w3 = (loss / o1 * o1 / h2 + loss / o2 * o2 / h2) * h2 / w3
t1 = (o1 - self.y(1)) * o1 * (1 - o1) # loss对net_o1的导数
t2 = (o2 - self.y(2)) * o2 * (1 - o2)
self.set_w(7, t1 * h1)
self.set_w(8, t2 * h1)
self.set_w(9, t1 * h2)
self.set_w(10, t2 * h2)
self.set_w(11, t1 * h3)
self.set_w(12, t2 * h3)
self.set_w(1, (t1 * self.w(7) + t2 * self.w(8)) * h1 * (1 - h1) * self.x(1))
self.set_w(2, (t1 * self.w(7) + t2 * self.w(8)) * h1 * (1 - h1) * self.x(2))
self.set_w(3, (t1 * self.w(9) + t2 * self.w(10)) * h2 * (1 - h2) * self.x(1))
self.set_w(4, (t1 * self.w(9) + t2 * self.w(10)) * h2 * (1 - h2) * self.x(2))
self.set_w(5, (t1 * self.w(11) + t2 * self.w(12)) * h3 * (1 - h3) * self.x(1))
self.set_w(6, (t1 * self.w(11) + t2 * self.w(12)) * h3 * (1 - h3) * self.x(2))
# 更新b:
self.set_b(1,
t1 * self.w(7) * h1 * (1 - h1) + t1 * self.w(9) * h2 * (1 - h2) + t1 * self.w(11) * h3 * (1 - h3) +
t2 * self.w(8) * h1 * (1 - h1) + t2 * self.w(10) * h2 * (1 - h2) + t2 * self.w(12) * h3 * (1 - h3))
self.set_b(2, t1 + t2)
return loss, o1, o2
if __name__ == '__main__':
_w = [0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65]
_b = [0.35, 0.65]
_x = [5.0, 10.0]
_y = [0.3, 0.8]
_lr = 0.5
print("demo")
bp = BP(_w, _b, _x, _y, _lr)
for i in range(1000):
_loss = bp.training()
print(_loss)
print(bp.get_w())
print(bp.get_b())