问题一: 机器学习的基本流程(16)


让我们将这些值写下来.
e , 1 = e_{\text {, } 1}= ,1?= 链接w 1 , 1 w_{1,1} w1,1? 和链接w 1 , 2 w_{1,2} w1,2? 上的分割误差之和
= e , , ? w 1 , 1 w 1 , 1 + w 2 , 1 + e , 2 ? w 1 , 2 w 1 , 2 + w 2 , 2 =e_{\text {, },} * \frac{w_{1,1}}{w_{1,1}+w_{2,1}}+\quad e_{\text {, } 2} * \frac{w_{1,2}}{w_{1,2}+w_{2,2}} =,,??w1,1?+w2,1?w1,1??+,2??w1,2?+w2,2?w1,2??
这有助于我们看到这个理论的实际作用, 下图详细阐释了在一个简单 的具有实际数字的 3 层网络中, 误差如何向后传播.
让我们演示一下反向传播的误差.你可以观察到,第二个输出层节点 的误差 0.5,在具有权重 1.0 和 4.0 的两个链接之间,根据比例被分割成了 0.1 和 0.4.你也可以观察到,在隐藏层的第二个节点处的重组误差等于连 接的分割误差之和,也就是 0.48 与 0.4 的和,等于 0.88.
如下图所示,我们进一步向后工作,在前一层中应用相同的思路.
关键点
神经网络通过调整链接权重进行学习.这种方法由误差引导,误差就是训练数据所给出正确答案和实际输出之间的差值. 简单地说,在输出节点处的误差等于所需值与实际值之间的差值. 然而,与内部节点相关联的误差并不显而易见.一种方法是按照链接权重的比例来分割输出层的误差,然后在每个内部节点处重组这些误差.
到此为止,已经生动的介绍了神经网络中误差反向传播的BP算法的基本思想,下面结合本人的主要研究方向-‘机器学习求解PDE’,通过框架演示神经网络求解微分方程及数值插值和拟合问题.
数学是这样一步步“沦陷”的
引言
近年来,深度学习由于神经网络强大的表示能力在计算机视觉、语音识别和自然语言处理等方面取得了巨大的成功.利用人工神经网络(ANN)进行数值计算来解决各种数学问题引起了大家的广泛研究.例如:
一、插值
问题描述
在函数 f ( x ) = s i n ( x ) ? 0.5 f(x)=sin(x)-0.5 f(x)=sin(x)?0.5, x ∈ ( ? 2 π , 2 π ) x\in(-2\pi,2\pi) x∈(?2π,2π)上均匀采样20个点作为插值点,使用 ANN 进行插值的数值计算结果如下:
程序源代码
# 开发者:Leo 刘# 开发环境: macOs Big Sur# 开发时间: 2021/8/1 11:43 上午# 邮箱: 517093978@qq.com# @Software: PyCharmimport torchimport torch.nn as nnimport numpy as npimport matplotlib.pyplot as pltfrom Dynamic_drawing import image2gif# 构建输入集x_data = http://www.kingceram.com/post/np.linspace(-2 * np.pi, 2 * np.pi, 300)[:, np.newaxis]x_data = torch.tensor(x_data).float()y_data = np.sin(x_data) - 0.5# y_data = np.sin(x_data)*x_data**2 - 0.5y_data = torch.tensor(y_data).float()# 定义神经网络class Net(torch.nn.Module):# 初始化数组,参数分别是初始化信息,特征数,隐藏单元数,输出单元数def __init__(self, n_feature, n_hidden, n_output):# 此步骤是官方要求super(Net, self).__init__()# 设置输入层到隐藏层的函数self.input = torch.nn.Linear(n_feature, n_hidden)# 设置隐藏层到隐藏层的函数self.hidden = torch.nn.Linear(n_hidden, n_hidden)# 设置隐藏层到输出层的函数self.predict = torch.nn.Linear(n_hidden, n_output)# 定义向前传播函数def forward(self, input):# 给x加权成为a,用激活函数将a变成特征b# input = torch.relu(self.hidden(input))# 线性插值input = torch.tanh(self.input(input))# 非线性插值# 给a加权成为b,用激活函数将b变成特征cinput = torch.tanh(self.hidden(input))# 给c加权,预测最终结果input = self.predict(input)return inputdef interpolation_node(x_inter_data, y_inter_data, N):data_size, w = x_data.size()b = np.array(range(N))a = 1 + data_size / N * bx_inter_node = x_inter_data[a]y_inter_node = y_inter_data[a]return x_inter_node, y_inter_node# 初始化网络print('神经网络结构:')myNet = Net(1, 10, 1)print(myNet)# 设置优化器# optimizer = torch.optim.SGD(myNet.parameters(), lr=0.05)optimizer = torch.optim.Adam(myNet.parameters(), lr=0.05)loss_func = nn.MSELoss()best_loss, best_epoch = 1000, 0epochs = 2000# 训练次数x_inter_node, y_inter_node = interpolation_node(x_data,y_data, 20)# 获取插值节点input = x_inter_nodelabel = y_inter_nodeLoss_list = []print('开始学习:')for epoch in range(epochs + 1):output = myNet(input)loss = loss_func(output, label)# 计算误差Loss_list.append(loss / (len(x_data)))optimizer.zero_grad()# 清除梯度loss.backward()# 误差反向传播optimizer.step()# 梯度更新torch.save(myNet.state_dict(), 'new_best_interpolation.mdl')# 记录误差if epoch % 100 == 0:print('epoch:', epoch, 'loss:', loss.item(), )# 记录最佳训练次数if epoch> int(4 * epochs / 5):if torch.abs(loss)