深度学习炼丹术 —— Taoye不讲码德,又水文了,居然写感知器这么简单的内容

深度学习模型训练之炼丹心得 最近炼丹,网络往往什么都学不到= =,不仅怀疑,看到一份英文的炼丹指南,记录一些心得。 英文链接:37 Reasons why your Neural Network is notworking 紧急手段 使用已知适用于此类数据的简单模型(例如,VGG用于图像)。 如果可以,使用标准损失。 停掉所有的花里胡哨,例如 正则化和数据增强。 如果是微调模型,请仔细检查数据... 阅读详情

手撕机器学习系列文章就暂时更新到此吧,目前已经完成了支持向量机SVM、决策树、KNN、贝叶斯、线性回归、Logistic回归,其他算法还请允许Taoye在这里先赊个账,后期有机会有时间再给大家补上。

更新至此,也是收到了部分读者的好评。虽然不多,但还是非常感谢大家的支持,希望每一位阅读过的读者都能够有所收获。

该系列文章的全部内容都是Taoye纯手打,也是参考了不少书籍以及公开资源,系列总字数在15W左右(含源码),总页数为138,后期会再慢慢填补,更多的技术文章可以来访Taoye的公众号:玩世不恭的Coder。文档可以随意传播,但注意不可修改其中的内容。

