chap4 simple neural network

全连接神经网络

问题描述

利用numpypytorch搭建全连接神经网络。使用numpy实现此练习需要自己手动求导,而pytorch具有自动求导机制。

我们首先先手动算一下反向传播的过程,使用的模型和初始化权重、偏差和训练用的输入和输出值如下:
在这里插入图片描述
我们看一下正向过程:计算出每个隐藏神经元的输入,通过激活函数(用Sigmoid函数)转换为下一层的输入,直到达到输出层计算最终输出:
先来计算隐藏层h_1的输入,
z h 1 = ω 1 x 1 + ω 2 x 2 + 1 = 1 ∗ 1 + ( − 2 ) ∗ ( − 1 ) + 1 = 4 z_{h_1}=\omega_1 x_1+\omega_2 x_2 + 1=1*1+(-2)*(-1)+1=4 zh1=ω1x1+ω2x2+1=11+(2)(1)+1=4
然后用激活函数激活,得到 h 1 h_1 h1的输出
a h 1 = σ ( z h 1 ) = 1 1 + e − z h 1 = 1 1 + e − 4 = 0.98201379 a_{h_1}=\sigma(z_{h_1})=\frac{1}{1+e^{-z_{h_1}}}=\frac{1}{1+e^{-4}}=0.98201379 ah1=σ(zh1)=1+ezh11=1+e41=0.98201379
同理有
z h 2 = ω 3 x 1 + ω 4 x 2 + 1 = − 1 ∗ 1 + 1 ∗ ( − 1 ) + 1 = − 1 z_{h_2}=\omega_3 x_1+\omega_4 x_2 + 1=-1*1+1*(-1)+1=-1 zh2=ω3x1+ω4x2+1=11+1(1)+1=1
可得 a h 2 = σ ( z h 2 ) = 0.26894142 a_{h_2}=\sigma(z_{h_2})=0.26894142 ah2=σ(zh2)=0.26894142
这两个输出作为下一层的输入,接下来计算输出层 o 1 o_1 o1
z o 1 = ω 5 ∗ a h 1 + ω 6 ∗ a h 2 + 1 = 2 ∗ 0.98201379 + ( − 2 ) ∗ 0.26894142 + 1 = 2.42614474 z_{o_1}=\omega_5*a_{h_1}+\omega_6*a_{h_2}+1=2*0.98201379+(-2)*0.26894142+1=2.42614474 zo1=ω5ah1+ω6ah2+1=20.98201379+(2)0.26894142+1=2.42614474
a o 1 = σ ( z o 1 ) = 1 1 + e − z o 1 = 1 1 + e − 2.42614474 = 0.91879937 a_{o_1}=\sigma(z_{o_1})=\frac{1}{1+e^{-z_{o_1}}}=\frac{1}{1+e^{-2.42614474}}=0.91879937 ao1=σ(zo1)=1+ezo11=1+e2.426144741=0.91879937
同理,得到输出层 o 2 o_2 o2的输出
z o 2 = ω 7 ∗ a h 1 + ω 8 ∗ a h 2 + 1 = − 2 ∗ 0.98201379 + ( − 1 ) ∗ 0.26894142 + 1 = − 1.23296900 z_{o_2}=\omega_7*a_{h_1}+\omega_8*a_{h_2}+1=-2*0.98201379+(-1)*0.26894142+1=-1.23296900 zo2=ω7ah1+ω8ah2+1=20.98201379+(1)0.26894142+1=1.23296900
a o 2 = σ ( z o 2 ) = 1 1 + e − z o 2 = 1 1 + e − 1.23296900 = 0.22566220 a_{o_2}=\sigma(z_{o_2})=\frac{1}{1+e^{-z_{o_2}}}=\frac{1}{1+e^{-1.23296900}}=0.22566220 ao2=σ(zo2)=1+ezo21=1+e1.232969001=0.22566220
可以看到,初始参数上的输出和目标值0.010.99有不小的距离,下面计算一下总误差

