自己编写全连接神经网络完成一个简单回归问题

1.全连接网络的基本流程

1.有一系列已经归一化的数据在这里插入图片描述
2.一个网络模型y = fcNet(x)
在这里插入图片描述

其中
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

所以从第i层fc到第i+1层的递归公式
在这里插入图片描述
在这里插入图片描述

3.正向传播

先一个列向量
在这里插入图片描述
按照递推公式
输出到模型中得到label,也就是y
在这里插入图片描述
4.定义最普通的损失函数
在这里插入图片描述
5.bp反向传播
这里面我要解释一下有些数学表达式的写法以免误解

A * B 或者AB的意思是:向量对应分量乘积,既不是矩阵乘法也不是向量内积,因为numpy就是这么定义的比如
在这里插入图片描述

A mul B的意思的:A,B矩阵乘积
在这里插入图片描述

训练网络最终目的是让y与label(y的真实值)的差距越小越好,也就是使得loss的值最小,所以把loss当成因变量,把fcNet中的所有参数和y的真实值当成自变量,loss关于它们的函数,就是这个样子
在这里插入图片描述
分开来就是
在这里插入图片描述
其中
在这里插入图片描述
在这里插入图片描述

流程大家大概都知道,让loss对每个w求导,设求出来的值是
在这里插入图片描述

这个就是多元函数
在这里插入图片描述
对某一个w的梯度了对吧

然后设置一个学习率,learning = 0.01什么的
然后让每个w
在这里插入图片描述
就相当于是梯度更新

但是有三个问题不容易算清楚
1.越是前面的层,它的求导越麻烦,因为涉及到复合函数求导的链式法则
2.前向计算的时候正着来,一个接一个矩阵乘法,反向传播的时候反着往前求导,矩阵的递推关系相比正向计算要复杂一些
3.编程的时候不像我们在纸上面计算,所有的东西都相当于全局变量,随时可以取到它们的值,我编程的时候,一层作为一个fc类,那么这一层的全连接神经网络只能知道本层的
(输入向量值,W参数,输出向量值)
想要知道前一层或者后一层的数据,只能通过前向计算或者反向传播的时候,前层或者后层返回的数据才知道。那么前一层或者后一层传过来的数据,是什么维度的,表示什么含义,一定要统一,不然就乱套了,没有办法传递了

在这里插入图片描述

从任意多的全连接层扣出2层来看
考虑这样一个第i层和第i+1层的问题,假如要对第i层的W矩阵求导
那么一定是这样的
在这里插入图片描述
其中第一项,跟i+1层有关,第i层是不可能算出来的,所以它应该作为第i+1层传过来的参数

在这里插入图片描述
这边可以看出来,表达式(1)的后面两项是可以在本层内计算的,且并不复杂,那第一项呢?

要考虑第一项是怎么样的,可以先考虑一下目前作为第i层,又该往i-1层传什么?先看第i-1层对W求导需要什么
在这里插入图片描述

很显然第一项,是需要第i层提供的,而这一项等于
在这里插入图片描述
在这个表达式中,第一项是第i+1层提供给第i层的,后两项是第i层自己可以计算到的,这样子,整个bp传播的递推就完整了,整理一下

对于第i层来说
在这里插入图片描述

化简一下(4),(5)表达式
在这里插入图片描述
所以整个反向传播函数大概这样

def bp(self,last,learning_rate):
        act = np.reshape(self.outx*(1-self.outx),[-1,1])
        p=last*act
        grad = np.matmul(p,np.reshape(self.inx,[1,self.input_dim]))
        pass_next = np.matmul(np.reshape(p,[1,-1]),self.w)
        self.w -= learning_rate*grad 
        return np.reshape(pn,[-1,1])

在整个对loss的前向计算过程中
在这里插入图片描述
对于这个图片所描述的网络
在这里插入图片描述
把y看成X5(in)
那么第一个last输入就是
在这里插入图片描述
也就是说,对于一个回归网络,且用方差作为损失函数的话,第一个last就是
在这里插入图片描述

