百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

神经网络篇——从代码出发理解BP神经网络

csdh11 2025-02-09 11:57 8 浏览

一提到反向传播算法,我们就不自觉的想到随机梯度下降、sigmoid激活函数和最让人头大的反向传播法则的推导,即便是把反向传播神经网络的原理学了一遍,也还是一头雾水,在这里推荐一本小编认为把BP神经网络讲的最通透的教材《Python神经网络编程》。下面小编将以代码的方式带着大家一步一步实现BP神经网络,并且还会再用框架的方式实现BP网络,用来和源码作比较,认识一下TensorFlow2.0的强大。

我们首先要理清建立BP神经网络的目的,其次,确定BP神经网络的结构,简单地以一个输入层,一个隐藏层,一个输出层为例,我们来思考一下写代码的思路,然后一步一步实现。


请点击输入图片描述

在这里,我们建立BP神经网络的目的是为了做预测,我们这里用700条MG时间序列数据作为训练数据,输入维度是10,输出为1,为了方便,我们设置一个隐藏层,这个隐藏层包含10个节点,所以我们的BP神经网络的结构就是[10,10,1]。接下来,开始思考一下流程:

1、读取数据,将数据分为训练集和测试集,注意这里的数据默认都是np.array()的格式。

2、初始化BP网络,主要是确定网络结构,输入层、隐藏层、输出层个数,以及随机初始化相互连接的权值

3、调用训练方法,传入数据进行训练

    1. 前向传播
    2. 反向传播
    3. 保存模型进行测试

里面还有很多细节,我们边写边完善,整个程序的框架已经很明确了。从第一步开始,读取数据,第一步中需要注意的是,读取的数据最好进行归一化处理,一方面,这样做有助于提高预测精度,另一方面,如果使用sigmoid作为激活函数的话,它的输出是在[0,1]之间的,如果数据不进行归一化,不在[0,1]区间的数是没有办法预测的。这里我们直接调用sklearn中的最大最小归一化的方法就可以,为了方便读者理解代码,我们将import紧挨着代码:


  1. #防止数据用科学计数法输出np.set_printoptions(suppress=True)#读取数据way1 = 'Traindata11.csv'data = np.array(pd.DataFrame(pd.read_csv(way1)))# 归一化所有数据from sklearn.preprocessing import MinMaxScalerformat_minmax = MinMaxScaler()data = format_minmax.fit_transform(data)x = data[:,:-1] #需要训练的数据y = data[:,-1] #label,标签#初始化BP网络#训练网络



第二步,我们要初始化网络,确定网络的结构:



def __init__(self, ni, nh, no):

"""

构造神经网络

:param ni:输入单元数量

:param nh:隐藏单元数量

:param no:输出单元数量

"""

self.ni = ni + 1 # +1 是为了偏置节点

self.nh = nh

self.no = no

# 激活值(输出值)

self.ai = [1.0] * self.ni #这里会生成一个1*ni维,数值全为1的列表

self.ah = [1.0] * self.nh

self.ao = [1.0] * self.no

# 权重矩阵

self.wi = np.random.randn(self.ni, self.nh) #输入层到隐藏层

self.wo = np.random.randn(self.nh, self.no) # 隐藏层到输出层

# 记录权重矩阵的上次梯度

self.ci = np.zeros([self.ni, self.nh])

self.co = np.zeros([self.nh, self.no])


第三步开始训练并保存模型:



def train(self,train,lable,max_iterations=1000, N=0.5, M=0.1):

"""

训练

:param train:训练集

:param lable:标签

:param max_iterations:最大迭代次数

:param N:本次学习率

:param M:上次学习率

"""

for i in range(max_iterations): #迭代最大训练次数(epoch)

for j in range(len(train)): #训练集

inputs = train[j] #输入向量

targets = lable[j] #目标值

self.forword_propagation(inputs) #前向传播训练

error = self.back_propagation(targets, N, M) #反向传播训练,传入lable

if i % 50 == 0: #每50次输出一次误差(loss),loss函数为mse

print('Combined error', error)

winame = 'wi.npy'

woname = 'wo.npy'

np.save(winame, self.wi)