使用均方误差来计算总误差:
E total  = 1 2 ∑ ( y ^ − y ) 2 E_{\text {total }}=\frac{1}{2} \sum(\hat{y}-y)^2 Etotal =21(y^y)2
其中 y y y是输出层的实际输出, y ^ \hat y y^是期望输出,比如对于 o 1 o_1 o1神经元,有误差:
E o 1 = 1 2 ( y o 1 ^ − y o 1 ) 2 = 1 2 ( 0.01 − 0.91879937 ) 2 = 0.41295815 E_{o_1}=\frac{1}{2}\left(\hat{y_{o_1}}-y_{o_1}\right)^2=\frac{1}{2}(0.01-0.91879937)^2=0.41295815 Eo1=21(yo1^yo1)2=21(0.010.91879937)2=0.41295815
同理,计算出 E o 2 = 0.29210614 E_{o_2}=0.29210614 Eo2=0.29210614
总误差即为 E total  = E o 1 + E o 2 = 0.41295815 + 0.29210614 = 0.70506429 E_{\text {total }}=E_{o_1}+E_{o_2}=0.41295815+0.29210614=0.70506429 Etotal =Eo1+Eo2=0.41295815+0.29210614=0.70506429

然后进行反向过程,反向传播算法的目的是更高效的计算梯度,从而更新参数值,使得总误差更小,也就是使实际输出更贴近我们期望输出。它是作为一个整体去更新整个神经网络的,反向就是先考虑输出层,然后再考虑上一层,直到输入层。
首先计算输出层:
考虑参数 ω 5 \omega_5 ω5,计算 ω 5 \omega_5 ω5的改变会对总误差有多大的影响,即计算 ∂ E t o t a l ∂ ω 5 \frac{\partial E_{total}}{\partial \omega_5} ω5Etotal,由链式法则有 ∂ E t o t a l ∂ ω 5 = ∂ E t o t a l ∂ a o 1 ∂ a o 1 ∂ z o 1 ∂ z o 1 ∂ ω 5 \frac{\partial E_{total}}{\partial \omega_5}=\frac{\partial E_{total}}{\partial a_{o_1}}\frac{\partial a_{o_1}}{\partial z_{o_1}}\frac{\partial z_{o_1}}{\partial \omega_5} ω5Etotal=ao1Etotalzo1ao1ω5zo1
要计算这个等式中的每个式子,首先计算 a o 1 a_{o_1} ao1如何影响总误差
E total  = 1 2 ∑ ( target  o 1 − a o 1 ) 2 + 1 2 ( target  o 2 − a o 2 ) 2 ∂ E total  ∂ a o 1 = 2 ∗ 1 2 ( target  o 1 − a o 1 ) ∗ ( − 1 ) + 0 = − ( target  o 1 − a o 1 ) = − ( 0.01 − 0.91879937 ) = 0.90879937 \begin{aligned} & E_{\text {total }}=\frac{1}{2} \sum\left(\text { target }_{o_1-a_{o_1}}\right)^2+\frac{1}{2}\left(\text { target }_{o_2}-a_{o_2}\right)^2 \\ & \frac{\partial E_{\text {total }}}{\partial a_{o_1}}=2 * \frac{1}{2}\left(\text { target }_{o_1-a_{o_1}}\right) *(-1)+0=-\left(\text { target }_{o_1}-a_{o_1}\right)=-(0.01-0.91879937)=0.90879937 \end{aligned} Etotal =21( target o1ao1)2+21( target o2ao2)2ao1Etotal =221( target o1ao1)(1)+0=( target o1ao1)=(0.010.91879937)=0.90879937

