题目要求
设计一个5层的全连接网络,损失函数自由,激励函数使用sigmoid/tanh/relu,反向传播过程自己写,不能使用pytorch框架的自动求导机制,目标是实现如下函数:
做法和思路
提示:题目需要五个隐藏层,我这里只画了两个。
具体实现
import numpy as np
import matplotlib.pyplot as plt
class LinearLayer: #创建线性层,用于初始化w、b,包括向前传播、向后反馈以及参数更新
def __init__(self, input_D, output_D):
self._W = 0.1*np.random.random(size=(input_D,output_D)) # 初始化不能为全0
self._b = 0.1*np.random.random(size=(1, output_D))
self._grad_W = np.zeros((input_D, output_D))
self._grad_b = np.zeros((1, output_D))
#向前传播函数
def forward(self, X):
return np.matmul(X,self._W) + self._b
#向后反馈函数
def backward(self, X, grad):
self._grad_W = np.matmul(X.T,grad)
self._grad_b = np.matmul(grad.T,np.ones(X.shape[0]))
return np.matmul(grad, self._W.T)
#更新参数
def update(self, learn_rate):
self._W = self._W - self._grad_W * learn_rate
self._b = self._b - self._grad_b * learn_rate
#print("更新后的w值为",self._W.sum())
#print("更新后的b值为",self._b.sum())
#这里激活函数使用的是relu
class Relu:
def __init__(self):
pass
def forward(self, X):
return np.maximum(X,0) #向前传播的时候如果是负数直接输出0
def backward(self, X, grad):
return np.where(X > 0, 1, 0) * grad #向后反馈的时候如果是负数直接输出0,如果是正数则输出1
# 用训练好的模型预测
def train_model():
x = np.arange(-5, 5) #选择了10个数字
y = x ** 2 + 2 * x - 3
train_x = x.reshape(-1, 1)
train_y = y.reshape(-1, 1)
linear1 = LinearLayer(x.shape[0], 10) #初始化一个线性模块,w1=10*10
relu1 = Relu()#初始化一个relu模块
linear2 = LinearLayer(10, 10)#w2=10*10
relu2 = Relu()
linear3 = LinearLayer(10, 10)#w3=10*10
relu3 = Relu()
linear4 = LinearLayer(10, 10)#w4=10*10
relu4 = Relu()
linear5 = LinearLayer(10, x.shape[0])#w5=10*10
for i in range(5000):
# 向前传播
a1 = linear1.forward(train_x.T)
z1 = relu1.forward(a1)
a2 = linear2.forward(z1)
z2 = relu2.forward(a2)
a3 = linear3.forward(z2)
z3 = relu3.forward(a3)
a4 = linear4.forward(z3)
z4 = relu4.forward(a4)
a5 = linear5.forward(z4)
y_predict = a5
# 获得网络输出,计算损失loss
loss = 0.5 * np.square(y_predict - train_y.T)
#print("原始值为",y)
#print("预测值为",y_predict)
# 反向传播
loss = np.array(loss, dtype=float)
grad = y_predict - train_y.T
grad5 = linear5.backward(a5, grad)
grad_5 = relu4.backward(z4, grad5)
grad4 = linear4.backward(a4, grad_5)
grad_4 = relu3.backward(z3, grad4)
grad3 = linear3.backward(a3, grad_4)
grad_3 = relu2.backward(z2, grad3)
grad2 = linear2.backward(a2, grad_3)
grad_2 = relu1.backward(z1, grad2)
grad1 = linear1.backward(a1,grad_2)
learn_rate = 1e-3 # 学习率
# 更新网络中线性层的参数
linear1.update(learn_rate)
linear2.update(learn_rate)
linear3.update(learn_rate)
linear4.update(learn_rate)
linear5.update(learn_rate)
# 判断学习是否完成
#if i % 10 == 0:
print("第",i+1,"轮的loss值为", loss.sum()/x.shape[0])
if loss.sum()/x.shape[0] < 0.1:
print("训练完成!")
plt.scatter(x, y)
plt.scatter(x,y_predict)
plt.show()
break
#开始训练
train_model()
#训练结果:
/homework1.py
第 1 轮的loss值为 40.235068706010225
第 2 轮的loss值为 40.138055377167994
第 3 轮的loss值为 40.03974163695549
第 4 轮的loss值为 39.94001076370604
第 5 轮的loss值为 39.83873486045853
第 6 轮的loss值为 39.73577305941389
第 7 轮的loss值为 39.630969538454785
第 8 轮的loss值为 39.524151314618905
第 9 轮的loss值为 39.415125772214154
第 10 轮的loss值为 39.30367787438628
第 11 轮的loss值为 39.189566995963006
第 12 轮的loss值为 39.072523301748504
第 13 轮的loss值为 38.95224357739768
第 14 轮的loss值为 38.8283863986096
第 15 轮的loss值为 38.700566497386035
第 16 轮的loss值为 38.56834814983919
第 17 轮的loss值为 38.43123736627747
第 18 轮的loss值为 38.28867260806159
第 19 轮的loss值为 38.14001368296304
第 20 轮的loss值为 37.98452837595992
第 21 轮的loss值为 37.8213762480025
第 22 轮的loss值为 37.64958887079093
第 23 轮的loss值为 37.46804554640048
第 24 轮的loss值为 37.27544326606675
第 25 轮的loss值为 37.070259263350906
第 26 轮的loss值为 36.850703971320556
第 27 轮的loss值为 36.614661440682106
第 28 轮的loss值为 36.35961322752179
第 29 轮的loss值为 36.082540285221896
第 30 轮的loss值为 35.7797953018842
第 31 轮的loss值为 35.44693492312758
第 32 轮的loss值为 35.07849695577737
第 33 轮的loss值为 34.66770130574926
第 34 轮的loss值为 34.20604407964796
第 35 轮的loss值为 33.68274051691219
第 36 轮的loss值为 33.0839521311727
第 37 轮的loss值为 32.39170387150165
第 38 轮的loss值为 31.58235537321236
第 39 轮的loss值为 30.624435946533005
第 40 轮的loss值为 29.475596583587013
第 41 轮的loss值为 28.078423968712563
第 42 轮的loss值为 26.355075114325835
第 43 轮的loss值为 24.201669170994265
第 44 轮的loss值为 21.47634621150896
第 45 轮的loss值为 18.033795607834442
第 46 轮的loss值为 13.792630933034133
第 47 轮的loss值为 8.940338612192615
第 48 轮的loss值为 4.29577410325479
第 49 轮的loss值为 1.2521427700100656
第 50 轮的loss值为 0.2527255828622374
第 51 轮的loss值为 0.10303616865388883
第 52 轮的loss值为 0.06051268329541225
训练完成!
Process finished with exit code 0
参考博客的链接:BP算法实现 作者:LifeBackwards
存在的问题
当输入层的个数是10个的时候,必须设置每一层隐藏层神经元的个数也是10个,否则在更新参数时会出现维度不匹配的问题。目前还没有想出很好的解决方案。哪位大佬能教教我,感谢!