np.save(woname, self.wo)


接下来我们就要实现前向传播和反向传播的方法了,我们按照顺序从前向传播开始,前向传播用到了sigmoid作为激活函数,所以我们把sigmoid函数也一并列出:



def sigmoid(self,x):

"""

sigmoid 函数,1/(1+e^-x)

:param x:

:return:

"""

return 1.0 / (1.0 + math.exp(-x))

def forword_propagation(self, inputs):

"""

前向传播进行分类

:param inputs:输入

:return:类别

"""

if len(inputs) != self.ni - 1: #检查输入数据的维度是否和声明的一致

print('输入维度有误,请重新检查输入')

for i in range(self.ni - 1): #按顺序将n维的input映射到n个输入节点上

self.ai[i] = inputs[i]

for j in range(self.nh): #遍历隐藏层节点,每个隐藏层节点的值为n个输入节点*对应权值(输入层和隐藏层)的和

sum = 0.0

for i in range(self.ni):

sum += (self.ai[i] * self.wi[i][j])

self.ah[j] = self.sigmoid(sum) #将节点值经过sigmoid函数激活后,变为[0,1]之间的值

for k in range(self.no): #遍历输出层节点,每个输出层节点的值为n个隐藏层节点*对应权值(隐藏层和输出层)的和

sum = 0.0

for j in range(self.nh):

sum += (self.ah[j] * self.wo[j][k])

self.ao[k] = self.sigmoid(sum) ##将节点值经过sigmoid函数激活后,变为[0,1]之间的值

return self.ao #返回输出层的值


接下来是反向传播,反向传播中需要对sigmoid进行求导,为了方便我们直接写出sigmoid的求导结果,另外这里的误差函数(loss)选择mse:



def dsigmoid(self,y):

"""

sigmoid 函数的导数

:param y:

:return:

"""

return y * (1 - y)

def back_propagation(self, targets, N, M):

"""

反向传播算法

:param targets: 实例的类别

:param N: 本次学习率

:param M: 上次学习率

:return: 最终的误差平方和的一半

"""

# 计算输出层 deltas,求导数

# dE/dw[j][k] = (t[k] - ao[k]) * s'( SUM( w[j][k]*ah[j] ) ) * ah[j]

output_deltas = [0.0] * self.no #初始化输出层列表为0

for k in range(self.no):

error = targets[k] - self.ao[k] #计算输出层误差

output_deltas[k] = error * self.dsigmoid(self.ao[k]) #计算每一个节点对误差的影响大小,占比越大,影响越大

# 根据delta更新隐藏层和输出层之间的权值

for j in range(self.nh):

for k in range(self.no):

# output_deltas[k] * self.ah[j] 才是 dError/dweight[j][k]

change = output_deltas[k] * self.ah[j] #根据比例计算需要调整的值

self.wo[j][k] += N * change + M * self.co[j][k] #调整权值,调整方法有很多,例如随机梯度下降,这里只是简单写了一下

self.co[j][k] = change #保存调整的梯度

# 计算隐藏层 deltas

hidden_deltas = [0.0] * self.nh

for j in range(self.nh):

error = 0.0

for k in range(self.no):

error += output_deltas[k] * self.wo[j][k]

hidden_deltas[j] = error * self.dsigmoid(self.ah[j])

# 更新输入层权值

for i in range(self.ni):

for j in range(self.nh):

change = hidden_deltas[j] * self.ai[i]

# print 'activation',self.ai[i],'synapse',i,j,'change',change

self.wi[i][j] += N * change + M * self.ci[i][j]

self.ci[i][j] = change

# 计算MSE

error = 0.0

for k in range(len(targets)):

error += (targets[k] - self.ao[k]) ** 2

error = error/len(y)

return error


到这里就差不多实现了一个最简单的BP神经网络,不过小编强烈反对用这个代码来进行实战,这个代码只适用于理解BP神经网络。在下一篇中,我将用Tensorflow框架和Pytorch框架来实现一个通用的BP神经网络,并且解答一下为什么要使用激活函数。

不知不觉,2021年到来了,马上天就要亮了,这一篇是小编的第一篇公众号,仅以此铭记2021.1.1日凌晨。祝各位读者,元旦快乐!!!