接下来计算 ∂ a o 1 ∂ z o 1 \frac{\partial a_{o_1}}{\partial z_{o_1}} zo1ao1
我们知道 σ ′ ( z ) = σ ( z ) ( 1 − σ ( z ) ) \sigma'(z)=\sigma(z)(1-\sigma(z)) σ(z)=σ(z)(1σ(z))(对sigmoid函数求导证明)
所以 所以  ∂ a o 1 ∂ z o 1 = a o 1 ( 1 − a o 1 ) = 0.91879937 ( 1 − 0.91879937 ) = 0.07460709 \text { 所以 } \frac{\partial a_{o_1}}{\partial z_{o_1}}=a_{o_1}\left(1-a_{o_1}\right)=0.91879937(1-0.91879937)=0.07460709  所以 zo1ao1=ao1(1ao1)=0.91879937(10.91879937)=0.07460709
最后是 ∂ z o 1 ∂ ω 5 \frac{\partial z_{o_1}}{\partial \omega_5} ω5zo1
z o 1 = ω 5 ∗ a h 1 + ω 6 ∗ a h 2 + b z_o1=\omega_5 * a_{h_1}+\omega_6 * a_{h_2}+b zo1=ω5ah1+ω6ah2+b
∂ z o 1 ∂ ω 5 = a h 1 = 0.98201379 \frac{\partial z_{o_1}}{\partial \omega_5}=a_{h_1}=0.98201379 ω5zo1=ah1=0.98201379
最后放到一起得到:
∂ E t o t a l ∂ ω 5 = ∂ E t o t a l ∂ a o 1 ∂ a o 1 ∂ z o 1 ∂ z o 1 ∂ ω 5 = 0.90879937 ∗ 0.07460709 ∗ 0.98201379 = 0.06658336 \frac{\partial E_{total}}{\partial \omega_5}=\frac{\partial E_{total}}{\partial a_{o_1}}\frac{\partial a_{o_1}}{\partial z_{o_1}}\frac{\partial z_{o_1}}{\partial \omega_5}=0.90879937*0.07460709*0.98201379=0.06658336 ω5Etotal=ao1Etotalzo1ao1ω5zo1=0.908799370.074607090.98201379=0.06658336
通常一般定义 δ o 1 = ∂ E t o t a l ∂ a o 1 ∂ a o 1 ∂ z o 1 = ∂ E t o t a l ∂ z o 1 \delta_{o_1}=\frac{\partial E_{total}}{\partial a_{o_1}}\frac{\partial a_{o_1}}{\partial z_{o_1}}=\frac{\partial E_{total}}{\partial z_{o_1}} δo1=ao1Etotalzo1ao1=zo1Etotal
因此, ∂ E t o t a l ∂ ω 5 = δ o 1 a h 1 \frac{\partial E_{total}}{\partial \omega_5}=\delta_{o_1}a_{h_1} ω5Etotal=δo1ah1
为了减小误差,通常需要更新当前权重,如下:
ω 5 = ω 5 − α ∗ ∂ E t o t a l ∂ ω 5 = 2 − 0.5 ∗ 0.06658336 = 1.96670832 \omega_5 = \omega_5 - \alpha * \frac{\partial E_{total}}{\partial \omega_5}=2-0.5*0.06658336=1.96670832 ω5=ω5αω5Etotal=20.50.06658336=1.96670832
同理可以算出其他权重 ω 6 = − 2.00911750 \omega_6=-2.00911750 ω6=2.00911750 ω 7 = − 1.93442139 \omega_7=-1.93442139 ω7=1.93442139 ω 8 = − 0.98204017 \omega_8=-0.98204017 ω8=0.98204017
这是输出层的所有参数,接下来需要往前推,更新隐藏层的参数。
首先来更新 ω 1 \omega_1 ω1:
∂ E t o t a l ∂ ω 1 = ∂ E t o t a l ∂ a h 1 ∂ a h 1 ∂ z h 1 ∂ z h 1 ∂ ω 1 \frac{\partial E_{total}}{\partial \omega_1}=\frac{\partial E_{total}}{\partial a_{h_1}}\frac{\partial a_{h_1}}{\partial z_{h_1}}\frac{\partial z_{h_1}}{\partial \omega_1} ω1Etotal=ah1Etotalzh1ah1ω1zh1
要用和更新输出层参数类似的步骤来更新隐藏层的参数,但是不同的是,每个隐藏层的神经元都影响了多个输出层(或下一层)神经元的输出, a h 1 a_{h_1} ah1同时影响了 a o 1 a_{o_1} ao1 a o 2 a_{o_2} ao2,因此计算 ∂ E t o t a l ∂ a h 1 \frac{\partial E_{total}}{\partial a_{h_1}} ah1Etotal需要将输出层的两个神经元都考虑在内:
∂ E t o t a l ∂ a h 1 = ∂ E o 1 ∂ a h 1 + ∂ E o 2 ∂ a h 1 \frac{\partial E_{total}}{\partial a_{h_1}}=\frac{\partial E_{o_1}}{\partial a_{h_1}}+\frac{\partial E_{o_2}}{\partial a_{h_1}} ah1Etotal=ah1Eo1+ah1Eo2,从 ∂ E o 1 ∂ a h 1 \frac{\partial E_{o_1}}{\partial a_{h_1}} ah1Eo1开始,有:
∂ E o 1 ∂ a h 1 = ∂ E o 1 ∂ z o 1 ∗ ∂ z o 1 ∂ a h 1 \frac{\partial E_{o_1}}{\partial a_{h_1}}=\frac{\partial E_{o_1}}{\partial z_{o_1}}* \frac{\partial z_{o_1}}{\partial a_{h_1}} ah1Eo1=zo1Eo1ah1zo1
上面已经算过 ∂ E o 1 ∂ z o 1 = 0.06780288 \frac{\partial E_{o_1}}{\partial z_{o_1}}=0.06780288 zo1Eo1=0.06780288了(实际上就是 ∂ E t o t a l ∂ z o 1 \frac{\partial E_{total}}{\partial z_{o_1}} zo1Etotal,因为 E t o t a l E_{total} Etotal只有 E o 1 E_{o_1} Eo1这一项对 z o 1 z_{o_1} zo1求导不为0),而且 ∂ z o 1 ∂ a h 1 = ω 5 = 2 \frac{\partial z_{o_1}}{\partial a_{h_1}}=\omega_5=2 ah1zo1=ω5=2,所以有 ∂ E o 1 ∂ a h 1 = 0.06780288 ∗ 2 = 0.13560576 \frac{\partial E_{o_1}}{\partial a_{h_1}}=0.06780288*2=0.13560576 ah1Eo1=0.067802882=0.13560576
同理,可得 ∂ E o 2 ∂ a h 1 = − 0.13355945 ∗ ( − 2 ) = 0.26711890 \frac{\partial E_{o_2}}{\partial a_{h_1}}=-0.13355945*(-2)=0.26711890 ah1Eo2=0.13355945(2)=0.26711890
因此:
∂ E t o t a l ∂ a h 1 = ∂ E o 1 ∂ a h 1 + ∂ E o 2 ∂ a h 1 = 0.13560576 + 0.26711890 = 0.40272466 \frac{\partial E_{total}}{\partial a_{h_1}}=\frac{\partial E_{o_1}}{\partial a_{h_1}}+\frac{\partial E_{o_2}}{\partial a_{h_1}}=0.13560576+0.26711890=0.40272466 ah1Etotal=ah1Eo1+ah1Eo2=0.13560576+0.26711890=0.40272466
现在已经知道了 ∂ E t o t a l ∂ a h 1 \frac{\partial E_{total}}{\partial a_{h_1}} ah1Etotal,还需要计算 ∂ a h 1 ∂ z h 1 \frac{\partial a_{h_1}}{\partial z_{h_1}} zh1ah1 ∂ z h 1 ∂ ω 1 \frac{\partial z_{h_1}}{\partial \omega_1} ω1zh1
a h 1 = σ ( z h 1 ) = 1 1 + e − z h 1 = 1 1 + e − 4 = 0.98201379 a_{h_1}=\sigma(z_{h_1})=\frac{1}{1+e^{-z_{h_1}}}=\frac{1}{1+e^{-4}}=0.98201379 ah1=σ(zh1)=1+ezh11=1+e41=0.98201379
∂ a h 1 ∂ z h 1 = a h 1 ( 1 − a h 1 ) = 0.98201379 ( 1 − 0.98201379 ) = 0.01766271 \frac{\partial a_{h_1}}{\partial z_{h_1}}=a_{h_1}(1-a_{h_1})=0.98201379(1-0.98201379)=0.01766271 zh1ah1=ah1(1ah1)=0.98201379(10.98201379)=0.01766271
z h 1 = ω 1 x 1 + ω 2 x 2 + b z_{h_1}=\omega_1 x_1+\omega_2 x_2 + b zh1=ω1x1+ω2x2+b
∂ z h 1 ∂ ω 1 = x 1 = 1 \frac{\partial z_{h_1}}{\partial \omega_1}=x_1=1 ω1zh1=x1=1
最后,总式子就可以计算了:
∂ E t o t a l ∂ ω 1 = ∂ E t o t a l ∂ a h 1 ∂ a h 1 ∂ z h 1 ∂ z h 1 ∂ ω 1 = 0.40272466 ∗ 0.01766271 ∗ 1 = 0.00711321 \frac{\partial E_{total}}{\partial \omega_1}=\frac{\partial E_{total}}{\partial a_{h_1}}\frac{\partial a_{h_1}}{\partial z_{h_1}}\frac{\partial z_{h_1}}{\partial \omega_1}=0.40272466*0.01766271*1=0.00711321 ω1Etotal=ah1Etotalzh1ah1ω1zh1=0.402724660.017662711=0.00711321
接下来就可以更新 ω 1 \omega_1 ω1
ω 1 = ω 1 − α ∗ E t o t a l ∂ ω 1 = 0.99644340 \omega_1=\omega_1 - \alpha * \frac{E_{total}}{\partial \omega_1}=0.99644340 ω1=ω1αω1Etotal=0.99644340
同理可以得到: ω 2 = − 1.99644340 \omega_2=-1.99644340 ω2=1.99644340 ω 3 = − 0.99979884 \omega_3=-0.99979884 ω3=0.99979884 ω 4 = 0.99979884 \omega_4=0.99979884 ω4=0.99979884
在执行10000此更新权重的过程后,误差变成了0.000,输出是0.011851540581436764和0.9878060737917571,这和期望输出0.01和0.99十分接近了。