如果文章中有任何不懂的问题,都可以直接提出,Taoye看见后会第一时间回复,同时欢迎大家来此私密地向Taoye催更:玩世不恭的Coder,公众号也有Taoye的私人联系方式。有些话,Taoye只能在那里和你偷偷地说 (#`O′)

为了提高大家的阅读体验,手撕机器学习系列文章Taoye已经整理成PDF和和HTML,阅读效果都很不错,在公众号【玩世不恭的Coder】下回复【666】即可免费获取,相信大家看完后一定会有所收获

前言

后期的计划就是更新深度学习相关的内容,关于深度学习,Taoye认为最好的学习方式(入门)就是自己手动实现,包括其原理以及代码部分(能实现就尽可能的实现)。在实现的同时中要不断思考其过程,这样非常有助于正确理解深度学习。

所以,该系列文章前期会尽可能从零开始来肝深度学习,而非一上来就搬出像Tensorflow、Keras、Caffe等这种“黑盒子”。

本篇文章主要是讲解感知器,同时也是为后面神经网络的内容打好基础,该文主要包括以下三个部分的内容:

  • 到底什么是感知器啊
  • 如何基于感知器实现逻辑电路以及异或问题的抛出
  • 基于两层感知器完美解决异或问题

一、到底什么是感知器啊

我们不妨先从其表面来初步理解一下感知器吧。

“感知器,感知器”,既然它是带有一个“器”字,那么我们不妨将其看做一个“机器”?

既然是个机器,那么它能必然能代替人工来实现一些我们所需要的功能,且我们能够人为的提交某些“东西”给它,而它同时也能根据我们所提供的“东西”给我们一些反馈。

是这样的嘛???

没毛病,兄dei,就是这样的。

感知器它能接收多个输入信号,并且根据这多个信号输出一个信号。这里的输入信号可以理解成我们给感知器提供的一些“东西”,或者说是数据(相信有阅读过Taoye的手撕机器学习系列文章的读者都能轻松明白吧),而输出信号则可以理解成经过感知器这个“机器”处理过后所得到的结果。

在上图感知器中,其接收了两个输入信号 x 1 , x 2 x_1, x_2 x1​,x2​,并通过 w 1 , w 2 w_1,w_2 w1​,w2​处理过后输出一个信号 y y y。其中 w 1 , w 2 w_1,w_2 w1​,w2​表示权重,权重越高,体现的是信号的重要性就越高,而每个圆圈代表一个“节点”或者说是“神经元”。输入信号 x 1 , x 2 x_1,x_2 x1​,x2​被输入到神经元之后,会分别乘以对应的权重 w 1 , w 2 w_1,w_2 w1​,w2​,并求和得到 w 1 x 1 + w 2 x 2 w_1x_1+w_2x_2 w1​x1​+w2​x2​,假如这个总和超过某个界限 θ \theta θ的时候,此时输出信号 y = 1 y=1 y=1,否则输出信号 y = 0 y=0 y=0,这里的界限 θ \theta θ我们也可以理解成阈值或是门槛,体现的是神经元被激活的难易程度。

用数学表达上述过程如下:

y = { 0 , w 1 x 1 + w 2 x 2 ≤ θ 1 , w 1 x 1 + w 2 x 2 > θ y = \begin{cases} 0, & w_1x_1+w_2x_2 \leq \theta\\ 1, & w_1x_1+w_2x_2 > \theta \\ \end{cases} y={0,1,​w1​x1​+w2​x2​≤θw1​x1​+w2​x2​>θ​

为了方便表示,我们一般将阈值 θ \theta θ拿到左边,并替换成 b b b,此时表示的就是偏置,且 b = − θ b=-\theta b=−θ。我们可以发现,无论我们的感知器怎么对输入信号进行处理,此时的偏置前的系数都等于1。

所以,我们可以在提供输入信号 x 1 , x 2 x_1,x_2 x1​,x2​的同时,另外添加一个恒定不变的信号1,该信号用于处理偏置 b b b,且并不会对整个感知器的处理造成任何的影响,处理结果如下:

y = { 0 , w 1 x 1 + w 2 x 2 + b ≤ 0 1 , w 1 x 1 + w 2 x 2 + b > 0 y = \begin{cases} 0, & w_1x_1+w_2x_2+b \leq 0\\ 1, & w_1x_1+w_2x_2+b > 0 \\ \end{cases} y={0,1,​w1​x1​+w2​x2​+b≤0w1​x1​+w2​x2​+b>0​

通过比较 w 1 x 1 + w 2 x 2 + b w_1x_1+w_2x_2+b w1​x1​+w2​x2​+b和0的大小,我们可以来决定输出信号 y y y的值。

感知器能实现的功能有很多,不仅可以实现简单的逻辑电路(布尔运算),还可以拟合出任何的线性函数,任何线性分类或是线性回归问题都可以通过感知器来解决。

前面我们在手撕机器学习的过程中,详细讲解了线性回归和逻辑回归,其大致过程和原理其实就相当于一个感知器,只不过那个时候我们并没有把感知器的概念直接抛出来而已。

下面我们可以通过感知器来实现一下基本的逻辑电路问题

二、如何基于感知器实现逻辑电路以及异或问题的抛出

我们不妨先看看与门的实现。

与门是有两个输入和一个输出的门电路,由排列组合的相关知识我们不难知道,两个输入信号说明总共有四种输入情况,且对于门电路来讲,只有当两个输入 x 1 , x 2 x_1,x_2 x1​,x2​都等于1的时候,此时的输出信号 y y y才能等于1,其他输入情况的 y y y值都等于0。

与门电路的“真值表”如下所示:

为了更直观的了解该数据的分布,我们不妨先对这四个数据进行可视化:

可以发现,此时的四个数据完全分隔两边,我们可以用一条直线来将其进行分类。据上述感知器的判别过程,我们可以知道,主要是要决定 w 1 , w 2 , b w_1,w_2,b w1​,w2​,b具体的值来构建一个线性模型,根据这个线性模型计算出来的值 w 1 x 1 + w 2 x 2 + b w_1x_1+w_2x_2+b w1​x1​+w2​x2​+b来最终判别数据的分类。

我们可以知道,实际上,满足这样条件的 w 1 , w 2 , b w_1,w_2,b w1​,w2​,b参数的选择有无数多个。比如,我们令 ( w 1 , w 2 , b ) = ( 0.6 , 0.6 , − 0.9 ) (w_1,w_2,b) = (0.6,0.6,-0.9) (w1​,w2​,b)=(0.6,0.6,−0.9),此时的分类模型为:

y = { 0 , 0.6 x 1 + 0.6 x 2 − 0.9 ≤ 0 1 , 0.6 x 1 + 0.6 x 2 − 0.9 > 0 y = \begin{cases} 0, & 0.6x_1+0.6x_2-0.9 \leq 0\\ 1, & 0.6x_1+0.6x_2-0.9 > 0 \\ \end{cases} y={0,1,​0.6x1​+0.6x2​−0.9≤00.6x1​+0.6x2​−0.9>0​

随之,我们将与门的四组数据x_data = [[0, 0], [1, 0], [0, 1], [1, 1]]和y_label = [0, 0, 0, 1]代入到上述模型中,可以发现模型得到的结果与其对应的标签值完全一致,即分类完全正确。相关实现代码和分类结果如下:

我们可以发现,该模型的分类完全正确。

不过需要注意一点的是:该感知器模型的目的仅仅是将数据分类正确,并没有像SVM那样实现间隔最大化的需求。

为了方便读者自行运行程序,这里给出上述过程的完整的代码:

import numpy as np
from matplotlib import pyplot as plt

%matplotlib inline

"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain: 与门数据的可视化
Parameters:
    x_data:数据的属性特征
    y_label:数据属性特征所对应的标签
    w_1,w_2:权重
    b:偏执
"""
def show_result(x_data, y_label, w_1, w_2, b):
    plt.scatter(x_data[:, 0], x_data[:, 1], c = y_label, cmap = plt.cm.copper, linewidths = 10)
    line_x_1 = np.linspace(0, 1.2, 100)
    line_x_2 = (-b - w_1 * line_x_1) / w_2
    plt.plot(line_x_1, line_x_2)
    plt.show()

"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain: 阶跃函数
"""
def out(in_data):
    return 0 if in_data < 0 else 1

"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain: 模型计算结果
"""
def model(x_1, x_2, w_1, w_2, b):
    return w_1 * x_1 + w_2 * x_2 + b

if __name__ == "__main__":
    x_data = np.array([[0, 0], [1, 0], [0, 1], [1, 1]])
    y_label = np.array([0, 0, 0, 1])
    for item in x_data:
        model_result = model(item[0], item[1], 0.6, 0.6, -1.1)
        out_result = out(model_result)
        print('%d and %d = %d' % (item[0], item[1], out_result))
    show_result(x_data, y_label, 0.6, 0.6, -1.1)

上述就是一个解决与门问题感知器的全部过程。

不过,细心的读者应该会发现,我们上述感知器的 ( w 1 , w 2 , b ) (w_1,w_2,b) (w1​,w2​,b)参数是自己人为定义的,从而强行达到对数据进行分类的目的,而非通过数据训练而来。

为此,我们有必要讲解一下感知器模型的训练过程。

哎,其实这个可以说是老话长谈了,之前我们在手撕机器学习算法的时候,都有n次接触过这个问题了,无非就是得到目标优化函数,然后通过梯度下降算法或者其他优化算法来更新模型参数,最后通过训练出来的参数来检验模型的效果。

大体上就是这样,为了照顾下新来的读者,我们再来回顾下这个过程(熟悉的读者可直接跳过这个部分的内容)

对于单个数据样本来讲,前面我们不是得到了感知器模型的计算结果了嘛,即:

y ^ = { 0 , w 1 x 1 + w 2 x 2 + b ≤ 0 1 , w 1 x 1 + w 2 x 2 + b > 0 \hat{y} = \begin{cases} 0, & w_1x_1+w_2x_2+b \leq 0\\ 1, & w_1x_1+w_2x_2+b > 0 \\ \end{cases} y^​={0,1,​w1​x1​+w2​x2​+b≤0w1​x1​+w2​x2​+b>0​

注意:上述的 w 1 , w 2 , b {w_1,w_2,b} w1​,w2​,b参数并非是最终结果,而是在一开始我们需要对它们进行初始化,然后通过不断的迭代更新,最终获得满足我们需求的参数值。

这里,我们用 y ^ \hat{y} y^​表示模型的计算结果, y y y表示数据的真实标签,为了通过数学化来衡量这两者之间的差距,我们可以使用两者差的平方的 1 2 \frac{1}{2} 21​来表示两者之间差距,即:

e = 1 2 ( y ^ − y ) 2 = 1 2 ( w 1 x 1 + w 2 x 2 + b − y ) 2 = 1 2 ( w T x + b − y ) 2 \begin{aligned} e& = \frac{1}{2}(\hat{y}-y)^2 \\ & = \frac{1}{2}(w_1x_1+w_2x_2+b-y)^2 \\ & = \frac{1}{2}(w^Tx+b-y)^2 \end{aligned} e​=21​(y^​−y)2=21​(w1​x1​+w2​x2​+b−y)2=21​(wTx+b−y)2​

以上是单个样本的误差,而我们知道,在训练数据中,样本是有多个的,为此我们需要综合所有样本的误差来体现模型对整体的分类效果,我们不妨令整体误差为 E E E,则:

E = e 1 + e 2 + e 3 + . . . + e N = ∑ i = 1 N e i = 1 2 ∑ i = 1 N ( w T x i + b − y i ) 2 \begin{aligned} E & = e_1+e_2+e_3+...+e_N \\ & = \sum_{i=1}^Ne_i \\ & = \frac{1}{2}\sum_{i=1}^N(w^Tx_i+b-y_i)^2 \end{aligned} E​=e1​+e2​+e3​+...+eN​=i=1∑N​ei​=21​i=1∑N​(wTxi​+b−yi​)2​

以上就是我们最终待优化的目标函数,我们现在目的就是得到 w 1 , w 2 , b w_1,w_2,b w1​,w2​,b参数的值,使得该目标函数的误差值达到最小。为此,我们需要分别对 w w w和 b b b求偏导,求解过程如下:

∂ E ∂ w = 1 2 ∑ i = 1 N ∂ ∂ w ( w T x i + b − y i ) 2 = ∑ i = 1 N ( w T x i + b − y i ) x i \begin{aligned} \frac{\partial E}{\partial w} & =\frac{1}{2}\sum_{i=1}^N\frac{\partial}{\partial w}(w^Tx_i+b-y_i)^2 \\ & = \sum_{i=1}^N(w^Tx_i+b-y_i)x_i \end{aligned} ∂w∂E​​=21​i=1∑N​∂w∂​(wTxi​+b−yi​)2=i=1∑N​(wTxi​+b−yi​)xi​​

同理,我们对 b b b求偏导,得到如下结果:

∂ E ∂ b = 1 2 ∑ i = 1 N ∂ ∂ b ( w T x i + b − y i ) 2 = ∑ i = 1 N ( w T x i + b − y i ) \begin{aligned} \frac{\partial E}{\partial b} & =\frac{1}{2}\sum_{i=1}^N\frac{\partial}{\partial b}(w^Tx_i+b-y_i)^2 \\ & = \sum_{i=1}^N(w^Tx_i+b-y_i) \end{aligned} ∂b∂E​​=21​i=1∑N​∂b∂​(wTxi​+b−yi​)2=i=1∑N​(wTxi​+b−yi​)​

求得偏导结果之后,我们需要利用梯度下降算法对 w 1 , w 2 , b w_1,w_2,b w1​,w2​,b参数进行更新迭代,具体更新过程如下:

w n e w = w o l d − η ∂ E ∂ w   b n e w = b o l d − η ∂ E ∂ b \begin{aligned} & w^{new}=w^{old}-\eta\frac{\partial E}{\partial w}\ \\ & b^{new} = b^{old}-\eta\frac{\partial E}{\partial b} \end{aligned} ​wnew=wold−η∂w∂E​ bnew=bold−η∂b∂E​​

至于为什么以这种方式更新参数,这里Taoye就不再赘述了,不解的读者可以看看前面写过的手撕机器学习系列文章。

了解了参数的更新方式之后,我们就可以编写程序来对数据进行迭代了,从而得到一个满足实际需求的最终参数,首先定义out_result方法用于输出模型的计算结果,这里用到了一个小技巧:y = result > 0用于判断每个样本通过感知机处理后的布尔值,大于0返回true,小于0返回false;此后,y.astype(np.int)用于将布尔值重新转化为int类型,且true将转换成1,而false转化成0,读者可自行实现该过程,out_result的具体代码如下:

随后,定义train方法用于训练 w 1 , w 2 , b w_1,w_2,b w1​,w2​,b参数,训练过程如上数学表达所示,即通过梯度下降法来不断迭代更新参数,从而使得损失函数达到最小,该train方法的具体代码如下所示:

运行分类结果如下:

可以发现,总共迭代了10次,最终训练出的参数值为 ( w 1 , w 2 , b ) = ( 0.6 , 0.6 , − 0.8 ) (w_1,w_2,b)=(0.6, 0.6, -0.8) (w1​,w2​,b)=(0.6,0.6,−0.8),即得到的模型为:

y ^ = { 0 , 0.6 x 1 + 0.6 x 2 − 0.8 ≤ 0 1 , 0.6 x 1 + 0.6 x 2 − 0.8 > 0 \hat{y} = \begin{cases} 0, & 0.6x_1+0.6x_2-0.8 \leq 0\\ 1, & 0.6x_1+0.6x_2-0.8 > 0 \\ \end{cases} y^​={0,1,​0.6x1​+0.6x2​−0.8≤00.6x1​+0.6x2​−0.8>0​

将与门的四种数据代入到上述感知器模型中,并与真实标签比较可以发现分类完全正确,即模型训练成功。这里还是需要注意一点:该感知器模型的目的仅仅是将数据分类正确,并没有像SVM那样实现间隔最大化的需求。

与门实现的完整代码如下:

import numpy as np
from matplotlib import pyplot as plt

%matplotlib inline

"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain: 与门数据的可视化
Parameters:
    x_data:数据的属性特征
    y_label:数据属性特征所对应的标签
    w_1,w_2:权重
    b:偏执
"""
def show_result(x_data, y_label, w_1, w_2, b):
    plt.scatter(x_data[:, 0], x_data[:, 1], c = y_label, cmap = plt.cm.copper, linewidths = 10)
    line_x_1 = np.linspace(0, 1.2, 100)
    line_x_2 = (-b - w_1 * line_x_1) / w_2
    plt.plot(line_x_1, line_x_2)
    plt.show()

"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain: 感知器处理数据
Parameters:
    x_data:数据的属性特征
    w:权重向量
    b:偏执
Return:感知器处理之后的结果,为一个向量形式
"""
def out_result(x_data, w, b):
    result = np.matmul(x_data, np.mat(w).T) + b
    y = result > 0
    return y.astype(np.int)

"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain: 更新迭代w、b参数
Parameters:
    x_data:数据的属性特征
    y_label: 数据标签
    max_iter: 最大迭代次数
    learning_rate: 学习率
    w: 权重参数
    b:偏置参数
Return:训练完成之后最终的w,b参数
"""
def train(x_data, y_label, max_iter, learning_rate, w, b):
    for i in range(max_iter):
        result = out_result(x_data, w, b)
        delta = np.mat(y_label).T - result
        w = (w + (learning_rate * np.matmul(x_data.T, delta)).T)
        b += (learning_rate * delta).sum()
    return w, b

if __name__ == "__main__":
    x_data = np.array([[0, 0], [1, 0], [0, 1], [1, 1]])
    y_label = np.array([0, 0, 0, 1])
    w, b = train(x_data, y_label, 10, 0.1, np.array([1, 1]), 0)
    print(w, b)
    show_result(x_data, y_label, w[0, 0], w[0, 1], b)

以上就是感知器实现与门的全部过程了,读者可根据上述的思路过程自己尝试实现一下。

同理,我们可以实现逻辑电路中的与非门和或门,实现原理同上,模型训练过程也和与门一模一样,只不过给模型传递的数据有所不同,也就是说只需要更换数据即可实现与非门和或门,这里就不再过多占篇幅讲解了,具体结果如下:

可以发现,感知器训练之后同样可以实现与非门和或门。

至此,我们已经知道使用感知器可以表示与门、与非门、或门的逻辑电路。这里重要的一点是:与门、与非门、或门的感知器构造是一样的。实际上,3个门电路只有参数的值(权重和阈值)不同。也就是说,相同构造的感知机,只需通过适当地调整参数的值,就可以像“变色龙演员”表演不同的角色一样,变身为与门、与非门、或门。——摘自《深度学习入门:基于Python的理论与实现》

既然与门、与非门、或门的逻辑电路,感知器都能够实现,那么我们接下来考虑一下异或门。

异或门也被称作逻辑亦或电路,其两个输入信号只有一方为1,另一方为0的时候,输出信号才能为1,亦或门所对应的真值表如下:

我们不妨对亦或门的数据进行可视化,来观察其分布情况,可视化代码和结果如下:

通过观察可以发现,无论怎么操作,我们都无法通过一条直线将两类数据分割开来。也就是说,我们无法通过上述所分析得到的感知器模型直接运用在异或门上。

感知机的局限性就在于它只能表示由一条直线分割的空间,由直线分割而形成的空间我们称之为线性空间。但如果我们把“线性”这个限制条件去掉,我们就可以完美对异或门进行分类了,比如下面这种分类方法:

通过这种曲线分割而形成的空间我们称之为非线性空间,线性和非线性可以说是机器学习领域中的老熟人了。以上这种方式解决线性不可分问题是非常常见的,不过既然我们已经进入了深度学习领域,我们需要尽可能用“准深度学习”的方式来解决这个问题。

对此,我们进入本篇文章的第三节:基于两层感知器完美解决异或问题

三、基于两层感知器完美解决异或问题

虽然说,上面所介绍的感知器并不能解决异或问题,但是我们也无需多么失望。

感知器的强大之处在于能够实现感知器之间的叠加,也就是多层感知器,这一点对于很多问题来讲是非常有帮助的。

至于什么是感知器之间的叠加,我们暂且不要去思考这个问题,我们先以逻辑电路的角度去思考异或问题。

思路参考于:《深度学习入门:基于Python的理论与实现》

以上是与门、与非门、或门、异或门的真值表,而且我们已经讲解了如何通过感知器完美解决前三者的问题,并用代码加以实现了,然而亦或问题我们依然无法按照上述方式解决。

我们不妨换个思路来解决下亦或问题,能不能通过与门、与非门、或门中的两者甚至三者的组合形式来解决亦或问题呢???即我们现在想要实现的需求是这样的:

上图中,左子图表示的是与门、与非门、或门的符号形式,右图则表示的是目标实现的异或问题。我们能不能将左图的“三门”填入到右图中的“?”框内,从而使得最终的输出满足亦或门的结果呢???

读者思考分界线=

OK,读者短暂的思考过后,想必都已经有了答案。再不济,通过排列组合也就只有六种填入情况,总能得到满足上述题目的要求。

其实,我们可以通过如下方式来实现异或问题,即从上至下,从左至右,“?”中依次填入与非门、或门、与门即可。具体如下:

保险起见,我们不妨来确认一下如此一来是否真的就能解决异或问题。假设** x 1 、 x 2 x_1、x_2 x1​、x2​表示的是初始输入信号**,则:

  • s 1 s_1 s1​表示的是基于与非门对 x 1 、 x 2 x_1、x_2 x1​、x2​的输出
  • s 2 s_2 s2​表示的是基于或门对 x 1 、 x 2 x_1、x_2 x1​、x2​的输出
  • y y y表示的是基于与门对 s 1 , s 2 s_1,s_2 s1​,s2​的输出,也就是异或门最终的输出

通过输入 x 1 , x 2 x_1,x_2 x1​,x2​的四组信号,我们可以得到如下结果:

事实证明,我们上述模型的最终输出和异或门的输出结果如出一辙,也就是说,我们完全是可以通过与门、与非门、或门三者的组合来实现异或门的。

而且我们上面都已经实现了与门、与非门、或门,基于此,我们就能很简单实现异或门,其实现过程如下:

  1. 输入与门的四组信号,训练出满足与门的参数集 w 11 、 w 12 、 b 1 w_{11}、w_{12}、b_{1} w11​、w12​、b1​
  2. 输入与非门的四组信号,训练出满足与非门的参数集 w 21 、 w 22 、 b 2 w_{21}、w_{22}、b_{2} w21​、w22​、b2​
  3. 输入或门的四组信号,训练出满足或门的参数集 w 31 、 w 32 、 b 3 w_{31}、w_{32}、b_{3} w31​、w32​、b3​
  4. 基于上述训练出的三组参数集,按照上面的模型结构来最终得到异或门的输出

上述过程中亦或门的演示结果如下:

异或门问题解决的完整代码:

import numpy as np
from matplotlib import pyplot as plt

%matplotlib inline

"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain: 数据的可视化
Parameters:
    x_data:数据的属性特征
    y_label:数据属性特征所对应的标签
    w_1,w_2:权重
    b:偏执
"""
def show_result(x_data, y_label, w_1, w_2, b):
    plt.scatter(x_data[:, 0], x_data[:, 1], c = y_label, cmap = plt.cm.copper, linewidths = 10)
    line_x_1 = np.linspace(0, 1.2, 100)
    line_x_2 = (-b - w_1 * line_x_1) / w_2
    plt.plot(line_x_1, line_x_2)
    plt.show()

"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain: 感知器处理数据
Parameters:
    x_data:数据的属性特征
    w:权重向量
    b:偏执
Return:感知器处理之后的结果,为一个向量形式
"""
def out_result(x_data, w, b):
    result = np.matmul(x_data, np.mat(w).T) + b
    y = result > 0
    return y.astype(np.int)

"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain: 更新迭代w、b参数
Parameters:
    x_data:数据的属性特征
    y_label: 数据标签
    max_iter: 最大迭代次数
    learning_rate: 学习率
    w: 权重参数
    b:偏置参数
Return:训练完成之后最终的w,b参数
"""
def train(x_data, y_label, max_iter, learning_rate, w, b):
    for i in range(max_iter):
        result = out_result(x_data, w, b)
        delta = np.mat(y_label).T - result
        w = (w + (learning_rate * np.matmul(x_data.T, delta)).T)
        b += (learning_rate * delta).sum()
    return w, b

if __name__ == "__main__":
    x_data = np.array([[0, 0], [1, 0], [0, 1], [1, 1]])
    and_label = np.array([0, 0, 0, 1])    # 与门的输出信号
    no_and_label = np.array([1, 1, 1, 0])    # 与非门的输出信号
    or_label = np.array([0, 1, 1, 1])    # 或门的输出信号
    
    w_1, b_1 = train(x_data, and_label, 10, 0.1, np.array([0, 0]), 0)    # 感知器训练出与门的参数集
    w_2, b_2 = train(x_data, no_and_label, 10, 0.1, np.array([0, 0]), 0)    # 感知器训练出与非门的参数集
    w_3, b_3 = train(x_data, or_label, 10, 0.1, np.array([0, 0]), 0)    # 感知器训练出或门的参数集
    
    no_and_predict = out_result(x_data, w_2, b_2)    # 与非门感知器模型的结果
    or_predict = out_result(x_data, w_3, b_3)    # 或门感知器模型的结果
    xor_predict = out_result(np.concatenate((no_and_predict, or_predict), axis = 1), w_1, b_1)    # 异或门感知器模型的结果
    
    xor_label = np.array([0, 1, 1, 0])
    for index in range(xor_label.size):    # 多层感知器解决亦或问题的验证
        print("%d 亦或 %d = %d, " % (x_data[index, 0], x_data[index, 1], xor_predict[index]),
             "%d == %d?, " % (xor_label[index], xor_predict[index]),
             xor_label[index] == xor_predict[index])

感知器算是一种非常简单的算法了,相信阅读至此的读者都能很快深入理解它的构造。虽然简单,但它却是我们步入“神经网络殿堂”的阶梯,或者说是基础,这也是为什么Taoye将感知器作为深度学习开门篇的原因。

对这篇文章做个简短的总结吧:

我们首先介绍了什么是感知器,直观上看到了感知器的基本结构以及能做些什么。其次,通过感知器详细讲解了与门的实现原理,并通过数学公式化(梯度下降算法)来剖析了参数的训练过程,之后以代码形式实现了与门的逻辑电路,最终同理得到与非门和或门的实现结果。此外,在第二节的最后,我们还抛出了单层感知器无法解决亦或门的问题,从而为第三节提供“引子”。最后,我们发现其实可以通过逻辑电路组合的形式来实现异或门,在模型结构中,也就是以一种多层感知器来解决的亦或问题,最终通过代码来验证了模型的真实有效性。

以上就是本篇文章的全部内容了。

还是挺愧疚的,最近在忙其他事情,文章托更有十天了吧 (ノへ ̄、)

不过嘛,Taoye还算是挺良心的吧???

还算是讲码德的吧???给大家把感知器安排的明明白白。

后面就要正式接触到神经网络了,神经网络大体上和上述详解的感知器差不多,只不过激活函数有所不同,上述感知器用到的激活函数是阶跃函数,而在神经网络中使用到的激活函数则需要根据实际问题来进行不同的定义。此外,在神经网络中还做了一些其他的拓展。

详细内容,请见的下篇分解。

我是Taoye,爱专研,爱分享,热衷于各种技术,学习之余喜欢下象棋、听音乐、聊动漫,希望借此一亩三分地记录自己的成长过程以及生活点滴,也希望能结实更多志同道合的圈内朋友,更多内容欢迎来访微信公主号:玩世不恭的Coder。

马上就要与2021年交接了,年终总结也是时候开始准备起来了。

我们下期再见,拜拜~~

参考资料:

[1] 《深度学习入门:基于Python的理论与实现》:斋藤康毅 人民邮电出版社
[2] 零基础入门深度学习- 感知器:https://www.zybuluo.com/hanbingtao/note/433855

推荐阅读

《Machine Learning in Action》—— Taoye给你讲讲Logistic回归是咋回事
《Machine Learning in Action》—— 浅谈线性回归的那些事
《Machine Learning in Action》—— 白话贝叶斯,“恰瓜群众”应该恰好瓜还是恰坏瓜
《Machine Learning in Action》—— 女同学问Taoye,KNN应该怎么玩才能通关
《Machine Learning in Action》—— 懂的都懂,不懂的也能懂。非线性支持向量机
《Machine Learning in Action》—— hao朋友,快来玩啊,决策树呦
《Machine Learning in Action》—— Taoye给你讲讲决策树到底是支什么“鬼”
《Machine Learning in Action》—— 剖析支持向量机,优化SMO
《Machine Learning in Action》—— 剖析支持向量机,单手狂撕线性SVM

28、解码清华SSVEP基准数据集:从EEG信号到深度学习模型的实战指南 本文详细解析了清华大学SSVEP基准数据集的处理与深度学习模型构建全流程。从EEG信号预处理、数据维度变换到SSVEP分类模型设计,提供了实战代码示例和关键技巧,帮助读者掌握脑机接口领域的数据处理方法与模型优化策略。 阅读详情

相关推荐

深度学习调参(炼丹)指南来了!

Datawhale干货方向:深度学习调参,编辑:机器之心「大量的实践经验已被提炼成这份强大的深度学习模型调参指南。」——Geoffrey Hinton。众所周知,AI 的超参数决定着模型学习效果和速度。相比普通机器学习任务,深度学习需要的训练时间较长,因此调参技巧就显得尤为重要。但鉴于深度学习「炼丹」的特性,不同的模型需要不同的超参数,而每个超参的意义又不同,在不同实验中,参数和调整的方向又都...

Datawhale 1868

三相直流无刷电机(带HALL传感器)BLDC控制一

本案例选择TIM0的CH0/CH1/CH2三个通道接入三路原始hall输出信号。三路TIM_CHx(48)通过配置存入到NIP寄存器(new input pattern,3 bits)内。未完待续。

m0_69929716的博客 405

AI入门----深度学习的软硬件配置

论软硬件配置的重要性 深度学习被戏称为“炼丹”,所以用来训练深度学习的机器就被称为“炼丹炉”。古人炼丹的时候采用的原料都是混合物,使用的火分为“文火”和“武火”,也没有使用惰性气体保护。所有的物质、条件等都没有量的概念,甚至炼丹师都不知道各种物质之间发生了什么反应,所以在这样的条件下想要练出质量合格的丹药是难上加难。 我们的深度学习之所以被称为“炼丹”,其实也是有原因的。例如,一个深度学习模型中使用多少层,每一层中神经元的个数、连接方式等都可以变化,都可以得到期望的结果,但是仔细去分析这些参数,却又完全无法

wangeil007的博客 5925

Python | KS检验以及其余非参数检验的实现

Python | KS检验以及其余非参数检验的实现1 什么是KS检验2 KS检验分类?3 KS检验的Python实现3.1 检验指定的数列是否服从正态分布3.2 检验指定的两个数列是否服从相同分布4 其余的非参数检验4.1 Wilcoxon符号秩检验(t检验的非参数版本)4.2 Kruskal-Wallis H检验(方差分析的非参数版本)4.3 Mann-Whitney秩检验5 参考 1 什么是KS检验 定义:检验一个分布f(x)与理论分布g(x)【比如正态分布】是否一致,或两个观测值分布是否有显著差异的检

RUC_Lee的博客 1万+

金融行业软件测试面试题(含答案)

6、假如发现了一个BUG,跟开发本身没什么关系,涉及到理念,需求问题,如何解决?11、假如要你测试6个月期限的p2p借款产品,你应该怎么设计案例,说出测试点。17、如果京东有一个购物网页给你,你要怎么进行测试?31、我们公司自动化测试用的语言是Java,Java你不会,该怎么办?23、你们测试用的测试环境是谁给的?24、如果领导分配你的任务超出负荷,领导高估了你的能力,怎么办。26、给你一个模块测试,只有一个星期的时间你如何有效率地完成?29、如果你组长的用例写错了,但他认为是对的,你怎么处理?

crhnb的博客 916

AI大模型里经常提到的“炼丹”、“挖矿”、“蒸馏”是什么意思?

炼丹重点描述模型调优的过程。蒸馏:模型蒸馏是一种模型压缩技术,它的目标是将一个大型、复杂的模型(被称为教师模型)的知识转移到一个小型、简单的模型(被称为学生模型)中。这个过程就像蒸馏一样,通过提取教师模型的关键信息(例如,它对数据的预测概率分布),并将这些信息用于训练学生模型,从而使学生模型能够模仿教师模型的行为,达到减小模型大小和计算复杂度的目的,同时保持较高的性能。这些术语都反映了机器学习和深度学习的一些关键过程和挑战,包括模型的设计和优化、数据的处理和利用,以及模型的压缩和部署。

simoncool23的博客 2万+

EtherCAT从站协议栈---- sampleappl.c 文件解析

这个源文件实际上包含该项目的入口函数main函数。 那么如何找到入口函数呢? 可以进入debug的simulator模式,选中run to main(), 当执行完启动文件startup_cm3.s后就进入了main函数(注意在main函数之前还进入了SystemInit函数), 如下图所示: 这个main函数主要架构如下: int main(void) { HW_Init(); /*PDI(过程数据接口)初始化,这里用的是MCI接.

Jiawei_Z的博客 3068

在深度学习领域,会 “炼丹” 到底算不算本事?

在深度学习的圈子里,“炼丹” 这个词常常被大家挂在嘴边。有人调侃 “炼丹师” 是在黑暗中摸索的神秘职业,也有人质疑 “炼丹” 不过是重复调参的体力活。但实际上,深度学习会 “炼丹” 不仅是本事,更是一门含金量极高的技术活!今天,就让我们揭开 “炼丹” 的神秘面纱,看看它究竟 “神” 在哪里🧐​一、“炼丹” 究竟炼的是什么?​在深度学习中,“炼丹” 通常指的是模型调优的过程,包括超参数调整、数据预处理优化、模型结构微调等一系列操作。

2501_91695603的博客 1210

WPF中使用TreeView封装组合控件TreeView+DataGrid

wpf的功能非常强大,很多控件都是原生的,但是要使用TreeView+DataGrid的组合,就需要我们自己去封装实现。功能如上图所示, 目前基本上把常用的样式都实现了,购买源码后,可以自行修改样式。本文源码效果如下,(搞了好几天,的确有难度,所以源码也收费,便宜,赚点辛苦费)第一种:技术的选择是TreeView(也就是本文的演示)。这2个图都是第三方控件自带的,并且都是收费使用。首先说明一下,实现上面的效果,有3种方法。本文演示的是使用TreeView的实现。第二种:技术的选择是DataGrid。

故里2130 1650

复旦微实现串口在线升级BOOT.BIN

将该 demo 生成的 app(升级用)和 fsbl、最简化 bit 文件(可选)打包成 BOOT.BIN,作为 golden image 烧写在 qspi flash 偏移 0 地址开始的位置,其中最简化 bit 文件为在线升级功能提供必要的物理通道(如果不需要,可以不打包该文件),golden image 一旦发布基本不需要进行升级,由该 golden image 负责和上位机进行通信交互,完成业务 app、业务 bit 文件、uboot 以及操作系统 image 等文件在线升级,在qspi flash

wangjie36的博客 3174

深度学习炼丹术 —— 与神经网络的初次邂逅:熟悉基本结构、设计和实现

在正式介绍神经网络之前,我们先对上篇文章中的感知器内容做个简短的回顾: 我们首先介绍了什么是感知器,直观上看到了感知器的基本结构以及能做些什么。其次,通过感知器详细讲解了与门的实现原理,并通过数学公式化(梯度下降算法)来剖析了参数的训练过程,之后以代码形式实现了与门的逻辑电路,最终同理得到与非门和或门的实现结果。此外,在第二节的最后,我们还抛出了单层感知器无法解决亦或门的问题,从而为第三节提供“引子”。最后,我们发现其实可以通过逻辑电路组合的形式来实现异或门,在模型结构中,也就是以一种多层感知器来解决的亦或

Taoye | 玩世不恭的Coder 576

华为嵌入式面试题及参考答案(持续更新)

异步是指在程序执行过程中,某些任务不需要等待立即完成就可以继续执行其他任务的过程。在计算机编程中,异步通常用于处理长时间运行的操作,如文件读写、网络通信等,以避免阻塞主线程。异步处理通常涉及到回调函数、事件循环、协程或未来的概念。使用宏定义来避免命名冲突。#else#endif堆和栈是计算机程序中用于存储数据的两种不同类型的内存区域。

大模型大数据攻城狮的专栏 2483

深度学习炼丹师的养成之路之——How to subtract the mean value

今天这个文章题目的名字好啰嗦啊,其实主要是为了提醒自己要有“工匠精神”,在深度学习的修炼之路上学会有耐心,慢工出细活。如果到头来只会盲目地堆网络和试参数,这就背离了修炼的正轨了。好了,闲话不多说。今天主要写的是一个关于在transfer learning的时候,需要注意的问题。虽然是一个看似不起眼的细节,但是须知这些小小的细节有时候却能左右DL的learning过程,从而对最后的模型产生潜移默化的影

qiusuoxiaozi的博客 2536

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

什么是深度学习?刘利刚老师讲的很好

什么是深度学习? -45分钟理解深度神经网络和深度学习 刘利刚 中国科学技术大学图形与几何计算实验室 http://staff.ustc.edu.cn/~lgliu 【绪言】 近年来,人工智能(Artificial Intelligence, AI)和深度学习(Deep Learning, DL)非常火爆,在各个领域得到了广泛的应用。在笔者所从事的计算机图形学领域,...

AplusX 9280

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

深度学习炼丹师的养成之路之——Batch size/Epoch/Learning Rate的设置和学习策略

这个名字好长啊。。 但是,考虑到每一次训练都要耗费长达数日的GPU时间,每次启动训练前,细致而缜密的前期准备工作其实非常必要而且至关重要,这直接影响着数日之后的loss和最终的performance。 首先推荐的一个文章是前几日看到的,知乎上谭旭的一个回答,谈到了最近facebook的training ImageNet in one hour,比较详细地阐释了batch size的大小对收敛性

qiusuoxiaozi的博客 2万+

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

我的深度学习炼丹之路

前段时间开启深度学习炼丹之路,确实受益良多,所以从今天起,打算开一个专栏,主要总结一下自己的学习过程,后面会不定期更新……

qq_45792899的博客 391

深度学习科学炼丹

本文主要记录一些深度学习中的一些trick的使用及其原因 不定期更新 为什么激活函数更喜欢ReLU而不是tanh或者sigmoid 当我们网络比较深的时候,ReLU往往表现更好,因为ReLU只有一个拐点,而tanh/sigmoid有两个拐点(这里叫拐点不太准确),之后曲线就都趋近于平缓,这可能会导致梯度消失的问题,当输入到激活函数的值很大或很小时,会导致在反向传播的时候会导致这部分的导数很...

jose_M的博客 738

网页爬虫之页面解析

前言 With the rapid development of the Internet,越来越多的信息充斥着各大网络平台。正如《死亡笔记》中L·Lawliet这一角色所提到的大数定律,在众多繁杂的数据中必然存在着某种规律,偶然中必然包含着某种必然的发生。不管是我们提到的大数定律,还是最近火热的大数据亦或其他领域都离不开大量而又干净数据的支持,为此,网络爬虫能够满足我们的需求,即在互联网上按照我...

Taoye | 玩世不恭的Coder 4700

《Machine Learning in Action》—— 女同学问Taoye,KNN应该怎么玩才能通关

《Machine Learning in Action》—— 女同学问Taoye,KNN应该怎么玩才能通关 女同学问Taoye,KNN应该怎么玩才能通关???某问得,给这位妮子安排上! 这篇是机器学习系列文章所涉及到的第六篇文章了,前面已经介绍过了支持向量机SVM以及决策树算法,一个躲在小房间里认真阅读过的读者应该对他们都有了一定的认识,算法的过程和原理也都大致了解了。 这篇文章我们来看看K-近邻(KNN)算法,关于KNN算法,由于比较的简单,没有SVM那么复杂的公式和过程,所以会肝一篇文章来结束。 更多机

Taoye | 玩世不恭的Coder 3237

网络爬虫之页面解析

作者:玩世不恭的Coder 时间:2020-03-13 说明:本文为原创文章,未经允许不可转载,转载前请联系涛耶 网络爬虫之页面解析 文章目录网络爬虫之页面解析前言一、Beautiful Soup就该这样使用节点选择数据提取Beautiful Soup小结二、XPath解析页面节点选择数据提取XPath小结三、pyquery入门使用节点选择数据提取pyquery小结四、腾讯招聘网解析实战网页...

Taoye | 玩世不恭的Coder 1188

基于Ubuntu+Python+Tensorflow+Jupyter notebook搭建深度学习环境

基于Ubuntu+Python+Tensorflow+Jupyter notebook搭建深度学习环境 前言 如今,人工智能、深度学习等高深知识逐渐融入大家的视野,小大验证码的识别,大到无人驾驶技术等都离不开深度学习。迎合时代的脚步,跟上技术的潮流,开始学习深度学习首先需要搭建深度学习环境。搭建环境的方式也有不少,本文主要是介绍,基于Ubuntu+Python+Tensorflow+Jupyter...

Taoye | 玩世不恭的Coder 949

《Machine Learning in Action》—— 白话贝叶斯,“恰瓜群众”应该恰好瓜还是恰坏瓜

概率论,可以说是在机器学习当中扮演了一个非常重要的角色了。Taoye对概率论知识的掌握目前也还仅仅只是停留在本科期间所接触到的,而且还都已经忘了不少。快速的复习回顾一下之后,用来理解机器学习中的贝叶斯算法,还是足够的。 手撕机器学习系列文章目前已经更新了支持向量机SVM、决策树、K-近邻(KNN),现在我们来玩玩贝叶斯算法,其他机器学习系列文章可根据自己需求来食用(持续更新中): 《Machine Learning in Action》—— 剖析支持向量机,单手狂撕线性SVM: https://www.z

Taoye | 玩世不恭的Coder 858

《Machine Learning in Action》—— 剖析支持向量机,单手狂撕线性SVM

《Machine Learning in Action》—— 剖析支持向量机,单手狂撕线性SVM 前面在写NumPy文章的结尾处也有提到,本来是打算按照《机器学习实战 / Machine Learning in Action》这本书来手撕其中代码的,但由于实际原因,可能需要先手撕SVM了,这个算法感觉还是挺让人头疼,其中内部太复杂了,涉及到的数学公式太多了,也涉及到了许多陌声的名词,如:非线性约束条件下的最优化、KKT条件、拉格朗日对偶、最大间隔、最优下界、核函数等等,天书或许、可能、大概就是这样的吧。 记

Taoye | 玩世不恭的Coder 558

《Machine Learning in Action》—— Taoye给你讲讲决策树到底是支什么“鬼”

《Machine Learning in Action》—— Taoye给你讲讲决策树到底是支什么“鬼” 前面我们已经详细讲解了线性SVM以及SMO的初步优化过程,具体可看: 《Machine Learning in Action》—— 剖析支持向量机,优化SMO 《Machine Learning in Action》—— 剖析支持向量机,单手狂撕线性SVM 关于SVM非线性相关的内容,我们留着下个星期来撕 这篇文章我们先来看看决策树的内容,决策树相对于SVM来讲要简单不少,也没有多么复杂的公式。我理

Taoye | 玩世不恭的Coder 514

《Machine Learning in Action》—— hao朋友,快来玩啊,决策树呦

《Machine Learning in Action》—— 小朋友,快来玩啊,决策树呦 在上篇文章中,《Machine Learning in Action》—— Taoye给你讲讲决策树到底是支什么“鬼”主要讲述了决策树的理论内容,介绍了什么决策树,以及生成决策树时所需要优先选取的三种决策标准。有学习的过SVM,或阅读过Taoye之前写的几篇SVM内容的文章可以发现,决策树相对于SVM来讲要简单很多,没有太多且复杂的公式推导。 我们在把之前的内容稍微回顾下: 属性特征的信息增益越高,按道理来讲应当被优

Taoye | 玩世不恭的Coder 507
上一篇: 《Machine Learning in Action》—— Taoye给你讲讲Logistic回归是咋回事
下一篇: 深度学习炼丹术 —— 与神经网络的初次邂逅:熟悉基本结构、设计和实现
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值