公众号“神经网络研究所”

公众号发送“BP神经网络图书”,即可获取电子版图书。

公众号发送“BP源码”,即可获取完整版源码。

相关推荐

当iPhone X遇上 Mate 10 Pro 怎么挑?

产品:Mate10Pro(全网通)华为手机1iPhoneX一出就遇上了对手Hello!大家好我是石头这里是zol。首先来看看我手里的这个,不是装x的意思,今天好多人欢天喜地的拿到了属于自己或者属...

谁是办公高手? 六款商务平板全推荐

1超低功耗联想Thinkpad10领衔ThinkPad的名字在笔记本上依然是高曝光率,从IBM到联想,它一直以来是商务、办公领域的不二人选,然而在平板电脑大行其道的今天,ThinkPad当然也不单...

如何仅用几行代码将微信4.0公测版转换成玲珑格式?

微信4.0(玲珑版)已上架如意玲珑应用商店!!!...

音乐研发必备:理解 MIDI 协议与标准 MIDI 文件格式

1.MIDI简介...

HEIF格式可以节约50%的空间!质量会有影响吗?

关于手机1亿像素到底有没有必要,争议肯定是存在的,但无法回避的一点是随着像素的成倍增加,一张照片十几MB成了常事,这必将给本就不太宽裕的存储容量造成压力,这种压力又会转嫁到用户身上,让他们不得不花更多...

「干货分享」30个前端知识技能提升的资源网站

今天给小伙伴们分享30个前端相关学习资源网站及一些在线小工具,希望能帮助到大家。CSS相关1、css精灵牛|在线图片CSS生成工具。...

用Facebook引流Shopify独立站,如何优化Facebook商户页面?

什么是FacebookBusinessPage?FacebookBusinessPage是官方的称号,其实你可以简单理解为facebookbusinesspage就是微信公众账户,而我们...

玩转手机摄影 nubia Z9 mini新品首测

1Z9系列新品nubiaZ9mini发布会开始之前的邀请函总能透露出很多内容,或者说我们总会特意解读出很多内容。nubia此前发出的3月26日智能手机新品发布会的邀请函很显然再一次着重强调了其产品...

影院看片怕座位不好?那买个盒子在家看

着消费者对高清播放器的需求的不断增加,高清播放器的功能也在不断得到提升。以前看电影的时候相信很多人更喜欢去电影院里观看,但是有时候去电影院的人太多买不到好位子也会让不少人感到扫兴。现在随着技术的革新,...

今天你买了么?不入后悔的8款平板推荐

随着高考大战的落幕,对于广大学生朋友们来说正真的暑假终于来了!这个假期想要外出旅行或是居家畅玩,没有一款便携式全能娱乐利器的平板电脑怎么能叫放假呢?正直京东618购物季即将到来的日子,相信你也不会错过...

Cursor使用指南:释放AI编程的无限潜能

Cursor简介...

谁说轻薄本缺乏生产力?没体验过别乱说

笔记本电脑轻薄化一直是各大厂商们不断努力的方向,不过早前的轻薄笔记本电脑会受制于技术方面的限制,无法将高能耗的CPU以及显卡塞入轻薄的机身内。为了能给这些芯片散热、供电,制造商们不得不对这些芯片的功耗...

通告ImageMagick再爆核心漏洞 站长小心

目前所有版本的GraphicsMagick和ImageMagick都支持打开文件,当文件名的第一个字符为“|”,则文件名会被传递给shell程序执行,导致(可能远程)代码执行。文件打开操作位于源代码文...

《玻璃之花与坏掉的世界》再曝新宣传片

雨文冰璃发表于昨天22:56【新闻】《玻璃之花与坏掉的世界》再曝新宣传片http://comic.qq.com/a/20151122/016784.htmPONYCANYON和A-1Pictu...

7 招教你轻松搭建以图搜图系统

作者|小龙责编|胡巍巍当您听到“以图搜图”时,是否首先想到了百度、Google等搜索引擎的以图搜图功能呢?事实上,您完全可以搭建一个属于自己的以图搜图系统:自己建立图片库;自己选择一张图片到...