使用numpy来练习上述过程:

import numpy as npclass Network():def __init__(self, **kwargs):self.w1, self.w2, self.w3, self.w4 = kwargs['w1'], kwargs['w2'], kwargs['w3'], kwargs['w4']self.w5, self.w6, self.w7, self.w8 = kwargs['w5'], kwargs['w6'], kwargs['w7'], kwargs['w8']self.d_w1, self.d_w2, self.d_w3, self.d_w4 = 0.0, 0.0, 0.0, 0.0self.d_w5, self.d_w6, self.d_w7, self.d_w8 = 0.0, 0.0, 0.0, 0.0self.x1 = kwargs['x1']self.x2 = kwargs['x2']self.y1 = kwargs['y1']self.y2 = kwargs['y2']self.learning_rate = kwargs['learning_rate']def sigmoid(self, z):a = 1 / (1 + np.exp(-z))return adef forward_propagate(self):loss = 0.0b = 1in_h1 = self.w1 * self.x1 + self.w2 * self.x2 + bout_h1 = self.sigmoid(in_h1)in_h2 = self.w3 * self.x1 + self.w4 * self.x2 + bout_h2 = self.sigmoid(in_h2)in_o1 = self.w5 * out_h1 + self.w6 * out_h2out_o1 = self.sigmoid(in_o1)in_o2 = self.w7 * out_h1 + self.w8 * out_h2out_o2 = self.sigmoid(in_o2)loss += (self.y1 - out_o1) ** 2 + (self.y2 - out_o2) ** 2loss = loss / 2return out_o1, out_o2, out_h1, out_h2, lossdef back_propagate(self, out_o1, out_o2, out_h1, out_h2):d_o1 = (out_o1 - self.y1)d_o2 = (out_o2 - self.y2)d_w5 = d_o1 * out_o1 * (1 - out_o1) * out_h1d_w6 = d_o1 * out_o1 * (1 - out_o1) * out_h2d_w7 = d_o2 * out_o2 * (1 - out_o2) * out_h1d_w8 = d_o2 * out_o2 * (1 - out_o2) * out_h2d_w1 = (d_w5 + d_w6) * out_h1 * (1 - out_h1) * self.x1d_w2 = (d_w5 + d_w6) * out_h1 * (1 - out_h1) * self.x2d_w3 = (d_w7 + d_w8) * out_h2 * (1 - out_h2) * self.x1d_w4 = (d_w7 + d_w8) * out_h2 * (1 - out_h2) * self.x2self.d_w1, self.d_w2, self.d_w3, self.d_w4 = d_w1, d_w2, d_w3, d_w4self.d_w5, self.d_w6, self.d_w7, self.d_w8 = d_w5, d_w6, d_w7, d_w8returndef update_w(self):self.w1 = self.w1 - self.learning_rate * self.d_w1self.w2 = self.w2 - self.learning_rate * self.d_w2self.w3 = self.w3 - self.learning_rate * self.d_w3self.w4 = self.w4 - self.learning_rate * self.d_w4self.w5 = self.w5 - self.learning_rate * self.d_w5self.w6 = self.w6 - self.learning_rate * self.d_w6self.w7 = self.w7 - self.learning_rate * self.d_w7self.w8 = self.w8 - self.learning_rate * self.d_w8if __name__ == "__main__":w_key = ['w1', 'w2', 'w3', 'w4', 'w5', 'w6', 'w7', 'w8']w_value = [1, -2, -1, 1, 2, -2, -2, -1]parameter = dict(zip(w_key, w_value))parameter['x1'] = 1parameter['x2'] = -1parameter['y1'] = 0.01parameter['y2'] = 0.99parameter['learning_rate'] = 0.5network = Network(**parameter)for i in range(10000):out_o1, out_o2, out_h1, out_h2, loss = network.forward_propagate()if (i % 1000 == 0):print("第{}轮的loss={}".format(i,loss))network.back_propagate(out_o1, out_o2, out_h1, out_h2)network.update_w()print("更新后的权重")print(network.w1, network.w2, network.w3, network.w4, network.w5, network.w6, network.w7, network.w8)

