深度学习笔记1:神经网络与模型训练过程
参考博客:PyTorch深度学习实战(1)——神经网络与模型训练过程详解_pytorch 实战-CSDN博客
人工神经网络
ANN:张量及数学运算的集合,排列方式近似于松散的人脑神经元排列
组成
1)输入层
2)隐藏层(中间层):连接输入层和输出层,在输入数据上执行转换,此外隐藏层利用神经元将输入值修改为更高、更低维的值,通过修改中间结点的激活函数可以实现复杂表示函数
3)输出层
训练
本质就是通过重复前向传播和后向传播两个关键步骤来调整神经网络的参数
前向传播--》输入经过隐藏层的到输出结果,第一次正向传播 权重初始化 计算预测值
后向传播--》根据误差相应调整权重来减小误差 修正参数
神经网络重复正向传播与反向传播以预测输出,指导获得令误差较小的权重为止
前向传播
1)输入值乘以权重计算隐藏层值
2)计算激活值
3)在每个神经元上重复前两个步骤,直到输出层
4)计算loss
封装为函数
def forward(inputs,outputs,weights):#如果是首次迭代,随机初始化
pre_hidden = np.dot(inputs,weights[0]) + weights[1]#向量点积
hidden = 1/(1+np.exp(-pre_hidden))#sigmoid激活函数
pred_out = np.dot(hidden,weights[2]) + weights[3]#计算输出
mse = np.mean(np.square(pred_out - outputs))#loss
return mse
反向传播
与前向传播相反,利用从前向传播中计算的损失值,以最小化损失值为目标更新网络权重
1)每次对神经网络中的每个权重进行少量修改
2)测量权重变化时的损失变化 ---》损失值关于权重的梯度
3)计算-α δL/δW 更新权重 α为学习率
如果改变权重损失变化大那么就大幅更新权重
否则 小幅跟新权重
在整个数据集上执行n次前向传播以及后向传播,表示模型进行了n个epoch的训练 ,执行一次算一个epoch
学习率
有助于构建更稳定的算法
梯度下降
更新权重以减小误差值的整个过程
SGD是将误差最小化的一种方法:随计算则数据中的训练数据样本,并根据该样本做出决策
实现梯度下降算法
1)定义前馈神经网络并计算均方误差值
2)为每个权重和偏执项增加一个非常小的量0.001,并针对每个权重和偏差的更新计算一个mse
from copy import deepcopy
import numpy as np
#创建update_weights函数,执行梯度下降来更新权重
def update_weights(inputs, outputs, weights, lr):
#使用deepcopy可以确保处理多个权重副本,不会影响实际权重
original_weights = deepcopy(weights)
temp_weights = deepcopy(weights)
updated_weights = deepcopy(weights)
original_loss = forward(inputs, outputs, original_weigts)
#遍历网络的所有层
for i, layer in enumerate(orignial_weights):
#循环遍历每个参数列表的所有参数 共四个参数列表,前两个表示输入连接到隐藏层的权重和偏置项参数
#另外两个表示链接隐藏层和输出层的偏置参数
for index, weight in np.ndenumerate(layer):
temp_weights = deepcopy(weights)#原始权重集
temp_weights[i][index] += 0.0001#增加很小的值权重更新
_loss_plus = forward(inputs, outputs, temp_weights)#更新损失
grad = (_loss_plus - original_loss)/0.0001
updated_weights[i][index] -= grad * lr #利用损失变化更新权重,使用学习率领权重变化更稳定
return updated_weights, original_loss#返回更新后的权重
合并前向传播和反向传播
构建一个带有隐藏层的简单神经网络,
1)输入连接到具有三个神经元的隐藏层
2)隐藏层连接到具有一个神经元的输出层
#导入相关库
import numpy as np
import matplotlib.pyplot as plt
from copy import deepcopy
x = np.array([[1,1]])
y = np.array(([[0]]))
#随机初始化权重和偏置值
W = [
np.array([[-0.05, 0.3793],
[-0.5820, -0.5204],
[-0.2723, 0.1896]], dtype=np.float32).T,
np.array([-0.0140, 0.5607, -0.0628], dtype=np.float32), #隐藏层两个偏置值
np.array([[ 0.1528, -0.1745, -0.1135]], dtype=np.float32).T,
np.array([-0.5516], dtype=np.float32)#输出层一个偏置值
]
#在一百个epoch内执行前向传播和反向传播,使用之前定义的forward和
def forward(inputs,outputs,weights):#如果是首次迭代,随机初始化
pre_hidden = np.dot(inputs,weights[0]) + weights[1]#向量点积
hidden = 1/(1+np.exp(-pre_hidden))#sigmoid激活函数
pred_out = np.dot(hidden,weights[2]) + weights[3]#计算输出
mse = np.mean(np.square(pred_out - outputs))#loss
return mse
def update_weights(inputs, outputs, weights, lr):
#使用deepcopy可以确保处理多个权重副本,不会影响实际权重
original_weights = deepcopy(weights)
temp_weights = deepcopy(weights)
updated_weights = deepcopy(weights)
original_loss = forward(inputs, outputs, original_weights)
#遍历网络的所有层
for i, layer in enumerate(original_weights):
#循环遍历每个参数列表的所有参数 共四个参数列表,前两个表示输入连接到隐藏层的权重和偏置项参数
#另外两个表示链接隐藏层和输出层的偏置参数
for index, weight in np.ndenumerate(layer):
temp_weights = deepcopy(weights)#原始权重集
temp_weights[i][index] += 0.0001#增加很小的值权重更新
_loss_plus = forward(inputs, outputs, temp_weights)#更新损失
grad = (_loss_plus - original_loss)/0.0001
updated_weights[i][index] -= grad * lr #利用损失变化更新权重,使用学习率领权重变化更稳定
return updated_weights, original_loss#返回更新后的权重
#绘制损失值
losses = []
for epoch in range(100):
W, loss = update_weights(x, y, W, 0.01)
losses.append(loss)
plt.plot(losses)
plt.title('loss over increasing number of epochs')
plt.xlabel('epochs')
plt.ylabel('loss value')
plt.show()
print(W)
#获取更新后的权值之后通过将输出传递给网络对输入进行预测计算输出值
pre_hidden = np.dot(x, W[0]) + W[1]
hidden = 1/(1+np.exp(-pre_hidden))
pre_out = np.dot(hidden, W[2]) + W[3]
print(pre_out)
注:在服务器上运行时im.show()无法展示图片
总结
训练神经网络主要是通过重复两个关键步骤,及用给定的学习率进行前向传播和反向传播,最终得到最佳权重