Python实现神经网络(零基础篇)_神经网络应用实现,百度、阿里、滴滴、新浪的面试心经总结

109 阅读8分钟

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。 img img

如果你需要这些资料,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

a = (1,3)
b = (5,7)
c = zip(a,b)
print(list(c))
#结果:[(1, 5), (3, 7)]

range函数创建一个整数列表

a = range(0,5,2) #从0开始加2一直加到5-1为止的所有整数
print([x for x in a])
#结果:[0, 2, 4]

全连接神经网络基础

本章节从Python的实现角度阐述全连接神经网络的基本框架,以及实现这些框架的Python语句

正如我们的大脑一样,通过皮肤眼睛等感受器对外界刺激的感受,感受以神经递质的方式在神经元之间传递,神经元通过正负电荷来处理感受信息。

受到这种启发,计算机的处理器也是1、0信号,通过有无电流进行处理。所以神经网络必然离不开神经元。一般全连接神经网络分为输入层、隐藏层、输出层三结构。
在这里插入图片描述

图中的圆圈就是一个个神经元,又称为节点,他们负责接收并处理外界或上一节点传输的数据。我们要做的便是用Python解释器来编写这样一个网络。因此我们先要引入工具包numpy.

import numpy

激活函数主要使用了sigmoid函数(现在大部分都是用Relu函数,详细原因将在优化提及),所以我们要先对激活函数进行定义

def sigmoid (x):
    return 1/(1+numpy.exp(-x))

文字解释:
定义一个函数名字叫sigmoid,需要一个变量(x)
输入数x后返回一个1/(1+e^(-x))的值

每个节点的运算方式都大同小异为sigmoid(WX+b),比如隐藏层第一个的h1便是X0×W1,h1f便是此神经元输出给下一层的数值。

注:关于权重W、偏置b以及激活函数的产生主要与线行分类器基础知识相关,本文是用Python实现全连接神经网络,在此不做过多理论解释,详细可以查看全连接神经网络基础部分。

神经元功能的定义

因此对于每一个节点来时,我们可以定义一个节点函数。

def feedforward(self,x):
        h1 = x[0]\*self.w1+x[1]\*self.w2+self.b1
        h1f = sigmoid(h1)
        h2 = x[0]\*self.w3+x[1]\*self.w4+self.b2
        h2f = sigmoid(h2)
        o1 = h1f\*self.w5+h2f\*self.w6+self.b3
        of = sigmoid(o1)

文字解释:
定义一个函数叫做 feedforward ,需要一个对象(本文值一个神经网络)和一个二维向量为自变量。(即在使用此函数时,需要给它一个神经网络和一组输入数据)

h1等于( X0 乘 所给网络的权重W1) 加 (X1乘所给网络权重W2 加偏置b1)
以此类推

这样我们就对神经网络的运算过程做了定义。接下来,我们需要解决网络的权重和偏置的问题。神经网络在初始化时会随机分配权重与偏置,我们不妨用高斯分布来取值。

神经网络的类定义

class nerualnetwo():
    def \_\_init\_\_(self):
       self.w1 = numpy.random.normal()
       self.w2 = numpy.random.normal()
       self.w3 = numpy.random.normal()
       self.w4 = numpy.random.normal()
       self.w5 = numpy.random.normal()
       self.w6 = numpy.random.normal()
       self.b1 = numpy.random.normal()
       self.b2 = numpy.random.normal()
       self.b3 = numpy.random.normal()

文字解释:
制作一个类叫做nerualnetwo
对这个类自身特有属性进行定义:
它的W1为高斯分布随机数值
以此类推

神经网络的高精准离不开大数据,在神经网络种,我们需要给定输入和输出作为训练集,让其进行训练,然后才能使用。那么训练的标准就是损失函数,要确定真实值与神经网络预测值之间的损失,通过调整权重和偏置以达到损失越来越小,知道符合期望为止。首先就要定义损失函数。

损失函数的定义

def mse\_loss(y_tr,y_pre):
    return((y_tr - y_pre)\*\*2).mean()

文字解释:
定义一个函数 mse_loss,需要真实值和预测值做为参数
返回真实值减预测值平方的平均值

网络的训练

有了损失函数L,我们就可以对神经网络进行训练了,训练的目的就是为了减小损失。那么减小损失一半会通过增加或减少W和b,改变损失值,如果Wb的增加使得损失值增加,那么我们需要减少W和b。判断一个函数的增减性通常会使用导数来进行,导数为正,即有增加趋势。所以损失函数L(W1,W2,W3,W4,W5,W6,b1,b2,b3),我们需要对这九个值分别求偏导,才得知它的大小与正负。现在流行的训练方法是自适应法,本文中以最简单的梯度下降法来实现,权重和偏置通过一步步调整最终走到损失函数最小的点。涉及到梯度,必然要求导数,那么为了方便我们可以先把sigmoid函数的导数求出。