输出为:

0轮的loss=0.71592427504641741000轮的loss=0.00033994112826449472000轮的loss=0.000121845330006650643000轮的loss=6.271954032855594e-054000轮的loss=3.751394416870217e-055000轮的loss=2.438595788224937e-056000轮的loss=1.6716935251649648e-057000轮的loss=1.1889923562720554e-058000轮的loss=8.688471135735563e-069000轮的loss=6.481437220727472e-06
更新后的权重
0.9057590485430621 -1.9057590485430547 0.4873077189729459 -0.4873077189729459 -1.130913420789734 -3.752510764474653 2.7328131233332877 1.948002277914531

使用pytorch来练习上述过程

import torch
from torch import nnclass Network(nn.Module):def __init__(self, w_value):super().__init__()self.sigmoid = nn.Sigmoid()self.linear1 = nn.Linear(2, 2, bias=True)self.linear1.weight.data = torch.tensor(w_value[:4], dtype=torch.float32).view(2, 2)self.linear1.bias.data = torch.ones(2)self.linear2 = nn.Linear(2, 2, bias=True)self.linear2.weight.data = torch.tensor(w_value[4:], dtype=torch.float32).view(2, 2)self.linear2.bias.data = torch.ones(2)def forward(self, x):x = self.linear1(x)x = self.sigmoid(x)x = self.linear2(x)x = self.sigmoid(x)return xw_value = [1, -2, -1, 1, 2, -2, -2, -1]
network = Network(w_value)loss_compute = nn.MSELoss()
learning_rate = 0.5
optimizer = torch.optim.SGD(network.parameters(), lr=learning_rate)x1, x2 = 1, -1
y1, y2 = 0.01, 0.99
inputs = torch.tensor([x1, x2], dtype=torch.float32)
targets = torch.tensor([y1, y2], dtype=torch.float32)for i in range(10000):optimizer.zero_grad()outputs = network(inputs)loss = loss_compute(outputs, targets)if (i % 1000 == 0):print("第{}轮的loss={}".format(i, loss))loss.backward()optimizer.step()# 最终的权重和偏差
print("权重:")
print(network.linear1.weight)
print(network.linear2.weight)
print("偏差:")
print(network.linear1.bias)
print(network.linear2.bias)
0轮的loss=0.70506429672241211000轮的loss=0.00017875838966574522000轮的loss=5.7717210438568145e-053000轮的loss=2.7112449970445596e-054000轮的loss=1.487863755755825e-055000轮的loss=8.897048246581107e-066000轮的loss=5.617492206511088e-067000轮的loss=3.6816677493334282e-068000轮的loss=2.4793637294351356e-069000轮的loss=1.704187070572516e-06
权重:
Parameter containing:
tensor([[ 0.9223, -1.9223],[-0.0543,  0.0543]], requires_grad=True)
Parameter containing:
tensor([[-0.3244, -3.2635],[ 0.5369,  0.4165]], requires_grad=True)
偏差:
Parameter containing:
tensor([0.9223, 1.9457], requires_grad=True)
Parameter containing:
tensor([-1.3752,  3.5922], requires_grad=True)

