用最原始的代码实现——反向传播(回归)

本文没有使用现有的框架,仅使用最原始的代码创建神经网络实现对sin函数的学习。

1.导入相关库

import numpy as np
import matplotlib.pyplot as plt

2.准备输入数据和正确答案数据(对应的label)

input_data = np.arange(0, np.pi*2, 0.1)    #输入
correct_data = np.sin(input_data)          #对应的label
input_data = (input_data-np.pi)/np.pi       #将输入收敛到-1.0~1.0的范围之内
n_data = len(correct_data)                 #数据数量

3.各个设定值

n_in = 1                #输入层的神经元数量
n_mid = 3               #中间层的神经元数量
n_out = 1               #输出层的神经元数量

wb_width = 0.01         #权重和偏置的扩散程度
eta = 0.1               #学习系数
epoch = 2001            #迭代次数
interval = 200          #显示进度的间隔实践

4.中间层

class MiddleLayer:
    def __init__(self, n_upper, n):                        #初始化设置
        self.w = wb_width * np.random.randn(n_upper, n)    #权重(矩阵)
        self.b = wb_width * np.random.randn(n)             #偏置(向量)
        
    def forward(self, x):                                  #正向传播
        self.x = x
        u = np.dot(x, self.w) + self.b
        self.y = 1/(1 + np.exp(-u))                        #sigmoid函数

    def backward(self, grad_y):
        delta = grad_y * (1 - self.y) * self.y             #sigmoid函数的微分

        self.grad_w = np.dot(self.x.T, delta)
        self.grad_b = np.sum(delta, axis = 0)

        self.grad_x = np.dot(delta, self.w.T)

    def update(self, delta):                               #权重和偏置的更新
        self.w -= eta * self.grad_w
        self.b -= eta * self.grad_b

5.输出层

class OutputLayer:
    def __init__(self, n_upper, n):                        #初始化设置
        self.w = wb_width * np.random.randn(n_upper, n)    #权重(矩阵)
        self.b = wb_width * np.random.randn(n)             #偏置(向量)
        
    def forward(self, x):                                  #正向传播
        self.x = x
        u = np.dot(x, self.w) + self.b
        self.y = u                                         #恒等函数

    def backward(self, t):                                 #反向传播
        delta = self.y - t  
           
        self.grad_w = np.dot(self.x.T, delta)
        self.grad_b = np.sum(delta, axis = 0)

        self.grad_x = np.dot(delta, self.w.T)

    def update(self, delta):                               #权重和偏置的更新
        self.w -= eta * self.grad_w
        self.b -= eta * self.grad_b

6.各个网络层的初始化

middle_layer = MiddleLayer(n_in, n_mid)
output_layer = OutputLayer(n_mid, n_out)

7.神经网络学习

for i in range(epoch):

    #随机打乱索引值
    index_random = np.arange(n_data)
    np.random.shuffle(index_random)

    #用于结果的显示
    total_error = 0
    plot_x = []
    plot_y = []
    
    for idx in index_random:
        x = input_data[idx:idx+1]
        t = correct_data[idx:idx+1]
    
        #正向传播
        middle_layer.forward(x.reshape(1,1))        #将输入转换为矩阵
        output_layer.forward(middle_layer.y)

        #反向传播
        output_layer.backward(t.reshape(1,1))       #将正确答案转为矩阵
        middle_layer.backward(output_layer.grad_x)

        #权重和偏置的更新
        middle_layer.update(eta)
        output_layer.update(eta)

        if i%interval == 0:

            y = output_layer.y.reshape(-1)

            #误差的计算
            total_error += 1.0/2.0 * np.sum(np.square(y-t))    #平方和误差

            plot_x.append(x)
            plot_y.append(y)

    if i%interval == 0:

        plt.plot(input_data, correct_data, linestyle = "dashed")
        plt.scatter(plot_x, plot_y, marker = "+")
        plt.show()

        print("Epoch:" + str(i) + "/" + str(epoch),
                "Error:" + str(total_error/n_data))

完整代码:

import numpy as np
import matplotlib.pyplot as plt

input_data = np.arange(0, np.pi*2, 0.1)    #输入
correct_data = np.sin(input_data)          #对应的label
input_data = (input_data-np.pi)/np.pi       #将输入收敛到-1.0~1.0的范围之内
n_data = len(correct_data)                 #数据数量

n_in = 1                #输入层的神经元数量
n_mid = 3               #中间层的神经元数量
n_out = 1               #输出层的神经元数量

wb_width = 0.01         #权重和偏置的扩散程度
eta = 0.1               #学习系数
epoch = 2001            #迭代次数
interval = 200          #显示进度的间隔实践


class MiddleLayer:
    def __init__(self, n_upper, n):  # 初始化设置
        self.w = wb_width * np.random.randn(n_upper, n)  # 权重(矩阵)
        self.b = wb_width * np.random.randn(n)  # 偏置(向量)

    def forward(self, x):  # 正向传播
        self.x = x
        u = np.dot(x, self.w) + self.b
        self.y = 1 / (1 + np.exp(-u))  # sigmoid函数

    def backward(self, grad_y):
        delta = grad_y * (1 - self.y) * self.y  # sigmoid函数的微分

        self.grad_w = np.dot(self.x.T, delta)
        self.grad_b = np.sum(delta, axis=0)

        self.grad_x = np.dot(delta, self.w.T)

    def update(self, delta):  # 权重和偏置的更新
        self.w -= eta * self.grad_w
        self.b -= eta * self.grad_b


class OutputLayer:
    def __init__(self, n_upper, n):  # 初始化设置
        self.w = wb_width * np.random.randn(n_upper, n)  # 权重(矩阵)
        self.b = wb_width * np.random.randn(n)  # 偏置(向量)

    def forward(self, x):  # 正向传播
        self.x = x
        u = np.dot(x, self.w) + self.b
        self.y = u  # 恒等函数

    def backward(self, t):  # 反向传播
        delta = self.y - t

        self.grad_w = np.dot(self.x.T, delta)
        self.grad_b = np.sum(delta, axis=0)

        self.grad_x = np.dot(delta, self.w.T)

    def update(self, delta):  # 权重和偏置的更新
        self.w -= eta * self.grad_w
        self.b -= eta * self.grad_b


middle_layer = MiddleLayer(n_in, n_mid)
output_layer = OutputLayer(n_mid, n_out)

for i in range(epoch):

    # 随机打乱索引值
    index_random = np.arange(n_data)
    np.random.shuffle(index_random)

    # 用于结果的显示
    total_error = 0
    plot_x = []
    plot_y = []

    for idx in index_random:
        x = input_data[idx:idx + 1]
        t = correct_data[idx:idx + 1]

        # 正向传播
        middle_layer.forward(x.reshape(1, 1))  # 将输入转换为矩阵
        output_layer.forward(middle_layer.y)

        # 反向传播
        output_layer.backward(t.reshape(1, 1))  # 将正确答案转为矩阵
        middle_layer.backward(output_layer.grad_x)

        # 权重和偏置的更新
        middle_layer.update(eta)
        output_layer.update(eta)

        if i%interval == 0:
            y = output_layer.y.reshape(-1)

            # 误差的计算
            total_error += 1.0 / 2.0 * np.sum(np.square(y - t))  # 平方和误差

            plot_x.append(x)
            plot_y.append(y)

    if i%interval == 0:
        plt.plot(input_data, correct_data, linestyle="dashed")
        plt.scatter(plot_x, plot_y, marker="+")
        plt.show()

        print("Epoch:" + str(i) + "/" + str(epoch),
              "Error:" + str(total_error / n_data))

 

  

  

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值