然后就开始试着用自己写的网络训练了,以下为代码

2代码

1.定义自己的全连接层结构fc
默认激活函数为sigmoid

import numpy as np
class fc():
    def __init__(self,input_dim,out_dim,name):
        self.name = name
        self.input_dim = input_dim
        self.out_dim = out_dim
        self.w = np.random.uniform(-0.2,0.2,(self.out_dim,self.input_dim)) 
        self.b = np.random.uniform(-0.5,0.5,(self.out_dim))
        self.disable = np.ones([self.out_dim,self.input_dim])
        self.inx =np.zeros([self.input_dim])
        self.outx =np.zeros([self.out_dim])
    
    def forward(self,x):
        self.inx = x
        self.outx = self.sigmoid(np.matmul(self.w,self.inx))+self.b
        return self.outx
    
    def bp(self,last,learning_rate):
        act = np.reshape(self.outx*(1-self.outx),[-1,1])
        p=last*act
        grad = np.matmul(p,np.reshape(self.inx,[1,self.input_dim]))
        pn = np.matmul(np.reshape(p,[1,-1]),self.w)
        self.w -= learning_rate*grad 
        return np.reshape(pn,[-1,1])

    def sigmoid(self,x):
        return 1/(1+np.exp(-x))

    

2.定义网络结构Net
这里定义了4层

class Net():
    def __init__(self):
        self.fc1 = fc(4,256,'fc1')
        self.fc2 = fc(256,64,'fc2')
        self.fc3 = fc(64,128,'fc3')
        self.fc4 = fc(128,1,'fc3')
    
    def forword(self,x):
        x = self.fc1.forward(x)
        x = self.fc2.forward(x)
        x = self.fc3.forward(x)
        x = self.fc4.forward(x)
        return x
    
    def bp(self,E,learning_rate):
        E4 = self.fc4.bp(E,learning_rate)
        E3 = self.fc3.bp(E4,learning_rate)
        E2 = self.fc2.bp(E3,learning_rate)
        E1 = self.fc1.bp(E2,learning_rate)

3.创建网络实例

fcNet = Net()

4.读取数据并查看了前4行
这边我随便找了一个aistudio上的数据集
股票数据集
因为这个代码可以处理的是回归问题,多个输入,一个输出

import pandas as pd
CSV_FILE_PATH = './work/AAPL.csv'
df = pd.read_csv(CSV_FILE_PATH)
df[:4]

在这里插入图片描述
5.简单处理数据,归一化,减均值除以标准差

x = df[['Open', 'High', 'Low', 'Close', 'Volume']]
x = np.array(x)
avg = x.sum(axis=0)/len(x)
avg
o =[0,0,0,0,0] 
for i in x:
    o[0]+=i[0]**2
    o[1]+=i[1]**2
    o[2]+=i[2]**2
    o[3]+=i[3]**2
    o[4]+=i[4]**2
xn = (x-avg)/(np.array(o)**0.5)

6.定义一次训练过程的函数

import random
def once(losses,learning_rate):
    c =0
    losssum =0
    index = [i for i in range(len(xn))]
    random.shuffle(index)
    for i in index:
        c+=1
        d = xn[i][:4]
        l = xn[i][4:5]
        loss= abs(fcNet.forword(d) - l)
        fcNet.bp(loss,learning_rate)
        losssum+=loss**2
        if(c%300==0):
            print(losssum)
            losses.append(losssum)
            losssum=0
    

7.开始训练,用一个列表保存每300次更新后,损失函数的值,并打印输出

losses = []
learn_rate = 0.0003
for i in range(1,10):
    print('now,learning_rate={}'.format(learn_rate))
    once(losses,learn_rate)

8.画图,看一下训练过程中损失函数的减小趋势

import matplotlib.pyplot as plt
plt.plot([i for i in range(len(losses))],losses)

在这里插入图片描述

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值