函数拟合

问题描述

理论和实验证明,一个两层的ReLU网络可以模拟任何函数[1~5]。请自行定义一个函数, 并使用基于ReLU的神经网络来拟合此函数。

要求

  • 请自行在函数上采样生成训练集和测试集,使用训练集来训练神经网络,使用测试集来验证拟合效果。
  • 可以使用深度学习框架来编写模型。
from torch.utils.data import DataLoader
from torch.utils.data import TensorDataset
import torch.nn as nn
import numpy as np
import torch# 准备数据
x1 = np.linspace(-2 * np.pi, 2 * np.pi, 400)
x2 = np.linspace(np.pi, -np.pi, 400)
y = np.sin(x1) + np.cos(3 * x2)
# 将数据做成数据集的模样
X = np.vstack((x1, x2)).T
Y = y.reshape(400, -1)
# 使用批训练方式
dataset = TensorDataset(torch.tensor(X, dtype=torch.float), torch.tensor(Y, dtype=torch.float))
dataloader = DataLoader(dataset, batch_size=100, shuffle=True)# 神经网络主要结构,这里就是一个简单的线性结构class Net(nn.Module):def __init__(self):super(Net, self).__init__()self.net = nn.Sequential(nn.Linear(in_features=2, out_features=10), nn.ReLU(),nn.Linear(10, 100), nn.ReLU(),nn.Linear(100, 10), nn.ReLU(),nn.Linear(10, 1))def forward(self, input: torch.FloatTensor):return self.net(input)net = Net()# 定义优化器和损失函数
optim = torch.optim.Adam(Net.parameters(net), lr=0.001)
Loss = nn.MSELoss()# 下面开始训练:
# 一共训练 1000次
for epoch in range(1000):loss = Nonefor batch_x, batch_y in dataloader:y_predict = net(batch_x)loss = Loss(y_predict, batch_y)optim.zero_grad()loss.backward()optim.step()# 每100次 的时候打印一次日志if (epoch + 1) % 100 == 0:print("step: {0} , loss: {1}".format(epoch + 1, loss.item()))# 使用训练好的模型进行预测
predict = net(torch.tensor(X, dtype=torch.float))# 绘图展示预测的和真实数据之间的差异
import matplotlib.pyplot as pltplt.plot(x1, y, label="fact")
plt.plot(x1, predict.detach().numpy(), label="predict")
plt.title("function")
plt.xlabel("x1")
plt.ylabel("sin(x1)+cos(3 * x2)")
plt.legend()
plt.show()

