不用框架入门与进阶深度学习(1)-手写感知器

转自公众号-AI圈终身学习,深度学习零基础入门与面试必会
致力于提供一个有情怀的集训互享开源平台,欢迎关注。


Neural Network

文集介绍

不用框架,代码手撸深度神经网络,系列文章。适合零基础入门,更适合进阶。系列文章,提前关注不迷路。适宜人群:

  • 深度学者初学者
  • 深度学习面试进阶者
  • 有意向转行AI的IT从业者
  • 对深度学习感兴趣的在校大学生

纸上得来终觉浅,文集所有代码地址:https://github.com/AIGroup-Z/deep-neural-network

这是本文集暂定要写的内容:

前言

上篇文章我们解释了什么是深度学习,以及神经网络。当然您可能觉得一头雾水,那是非常正常的。本节接着介绍神经网络的基本组成单元-感知器。

一、感知器是什么?

如图,红色加粗部分就是一个感知器:

我们把它抠出来,就变成了这个样子:

感知器为框里的部分,它不包括输入层。因此,其组成如下:

  • 权重与偏置项 一个感知器有多个输入 ( x 1 , x 2 , . . . , x n x i R ) (x_1, x_2, ...,x_n|x_i \in \mathbb R) ,每个输入有对应的权重 ( w 1 , w 2 , . . . , w n w i R ) (w_1, w_2, ...,w_n|w_i \in \mathbb R) , 此外有个偏置项 b R b \in \mathbb R
  • 激活函数 感知器有很多种激活函数可选,我们暂时选择阶跃函数f做为激活函数:

所以我们的感知器最后得到的输出结果是:
(2) y = f ( w x + b ) y=f(w\cdot x+b) \tag{2}

可能您看得有点晕,俗话说一行代码胜千言,接下来我们用感知器实现一个**与门(and)或门(or)**函数。

二、动手实现感知器

2.1 任务与数据介绍

这一节我们实现一个and函数。and函数非常简单,只有当两个输入都为1的时候,它的输出才为1,真值表如下:

x 1 x_1 x 2 x_2 y y
1 1 1
1 0 0
0 1 0
0 0 0

因此我们的训练数据如下:

# 数据准备
def get_and_training_dataset():
    x_train = [[0, 0], [0, 1], [1, 0], [1, 1]]
    y_train = [0, 0, 0, 1]
    return x_train, y_train

现在,我们有两个输入 x 1 x_1 x 2 x_2 ,最终我们获得的权重值是 w 1 = 0.2 w 2 = 0.1 b = 0.2 w_1=0.2;w_2=0.1;b=-0.2 ,这个时候它就是and感知机。我们以输入 x 1 = 1 ; x 2 = 1 x_1=1;x_2=1 进行验证,其他输入请读者自己验算,结果如下:

(3) y = f ( w x + b ) = f ( w 1 x 1 + w 2 x 2 + b ) = f ( 0.2 1 + 0.1 1 0.2 ) = f ( 0.1 ) = 1 \begin{aligned} y&=f(w\cdot x+b)\\ &=f(w_1x_1 + w_2x_2+b)\\ &=f(0.2*1+0.1*1-0.2)\\ &=f(0.1)\\ &=1\\ \end{aligned} \tag{3}

那么这个权重值是怎么来的呢?这是一种叫梯度下降的训练方式更新出来的,流程如下:

  • 第一步 初始化权重 w i w_i 和偏置项 b b 为0.
  • 第二步 迭代更新权重 w i w_i 和偏置项 b b ,规则如下:

(4) Δ b i = δ ( y y ^ ) Δ w i = δ ( y y ^ ) x i w i = w i + Δ w i b i = b i + Δ b i \begin{aligned} \Delta b_i=\delta (y- \widehat{y}) \\ \Delta w_i=\delta (y- \widehat{y})x_i \\ w_i=w_i + \Delta w_i\\ b_i=b_i + \Delta b_i \end{aligned} \tag{4}

其中 δ \delta (读delta)叫学习率, y y 为正确的输出, y ^ \widehat{y} (读y hat)为预测的输出。如果这些符号看不懂没关系,直接看下一节的代码就明白了。

为什么是这样的更新规则,我们留在下一节讲,这里您只需要知道流程即可。

2.2 代码实现

文集所有代码地址:https://github.com/AIGroup-Z/deep-neural-network

import numpy as np

class Perceptron(object):
    def __init__(self, input_feature_num, activation=None):
        self.activation = activation if activation else self.sign
        self.w = [0.0] * input_feature_num
        self.b = 0.0

    def sign(self, z):
        # 阶跃激活函数:
        # sign(z) = 1 if z > 0 
        # sign(z) = 0 otherwise
        return int(z>0)
    
    def predict(self, x):
        # 预测输出函数
        # y_hat = f(wx + b)
        return self.activation(
            np.dot(self.w, x) + self.b)
    
    def fit(self, x_train, y_train, iteration, learning_rate):
        # 训练函数
        for _ in range(iteration):
            for x, y in zip(x_train, y_train):
                y_hat = self.predict(x)
                self._update_weights(x, y_hat, y, learning_rate)
    
    def _update_weights(self, x, y_hat, y, learning_rate):
        # 权重更新, 对照公式查看
        delta = y - y_hat
        self.w = np.add(self.w,
                        np.multiply(learning_rate * delta, x))
        self.b += learning_rate * delta
    
    def __str__(self):
        return 'weights: {}\tbias: {}'.format(self.w, self.b)

模型和数据我们都有了,接下来直接训练即可获得and感知器:

# 模型训练
x_train, y_train = get_and_training_dataset()
and_p = Perceptron(2)
and_p.fit(x_train, y_train, iteration=5, learning_rate=0.1)

最终预测输出如下:

# 预测数据
print('and 感知机权重:\n', and_p, '\n')
print('1 & 1 = %d' % and_p.predict([1, 1]))
print('1 & 0 = %d' % and_p.predict([1, 0]))
print('0 & 1 = %d' % and_p.predict([0, 1]))
print('0 & 0 = %d' % and_p.predict([0, 0]))

2.3 作业:实现一个or感知机

在这里(https://github.com/AIGroup-Z/deep-neural-network) 查看代码您会发现,我们在Jupyter Notebook上留了这个作业,你可以在我们的代码基础上实现它,以确认自己已经掌握了感知机。

三、结语

本节主要介绍了神经网络中的元单元-感知机,并且使用它做了一个与门与或门,不知道您觉得这节难度如何?好消息是恭喜你走出了深度学习的第一步,后面我们会介绍更加有趣的部分,并且将感知器用于实战当中,敬请期待。

参考资料:


如果有任何问题,你不是一个人。可以在公众号首页找到我们的组队学习群。

公众号修饰图fixed

发布了89 篇原创文章 · 获赞 37 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/u012891055/article/details/85094405