如何在Python中从头开始构建自己的神经网络

目的

为了更好地理解神经网络工作原理,本文打算不借助任何第三方机器学习框架从零基础构建简单的神经网络,这有助于更深层的理解神经网络的本质。

什么是神经网络

完整的介绍神经网络需要从神经科学讲起,这也不是本文的重点,为了理解方便我们把神经网络所需要的输入输出用数学函数的方式表示。

神经网络的组成部分:
* 输入层 x
* 隐藏层(任意数量)
* 输出层 y
* 每层之间的权重w 和 偏移量 b
* 每层之间的激活函数,本文我们用sigmoid作为激活函数

下图为本文要构建的2层神经网络,值得注意的是网络层数通常不包含输入层


python构建神经网络:
class NeuralNetwork:
    def __init__(self, x, y):
        self.input      = x
        self.weights1   = np.random.rand(self.input.shape[1],4) 
        self.weights2   = np.random.rand(4,1)                 
        self.y          = y
        self.output     = np.zeros(y.shape)
训练:

该2层神经网络的的输出值为:

网络输出

从公式中可以看出,只有权重w和偏移量b影响最终的输出。
通常,权重和偏移量的正确性决定了神经网络预测的强度。 从输入数据微调权重和偏移量的过程称为训练神经网络。
神经网络训练过程中的每次迭代包括以下两个部分:
前向传播: 计算网络预测值y
反向传播: 更新权重w 和偏移量b

网络训练流程图
前向传播(Feedforward):

通过训练流程图可知,前向传播过程就是在计算网络输出的过程。我们在上述类中添加一个前向传播函数计算该过程,为了计算方便,我们把偏移量b设置为0(没有偏移量)。

class NeuralNetwork:
    def __init__(self, x, y):
        self.input      = x
        self.weights1   = np.random.rand(self.input.shape[1],4) 
        self.weights2   = np.random.rand(4,1)                 
        self.y          = y
        self.output     = np.zeros(self.y.shape)

    def feedforward(self):
        self.layer1 = sigmoid(np.dot(self.input, self.weights1))
        self.output = sigmoid(np.dot(self.layer1, self.weights2))

当然,我们怎么知道模型输出值预测的准确性(模型性能的好坏)呢?损失函数(Loss Function) 会帮助我们解决此问题。

损失函数(Loss Function):

虽然可用的损失函数很多,但是我们需要解决的问题就决定了我们应该用什么样的损失函数。在本文,我们将使用简单的均方误差作为我们的损失函数。

4.png

也就是说,均方误差仅仅是每个预测值与实际值之差的总和。 差值是平方的,因此我们测量差值的绝对值。
训练的目标是找到最佳的权重和偏移量,以最大限度地减少损失函数。

反向传播(Backpropogation):

已经得到了模型的预测误差,需要一种方法来传播误差,并更新我们的权重和偏移量。
为了知道调整权重和偏移量的适当数值,需要知道损失函数相对于权重和偏移量的导数。

回想一下微积分函数的导数就是函数的斜率,如果我们有导数,我们可以通过增加/减少来简单地更新权重和偏差(参见上图)。 这被称为梯度下降
但是,我们不能直接计算损失函数相对于权重和偏差的导数,因为损失函数的方程不包含权重和偏差。 因此,我们需要链规则来帮助我们计算它。

用于计算损失函数相对于权重的导数的链规则。 请注意,为简单起见,我们仅假设1层神经网络显示偏导数

虽然看起来比较复杂,但我们得到我们需要的东西损失函数相对于权重的导数(斜率),这样我们就可以相应地调整权重。

现在我们有了,让我们将反向传播函数添加到我们的python代码中。

class NeuralNetwork:
    def __init__(self, x, y):
        self.input      = x
        self.weights1   = np.random.rand(self.input.shape[1],4) 
        self.weights2   = np.random.rand(4,1)                 
        self.y          = y
        self.output     = np.zeros(self.y.shape)

    def feedforward(self):
        self.layer1 = sigmoid(np.dot(self.input, self.weights1))
        self.output = sigmoid(np.dot(self.layer1, self.weights2))

    def backprop(self):
        # application of the chain rule to find derivative of the loss function with respect to weights2 and weights1
        d_weights2 = np.dot(self.layer1.T, (2*(self.y - self.output) * sigmoid_derivative(self.output)))
        d_weights1 = np.dot(self.input.T,  (np.dot(2*(self.y - self.output) * sigmoid_derivative(self.output), self.weights2.T) * sigmoid_derivative(self.layer1)))

        # update the weights with the derivative (slope) of the loss function
        self.weights1 += d_weights1
        self.weights2 += d_weights2

上面我们已经完成了一个简单的2层神经网络的python代码,下面我们看一下这个网络模型是如何运作的。


我们网络模型应该学习最理想的权重使网络预测性能达到最好。首先让我们的神经网络迭代1500次,看看会发生什么。观察下面的每次迭代损失图,我们可以清楚地看到损失单调递减到最小值。 这与我们之前讨论过的梯度下降算法一致。

让我们看一下1500次迭代后神经网络的最终预测(输出)


从模型预测结果可以看出,我们的前向和反向传播算法成功地训练了神经网络,并且预测收敛于真实值。
请注意,预测和实际值之间存在细微差别。 这是应该的,因为它可以防止过拟合并允许神经网络更好地适配看不见的数据(泛化能力)。

下一步:

虽然我们实现了简单的2层神经网络,但关于神经网络和深度学习还有很多东西要学,例如:

  • 除了Sigmoid激活函数意外,还有哪些激活函数,在什么场景下使用?
  • 什么是学习率?,在网络训练过程如何使用它?
  • 什么是循环神经网络(RNN)卷积神经网络(CNN)
  • ....
结语:

虽然现在像TensorflowKeras等机器学习框架让神经网络中的建模、训练、评估等过程变得如此方便,也不需要我们理解神经网络深层的工作原理,但是作为一个打算从事用神经网络来处理数据的数据科学加来说,理解神经网络工作原理显得十分重要,我希望本文对理解神经网络有一定的帮助。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,245评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,749评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,960评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,575评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,668评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,670评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,664评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,422评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,864评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,178评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,340评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,015评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,646评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,265评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,494评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,261评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,206评论 2 352