输出:

step: 100 , loss: 0.23763391375541687
step: 200 , loss: 0.06673044711351395
step: 300 , loss: 0.044088222086429596
step: 400 , loss: 0.013059427961707115
step: 500 , loss: 0.010913526639342308
step: 600 , loss: 0.003434327431023121
step: 700 , loss: 0.00702542532235384
step: 800 , loss: 0.001976138213649392
step: 900 , loss: 0.0032644111197441816
step: 1000 , loss: 0.003176396246999502

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/19589.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

达梦数据库写文件的方式探索

0x01 前沿 这篇文章整体算是《达梦数据库手工注入笔记》的续集,达梦作为国内优秀的信创数据库,在关基单位中拥有越来越大的用户使用量。 通过SQL注入来写文件一直以来都是SQL注入漏洞深入利用的一种方式,对于不同的数据库通常写文件的方式也是…

刷代码随想录有感(86):贪心算法——跳跃游戏II(最小跳跃次数)

题干&#xff1a; 代码&#xff1a; class Solution { public:int jump(vector<int>& nums) {if(nums.size() 1)return 0;int curcover 0;int nextcover 0;int res 0;for(int i 0; i < curcover; i){nextcover max(i nums[i], nextcover);if(i curcover …

二叉树的链式存储

目录 1.二叉树的概念和性质2.二叉树的链式存储2.1二叉树的遍历2.1.1前中后遍历2.1.2层次遍历 2.2求节点的个数2.3求叶子节点的个数2.4求第k层节点个数2.5二叉树的销毁2.6怎样通过前序遍历构建二叉树2.7判断是否是满二叉树 1.二叉树的概念和性质 一&#xff0c;概念 1.五种形态…

掌握 JavaScript 基本输出方法

掌握 JavaScript 基本输出方法 前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接下来还会持续更新。 作者&#xff1a;神的孩子都在歌唱 JavaScript 是一种强大且灵活的编程语言&#xff0c;广泛用于 Web 开发。通过 JavaScript&#xff…

YOLOV8训练自己的数据集图文实战,包含voc数据集处理代码

yolov8官方链接: link 本文章是以labelimg标注好的voc数据集为基础,通过转换格式训练模型, 一,安装 pip install ultralyticsor pip install githttps://github.com/ultralytics/ultralytics.gitmainlink 二,数据集准备 数据集格式如下 ├── ultralytics └── datase…

RocketMq broker源码解析

broker 集群工作流程 NameSrv启动成功后&#xff0c;等待broker、Consumer和producer启动后也与NameSrv保持长连接, NameSrv相当于是路由控制中心。启动broker, broker与所有的NameSrv建立长连接, broker&#xff0c;通过定时线程定时向NameSrv发送心跳&#xff0c;broker信息…

LightDB pro*c迁移指南(游标模块)

文章目录 一、不使用SQLDA描述符范围的游标操作1.1 oracle 案例1.1.1 使用游标获取数据1.1.2 对于fetch结果集怎么去利用 1.2 LightDB 案例1.2.1 使用游标获取数据1.2.2 对于fetch结果集怎么去利用 3 总结&#xff1a;不同项 二、使用SQLDA描述符范围的游标操作2.1 Oracle样例2…

KMPlayer v2024.4.25.13 官方版 (万能播放器)

前言 KMPlaye通过各种插件扩展KMP可以支持层出不穷的新格式。KMPlaye强大的插件功能&#xff0c;直接从Winamp继承的插件功能&#xff0c;能够直接使用Winamp的音频&#xff0c;输入&#xff0c;视觉效果插件&#xff0c;而通过独有的扩展能力&#xff0c;只要你喜欢&#xff…

webman-admin多图上传预览和删除