def der\_sigmoid(x):
    return sigmoid(x)\*(1-sigmoid(x))

超参数: 学习率 迭代次数,需要自己设定,学习率与梯度的乘积为步长。即权重和偏置每向前一步,就不需要走学习率和当前梯度的乘积这么远。学习率太高会导致迈过最优点,学习率太低则走的太慢。

def train(self,data,all_y_tr):
        epochs = 1000
        learn_rate = 0.1
        for i in range(epochs):
            for x , y_tr in zip(data,all_y_tr):
                valcell = self.feedforward(x)
                y_pre = valcell[5]
                der_L_y_pre = -2\*(y_tr-y_pre)
                der_y_pre_h1 = der_sigmoid(valcell[4])\*self.w5
                der_y_pre_h2 = der_sigmoid(valcell[4])\*self.w6
                der_h1_w1 = der_sigmoid(valcell[0])\*x[0]
                der_h1_w2 = der_sigmoid(valcell[0])\*x[1]
                der_h2_w3 = der_sigmoid(valcell[2])\*x[0]
                der_h2_w4 = der_sigmoid(valcell[2])\*x[1]
                der_y_pre_w5 = der_sigmoid(valcell[4])\*valcell[1]
                der_y_pre_w6 = der_sigmoid(valcell[4])\*valcell[3]
                der_y_pre_b3 = der_sigmoid(valcell[4])
                der_h1_b1 = der_sigmoid(valcell[0])
                der_h2_b2 = der_sigmoid(valcell[2])
#重新赋予权值和偏置
                self.w1 -= learn_rate \* der_L_y_pre \* der_y_pre_h1 \* der_h1_w1
                self.w2 -= learn_rate \* der_L_y_pre \* der_y_pre_h1 \* der_h1_w2
                self.w3 -= learn_rate \* der_L_y_pre \* der_y_pre_h2 \* der_h2_w3
                self.w4 -= learn_rate \* der_L_y_pre \* der_y_pre_h2 \* der_h2_w4
                self.w5 -= learn_rate \* der_L_y_pre \* der_y_pre_w5
                self.w6 -= learn_rate \* der_L_y_pre \* der_y_pre_w6
                self.b1 -= learn_rate \* der_L_y_pre \* der_y_pre_h1 \* der_h1_b1
                self.b2 -= learn_rate \* der_L_y_pre \* der_y_pre_h2 \* der_h2_b2
                self.b3 -= learn_rate \* der_L_y_pre \*der_y_pre_b3
              #每10步输出一次当前损失值
                if i % 10 ==0 :
                    y_pred = numpy.apply_along_axis(self.simulate,1,data)
                    loss = mse_loss (all_y_tr , y_pred)
                    print(i,loss)


文字解释:
定义一个函数叫 train ,需要一个神经网络,输入数据以及对应的输出数据为参数
.设置循环次数为1000
.学习率为0.1
.将以下运算做一个1000次的循环
… …将输入数据与输出数据打包一一对应,然后分别赋值给x和y_tr
… …所有节点值组Valcell等于feedforward函数得出的结果
… …y_pre(y预测值)为valcell的第六个值
… …损失函数对y预测求偏导数
… …y_预测对h1求编导数
… …y_预测对h2求偏导数
… …h1对w1求偏导数
以此类推
最终通过链式求导法则可以得出损失函数L对W1求偏导的值…

训练之后我们就可以用预测函数来预测

def simulate (self,x):
        h1 = x[0]\*self.w1+x[1]\*self.w2+self.b1
        h1f = sigmoid(h1)
        h2 = x[0]\*self.w3+x[1]\*self.w4+self.b2
        h2f = sigmoid(h2)
        o1 = h1f\*self.w5+h2f\*self.w6+self.b3
        of = sigmoid(o1)

整体代码

由于权重 偏置、运算、训练以及拟合都是神经网络的基本特性,因此我们把这些函数统统放入刚才定义的nerualnetwo中。所有代码如下:

import numpy

def sigmoid (x):
    return 1/(1+numpy.exp(-x))

def der\_sigmoid(x):
    return sigmoid(x)\*(1-sigmoid(x))

def mse\_loss(y_tr,y_pre):
    return((y_tr - y_pre)\*\*2).mean()


