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

1.有一系列已经归一化的数据

神经网络归一化必须0到1吗 神经网络自回归_神经网络


2.一个网络模型y = fcNet(x)

神经网络归一化必须0到1吗 神经网络自回归_线性代数_02

其中

神经网络归一化必须0到1吗 神经网络自回归_线性代数_03

神经网络归一化必须0到1吗 神经网络自回归_深度学习_04


神经网络归一化必须0到1吗 神经网络自回归_神经网络归一化必须0到1吗_05

所以从第i层fc到第i+1层的递归公式

神经网络归一化必须0到1吗 神经网络自回归_神经网络_06


神经网络归一化必须0到1吗 神经网络自回归_算法_07

3.正向传播

先一个列向量

神经网络归一化必须0到1吗 神经网络自回归_神经网络归一化必须0到1吗_08


按照递推公式

输出到模型中得到label,也就是y

神经网络归一化必须0到1吗 神经网络自回归_算法_09


4.定义最普通的损失函数

神经网络归一化必须0到1吗 神经网络自回归_神经网络归一化必须0到1吗_10


5.bp反向传播

这里面我要解释一下有些数学表达式的写法以免误解A * B 或者AB的意思是:向量对应分量乘积,既不是矩阵乘法也不是向量内积,因为numpy就是这么定义的比如

神经网络归一化必须0到1吗 神经网络自回归_深度学习_11

A mul B的意思的:A,B矩阵乘积

神经网络归一化必须0到1吗 神经网络自回归_神经网络归一化必须0到1吗_12

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

神经网络归一化必须0到1吗 神经网络自回归_神经网络_13


分开来就是

神经网络归一化必须0到1吗 神经网络自回归_神经网络_14


其中

神经网络归一化必须0到1吗 神经网络自回归_算法_15


神经网络归一化必须0到1吗 神经网络自回归_线性代数_16

流程大家大概都知道,让loss对每个w求导,设求出来的值是

神经网络归一化必须0到1吗 神经网络自回归_线性代数_17

这个就是多元函数

神经网络归一化必须0到1吗 神经网络自回归_线性代数_18


对某一个w的梯度了对吧然后设置一个学习率,learning = 0.01什么的

然后让每个w

神经网络归一化必须0到1吗 神经网络自回归_算法_19


就相当于是梯度更新

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

神经网络归一化必须0到1吗 神经网络自回归_神经网络归一化必须0到1吗_20

从任意多的全连接层扣出2层来看

考虑这样一个第i层和第i+1层的问题,假如要对第i层的W矩阵求导

那么一定是这样的

神经网络归一化必须0到1吗 神经网络自回归_线性代数_21


其中第一项,跟i+1层有关,第i层是不可能算出来的,所以它应该作为第i+1层传过来的参数

神经网络归一化必须0到1吗 神经网络自回归_神经网络归一化必须0到1吗_22


这边可以看出来,表达式(1)的后面两项是可以在本层内计算的,且并不复杂,那第一项呢?要考虑第一项是怎么样的,可以先考虑一下目前作为第i层,又该往i-1层传什么?先看第i-1层对W求导需要什么

神经网络归一化必须0到1吗 神经网络自回归_算法_23

很显然第一项,是需要第i层提供的,而这一项等于

神经网络归一化必须0到1吗 神经网络自回归_神经网络_24


在这个表达式中,第一项是第i+1层提供给第i层的,后两项是第i层自己可以计算到的,这样子,整个bp传播的递推就完整了,整理一下对于第i层来说

神经网络归一化必须0到1吗 神经网络自回归_线性代数_25

化简一下(4),(5)表达式

神经网络归一化必须0到1吗 神经网络自回归_神经网络归一化必须0到1吗_26


所以整个反向传播函数大概这样

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的前向计算过程中

神经网络归一化必须0到1吗 神经网络自回归_神经网络_27


对于这个图片所描述的网络

神经网络归一化必须0到1吗 神经网络自回归_神经网络_28


把y看成X5(in)

那么第一个last输入就是

神经网络归一化必须0到1吗 神经网络自回归_算法_29


也就是说,对于一个回归网络,且用方差作为损失函数的话,第一个last就是

神经网络归一化必须0到1吗 神经网络自回归_线性代数_30

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

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]

神经网络归一化必须0到1吗 神经网络自回归_神经网络_31


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)

神经网络归一化必须0到1吗 神经网络自回归_神经网络_32