前言 在webmen文档和论坛中都没找到多图上传的示例&#xff0c;自己找了一个&#xff0c;整合了一下凑合用 insert页面 引入css <link rel"stylesheet" href"/app/admin/admin/css/muti-upload.css" />muti-upload.css内容如下 .uploader-list .ha…

微信小程序学习

04.认识小程序项目的基本组成结构 把allow改成disallow,表示所有的页面不被微信进行索引。 比如修改首页的上面栏颜色

自制数据#国家2000投影带划分范围shp(高斯克吕格 3°/6°分带)

国家2000投影分带范围&#xff08;3&#xff09; https://www.123pan.com/s/lqEljv-xvCHA.html 国家2000投影分带范围&#xff08;6&#xff09; https://www.123pan.com/s/lqEljv-xvCHA.html 声明&#xff1a;转载此文不为商业用途。文字和图片版权归原作者所有&#xff0c;…

网络安全基础技术扫盲篇名词解释之“证书“

用通俗易懂的话说&#xff1a; 证书就好比是一张身份证&#xff08;类似&#xff0c;但不完全相同&#xff09;&#xff0c;用来证明一个网站的身份是否可信。就像你要确认一个陌生人的身份需要看他的身份证一样&#xff0c;电脑在连接一个网站时&#xff0c;也会查看网站的证…

延时性(过期/超时)和周期性的定时任务的实现方式

延时性&#xff08;过期/超时&#xff09;和周期性的定时任务的实现方式 一、延时性的定时任务&#xff08;例如订单超时30分钟后自动取消该订单&#xff09;1.使用DelayQueue实现任务即将到期提醒功能&#xff08;非分布式&#xff09;2.使用Redis实现任务即将到期提醒功能&am…

探索Web3工具:正确使用区块链平台工具的秘诀

在当今日新月异的数字时代&#xff0c;区块链技术正以惊人的速度改变着我们的生活和工作方式。尤其对于那些想要踏入区块链世界的人来说&#xff0c;正确使用区块链平台工具至关重要。本文将向您介绍一些关键的Web3工具&#xff0c;并以TestnetX.com为例&#xff0c;展示如何利…

数字化转型推动生物技术企业增长—纷享销客与集萃药康共探新动力

上周&#xff0c;在南京锦创书城&#xff0c;一场主题为“生物技术企业增长新动力&#xff1a;以客户为中心的数字化转型与创新”的研讨会圆满落幕。此次活动由纷享销客江苏分公司联合江苏集萃药康生物科技股份有限公司共同举办&#xff0c;吸引了众多生物技术领域企业的负责人…

斑消宝六周年大动作,斑小将将再迎高光时刻

如今&#xff0c;周年庆典已经成为众多品牌展示自身实力与影响力的重要舞台。这不仅仅是一个简单的庆祝活动&#xff0c;更是一次向外界展示品牌发展历程、未来规划以及团结合作伙伴的绝佳机会。在这样的背景下&#xff0c;广州斑消宝化妆品有限公司将打造别具一格的盛典&#…

npm安装依赖报错npm ERR! code ENOTFOUNDnpm ERR! syscall getaddrinfo

npm安装依赖报错 今天在学习vue的时候&#xff0c;在使用npm install vue -g来安装一个局部的vue时候&#xff0c;报出如下错误&#xff1a; npm ERR! code CERT_HAS_EXPIRED npm ERR! errno CERT_HAS_EXPIRED npm ERR! request to https://registry.npm.taobao.org/vue faile…

iphone内存满了开不了机怎么办?白苹果解决办法分享!

虽然苹果手机在使用时比较顺畅&#xff0c;但是手机用久了&#xff0c;照片、视频等资料累积过多&#xff0c;也难免会导致内存不足&#xff0c;出现无法开机卡在开机界面白苹果的情况。 内存不足导致iPhone白苹果的问题很常见&#xff0c;可以说是苹果最常见的故障之一。接下来…

【学习笔记】Windows GDI绘图(九)Graphics详解(上)

文章目录 Graphics 定义创建Graphics对象的方法通过Graphics绘制不同的形状、线条、图像和文字等通过Graphics操作对象坐标 Graphics属性Clip(裁切/绘制区域)ClipBounds获取裁切区域矩形范围CompositiongMode合成方式CompositingQuality渲染质量DpiX和DpiY 水平、垂直分辨率Int…

C++ 逻辑运算

一 逻辑运算 2 逻辑运算符 逻辑表达式 四 逻辑表达式 五 逻辑运算符的优先级 六 注意事项 注意 总结