class nerualnetwo():
    def \_\_init\_\_(self):
       self.w1 = numpy.random.normal()
       self.w2 = numpy.random.normal()
       self.w3 = numpy.random.normal()
       self.w4 = numpy.random.normal()
       self.w5 = numpy.random.normal()
       self.w6 = numpy.random.normal()
       self.b1 = numpy.random.normal()
       self.b2 = numpy.random.normal()
       self.b3 = numpy.random.normal()
    def feedforward(self,x):
        h1 = x[0]\*self.w1+x[1]\*self.w2+self.b1
        h1f = sigmoid(h1)
        h2 = x[0]\*self.w3+x[1]\*self.w4+self.b2
        h2f = sigmoid(h2)
        o1 = h1f\*self.w5+h2f\*self.w6+self.b3
        of = sigmoid(o1)
        return h1,h1f,h2,h2f,o1,of
    def simulate (self,x):
        h1 = x[0]\*self.w1+x[1]\*self.w2+self.b1
        h1f = sigmoid(h1)
        h2 = x[0]\*self.w3+x[1]\*self.w4+self.b2
        h2f = sigmoid(h2)
        o1 = h1f\*self.w5+h2f\*self.w6+self.b3
        of = sigmoid(o1)
        return of
    def train(self,data,all_y_tr):
        epochs = 1000
        learn_rate = 0.1
        for i in range(epochs):
            for x , y_tr in zip(data,all_y_tr):
                valcell = self.feedforward(x)
                y_pre = valcell[5]
                der_L_y_pre = -2\*(y_tr-y_pre)
                der_y_pre_h1 = der_sigmoid(valcell[4])\*self.w5
                der_y_pre_h2 = der_sigmoid(valcell[4])\*self.w6
                der_h1_w1 = der_sigmoid(valcell[0])\*x[0]
                der_h1_w2 = der_sigmoid(valcell[0])\*x[1]
                der_h2_w3 = der_sigmoid(valcell[2])\*x[0]
                der_h2_w4 = der_sigmoid(valcell[2])\*x[1]
                der_y_pre_w5 = der_sigmoid(valcell[4])\*valcell[1]
                der_y_pre_w6 = der_sigmoid(valcell[4])\*valcell[3]
                der_y_pre_b3 = der_sigmoid(valcell[4])
                der_h1_b1 = der_sigmoid(valcell[0])
                der_h2_b2 = der_sigmoid(valcell[2])

                self.w1 -= learn_rate \* der_L_y_pre \* der_y_pre_h1 \* der_h1_w1
                self.w2 -= learn_rate \* der_L_y_pre \* der_y_pre_h1 \* der_h1_w2
                self.w3 -= learn_rate \* der_L_y_pre \* der_y_pre_h2 \* der_h2_w3
                self.w4 -= learn_rate \* der_L_y_pre \* der_y_pre_h2 \* der_h2_w4
                self.w5 -= learn_rate \* der_L_y_pre \* der_y_pre_w5
                self.w6 -= learn_rate \* der_L_y_pre \* der_y_pre_w6
                self.b1 -= learn_rate \* der_L_y_pre \* der_y_pre_h1 \* der_h1_b1
                self.b2 -= learn_rate \* der_L_y_pre \* der_y_pre_h2 \* der_h2_b2
                self.b3 -= learn_rate \* der_L_y_pre \*der_y_pre_b3
                if i % 10 ==0 :
                    y_pred = numpy.apply_along_axis(self.simulate,1,data)
                    loss = mse_loss (all_y_tr , y_pred)
                    print(i,loss)

网络定义完成后

进行训练与拟合操作

#训练网络
data = numpy.array([[-2, -1],[25, 6],[17, 4],[-15, -6]])
all_y_trues = numpy.array([1,0,0,1])
ner = nerualnetwo()

ner.train(data,all_y_trues)


#预测:结果为0.99左右


**收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。**
![img](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/1dcfcdc616f34e9197c4d1641f98088b~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MzM5MTQ5MjgwNjA=:q75.awebp?rk3s=f64ab15b&x-expires=1771321837&x-signature=froLdo9dDw067OdgTwpTc8zJGdc%3D)
![img](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/939e5129b6e04aa7893f3f672560407a~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MzM5MTQ5MjgwNjA=:q75.awebp?rk3s=f64ab15b&x-expires=1771321837&x-signature=xnNLyPdPHzNnsojSwuGcmprLsFk%3D)

**[如果你需要这些资料,可以戳这里获取](https://gitee.com/vip204888)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人**

**都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**