前言:本系列博客参考于 《机器学习算法导论》和《Python机器学习

如有侵权,敬请谅解。本书尽量用总结性的语言重述本书内容,避免侵权。

上一篇已经初步介绍了机器学习相关知识,简短介绍了机器学习的分类等等,本篇介绍其中监督学习中的分类领域下的感知器算法。


\[QAQ
\]

本篇将循序渐进的实现一个感知器,并且通过训练使其具备对鸢尾花数据集中数据进行分类的能力。

早期的机器学习

在详细讨论感知器和相关算法之前,先大体了解一下早期机器学习的起源。 为了理解大脑的工作原理以涉及人工智能系统,沃伦*麦卡洛克 和 沃尔特*皮茨 在 \(1943\)​ 年 神经元是大脑中相互连接的神经细胞,这些细胞可以处理和传递化学和电信号。

麦卡洛克-皮茨 将神经细胞描述为一个具备二进制输出的逻辑门。

树突接收多个输入信号,如果累加的信号超过某一阈(yu)值,经细胞体的整合就会生成一个输出信号,并通过轴突进行传递。

正是基于以上 \(MCP\) 模型,感知器学习法则被提出来。

感知器

Description

$MCP$ 模型出现几年后,弗兰克*罗森布拉特提出了第一个感知器学习法则。
在此感知器规则中,罗森布拉特提出了一个自学习算法,此算法可以自动
在监督学习与分类中,类似算法可用于预测样本所属的类别。


更严谨的讲,我们可以把这个问题看作一个二值分类,为了简单起见,把两类分别记为 $1$(正类别)和 $-1$(父类别)。
定义一个激活函数(activation function),
它以特定的输入值x与相应的权值向量w的线性组合作为输入。

转化成公式长这个样子:

\[\begin{array}{c}
\phi(z)=w_{1} * x_{1}+w_{2} * x_{2}+\ldots+w_{m} * x_{m}=\sum_{m=0}^{m} w_{j} x_{j}=w^{T} x \\
w=\left\{\begin{array}{c}
w_{1} \\
w_{2} \\
\cdots \\
w_{m}
\end{array}\right\}, x=\left\{\begin{array}{c}
x_{1} \\
x_{2} \\
\cdots \\
x_{m}
\end{array}\right\}
\end{array}
\]

此时,对于一个特定样本 \(x_i\) 的激活,如果其值大于预设的阈值 \(a\),我们将其划为 \(1\) 类,否则为 \(-1\) 类。在感知器算法中,激活函数(如下公式)

\[\phi(z)=w_{1} * x_{1}+w_{2} * x_{2}+\ldots+w_{m} * x_{m}=\sum_{m=0}^{m} w_{j} x_{j}=w^{T} x
\]

\(\phi(z)\) 是一个简单的分段函数

\[\phi(z)=\left\{\begin{array}{ll}
1, & \text { 若 } \mathrm{z}>=\mathrm{a} \\
-1, & \text { 其他 }
\end{array}\right.
\]

\(MCP\) 神经元和罗森布拉特阈值感知器的理念就是,

通过模拟的方式还原大脑中单个神经元的工作方式:他是否被激活。

总结的来说,罗森布拉特感知器最初的规则非常简单,可总结如下几步:

  1. 将权重初始化为 \(0\)​ 或者是一个极小的随机数
  2. 迭代所有训练样本,执行以下操作:
    1. 根据以上公式,计算输出值
    2. 更新权重

这里的输出值是指通过前面定义的单位阶跃函数预测得出的类标,而每次对权重向量中每一权重 \(w\) 的更新方式为:

\[w_{j}:=w_{j}+\Delta w_{j}
\]

对于用于更新权重的值可以通过感知器学习规则计算获得:

\[\Delta w_{j}=\eta\left(y^{(i)}-\hat{y}^{(i)}\right) x_{j}^{(i)}
\]

其中 \(η\) 是学习速率(一个介于 \(0.0\) 到 \(1.0\) 之间的常数)

\(y^{(i)}\) 是第 \(i\) 个样本的真实类标(即真实值)

\(\hat{y}^{(i)}\) 是第 \(i\) 个样本的预测类标(预测值)。需要注意的是,权重向量中的所有权重值是同时更新的,这意味着在所有的权重 \(\Delta w_{j}\) 更新前,我们无法重新计算 \(\hat{y}^{(i)}\)

具体的,对于一个二维数据集,可通过下世进行更新:

\[\begin{array}{c}
\Delta w_{0}=\eta\left(y^{(i)}-\text { output }^{(i)}\right) \\
\Delta w_{1}=\eta\left(y^{(i)}-\text { output }^{(i)}\right) x_{1}^{(i)} \\
\Delta w_{2}=\eta\left(y^{(i)}-\text { output }^{(i)}\right) x_{2}^{(i)}\\
...
\end{array}
\]

\[QAQ
\]

接下来介绍感知器的内核(推导过程),体验一下感知器规则的简洁之美(TQL

  1. 对于如下式所示的两种场景,若感知器对类标的预测正确,权重可不做更新:

    \[\begin{array}{l}
    \Delta w_{j}=\eta\left(-1^{(i)}-(-1)^{(i)}\right) x_{j}^{(i)}=0 \\
    \Delta w_{j}=\eta\left(1^{(i)}-1^{(i)}\right) x_{j}^{(i)}=0
    \end{array}
    \]
  2. 在类标预测错误的情况下,权重的值会分别趋向于正类别或者负类别的方向:

    \[\begin{array}{l}
    \Delta w_{j}=\eta\left(-1^{(i)}-1^{(i)}\right) x_{j}^{(i)}=-2 \eta x_{j}^{(i)} \\
    \Delta w_{j}=\eta\left(1^{(i)}-(-1)^{(i)}\right) x_{j}^{(i)}=2 \eta x_{j}^{(i)}
    \end{array}
    \]

解释:假定 \(x_{j}^{(i)}=0.5\) 且模型将此样本错误的分类到了 \(-1\) 类别内。在此情况下,我们应将相应的权值增 \(1\) ,以保证下次遇到此样本时使得激活函数:\(x_{j}^{(i)}=w_{j}^{(i)}\)

能将其更多的判定为正类别,这也相当于增大其值大于单位阶跃函数阈值的概率,以使得样本被判定为 \(+1\) 类:\(\Delta w_{j}^{(i)}=\left(1^{(i)}-(-1)^{(i)}\right) * 0.5^{(i)}=2 * 0.5=1\)

权重的更新与 \(x_{j}^{(i)}=0.5\) 成比例。例如另外一个样本 \(x_{j}^{(i)}=2\)

被错误的分类到 \(-1\) 类别中,我们应更大幅度的移动决策边界,以保证下次遇到此样本时能正确分类。

\[\Delta w_{j}^{(i)}=\left(1^{(i)}-(-1)^{(i)}\right) * 2^{(i)}=2 * 2=4
\]

注意:感知器收敛的前提是两个类别必须是线性可分的,且学习速率足够小。

如果两个类别无法通过一个线性决策边界进行划分,可以为模型在训练数据集上的学习迭代次数设置一个最大值,或者设置一个允许错误分类样本数量的阈值,否则,感知器训练算法将永远不停的更新权值

下图是感知器流程图,很权威的一张图。

上图说明了感知器如何接收样本 \(x\) 的输入,并将其与权值 \(w\) 进行加权以计算净输入(net_input),进而净输入被传递到激活函数(在此为单位阶跃函数),然后生成值为 \(+1\) 或者 \(-1\) 的二值输出,并以其作为样本的预测类标。在学习阶段,此输出用来计算预测的误差并更新权重。


Python实现

上述已经深入讲解感知器的规则,下面我们用代码实现它。

我们封装一个感知器类,对外提供训练和预测接口。

具体细节可见注释。

import numpy as np

class Perceptron(object):
"""
Perceptron:感知器
感知器收敛的前提是:两个类别必须是线性可分的,且学习速率必须足够小,否则感知器算法会永远不停的更新权值
""" def __init__(self, eta=0.01, n_iter=10):
"""
初始化感知器对象
:param eta: float 学习速率
:param n_iter: int 在训练集进行迭代的次数
"""
self.eta = eta
self.n_iter = n_iter def net_input(self, xi):
"""
计算净输入
:param xi: list[np.array] 一维数组数据集
:return: 计算向量的点积
向量点积的概念:
{1,2,3} * {4,5,6} = 1*4+2*5+3*6 = 32 description:
sum(i*j for i, j in zip(x, self.w_[1:])) python计算点积
"""
print(xi, end=" ")
print(self.w_[:], end=" ")
x_dot = np.dot(xi, self.w_[1:]) + self.w_[0]
print("的点积是:%d" % x_dot, end=" ")
return x_dot """ 计算类标 """
def predict(self, xi):
"""
预测方法
:param xi: list[np.array] 一维数组数据集
:return:
"""
target_pred = np.where(self.net_input(xi) >= 0.0, 1, -1)
print("预测值:%d" % target_pred, end="; ")
return target_pred def fit(self, x, y):
"""
学习、训练方法
:param x: list[np.array] 一维数组数据集
:param y: 被训练的数据集的实际结果
:return:
权值,初始化为一个零向量R的(m+1)次方,m代表数据集中纬度(特征)的数量
x.shape[1] = (100,2) 一百行2列:表示数据集中的列数即特征数 np.zeros(count) 将指定数量count初始化成元素均为0的数组 self.w_ = [ 0. 0. 0.]
""" """
按照python开发惯例,对于那些并非在初始化对象时创建但是又被对象中其他方法调用的属性,可以在后面添加一个下划线.
将权值初始化为一个零向量,x.shape[1] 是特征的维度数量,如鸢尾花数据 (150, 5) self.w_ = [0,0,0,0,0,0]
w_[0]是初始权重值0 w_[1:] 每次更新的权重值
"""
self.w_ = np.zeros(1 + x.shape[1])
print(self.w_)
# 收集每轮迭代过程中错误分类样本的数量,以便后续对感知器在训练中表现的好坏做出判定
self.errors_ = [] for _ in range(self.n_iter):
errors = 0
"""
迭代所有样本,并根据感知器规则来更新权重
"""
for x_element, target in zip(x, y):
""" 如果预测值(self.predict(x_element))和实际值(target)一致,则update为0 """
update = self.eta * (target - self.predict(x_element))
print("真实值:%d" % target)
self.w_[1:] += update * x_element
self.w_[0] += update
errors += int(update != 0.0)
self.errors_.append(errors)
return self

另外附上 《机器学习算法导论》书中的简易代码版本

import numpy as np

class Perceptron:
def fit(self, X, y):
# 学习、训练方法
m, n = X.shape
w = np.zeros((n, 1))
b = 0
done = False
while not done:
done = True
for i in range(m):
x = X[i].reshape(1, -1)
if y[i] * (x.dot(w) + b) <= 0:
w = w + y[i] * x.T
b = b + y[i]
done = False
self.w = w
self.b = b def predict(self, X):
# 预测方法
return np.sign(X.dot(self.w) + self.b)

机器学习 | 剖析感知器算法 & Python实现的更多相关文章

  1. 感知器算法--python实现

    写在前面: 参考: 1  <统计学习方法>第二章感知机[感知机的概念.误分类的判断]   http://pan.baidu.com/s/1hrTscza 2   点到面的距离 3   梯度 ...

  2. 机器学习之感知器算法原理和Python实现

    (1)感知器模型 感知器模型包含多个输入节点:X0-Xn,权重矩阵W0-Wn(其中X0和W0代表的偏置因子,一般X0=1,图中X0处应该是Xn)一个输出节点O,激活函数是sign函数. (2)感知器学 ...

  3. Stanford大学机器学习公开课(三):局部加权回归、最小二乘的概率解释、逻辑回归、感知器算法

    (一)局部加权回归 通常情况下的线性拟合不能很好地预测所有的值,因为它容易导致欠拟合(under fitting).如下图的左图.而多项式拟合能拟合所有数据,但是在预测新样本的时候又会变得很糟糕,因为 ...

  4. [置顶] 局部加权回归、最小二乘的概率解释、逻辑斯蒂回归、感知器算法——斯坦福ML公开课笔记3

    转载请注明:http://blog.csdn.net/xinzhangyanxiang/article/details/9113681 最近在看Ng的机器学习公开课,Ng的讲法循循善诱,感觉提高了不少 ...

  5. 感知器及其Python实现

    感知器是由美国计算机科学家罗森布拉特(F.Roseblatt)于1957年提出的.感知器可谓是最早的人工神经网络.单层感知器是一个具有一层神经元.采用阈值激活函数的前向网络.通过对网络权值的训练,可以 ...

  6. Perceptron Algorithm 感知器算法及其实现

    Rosenblatt于1958年发布的感知器算法,算是机器学习鼻祖级别的算法.其算法着眼于最简单的情况,即使用单个神经元.单层网络进行监督学习(目标结果已知),并且输入数据线性可分.我们可以用该算法来 ...

  7. 第三集 欠拟合与过拟合的概念、局部加权回归、logistic回归、感知器算法

    课程大纲 欠拟合的概念(非正式):数据中某些非常明显的模式没有成功的被拟合出来.如图所示,更适合这组数据的应该是而不是一条直线. 过拟合的概念(非正式):算法拟合出的结果仅仅反映了所给的特定数据的特质 ...

  8. 【2008nmj】Logistic回归二元分类感知器算法.docx

    给你一堆样本数据(xi,yi),并标上标签[0,1],让你建立模型(分类感知器二元),对于新给的测试数据进行分类. 要将两种数据分开,这是一个分类问题,建立数学模型,(x,y,z),z指示[0,1], ...

  9. 机器学习之感知器和线性回归、逻辑回归以及SVM的相互对比

    线性回归是回归模型 感知器.逻辑回归以及SVM是分类模型 线性回归:f(x)=wx+b 感知器:f(x)=sign(wx+b)其中sign是个符号函数,若wx+b>=0取+1,若wx+b< ...

  10. 感知器算法PLA

    for batch&supervised binary classfication,g≈f <=> Eout(g)≥0 achieved through Eout(g)≈Ein(g ...

随机推荐

  1. 深入了解UUID:生成、应用与优势

    一.引言 在当今数字化时代,唯一标识一个对象的能力变得越来越重要.UUID(Universally Unique Identifier,通用唯一标识符)应运而生,作为一种保证全球唯一性的标识方法,广泛 ...

  2. [python][图像切割]给定手写数字图片完成数字切割

    import torch import torch.nn as nn from torchvision import transforms from PIL import Image, ImageOp ...

  3. [ABC233G] Strongest Takahashi

    Problem Statement There is a $N \times N$ grid, with blocks on some squares. The grid is described b ...

  4. K8s 里如何优雅地使用 /dev/shm 实现容器间共享内存

    目录 1. 从 docker run 的 --shm-size 参数聊起 2. Linux 里的 /dev/shm 3. Docker 对共享内存的支持 4. K8s 里如何设置 /dev/shm 大 ...

  5. ubuntu安装opencv的正确方法

    本文介绍的是如何安装ubuntu下C++接口的opencv 1.安装准备: 1.1安装cmake sudo apt-get install cmake 1.2依赖环境 sudo apt-get ins ...

  6. MybatisPlus实现高效的多对多查询

    1.前置 事先声明一下代码中蕴含了大量的Stream和Lambda表达式操作,还不清楚的小伙伴可以去参考一下Java8新特性Stream流,而却我是用的是MybatisPlus这方面不清楚的也可以参考 ...

  7. 三维GIS渲染引擎盘点,以Cesium为核心的拓展优化

    目前,以Cesium为核心的各类产品繁多,本文将挑选一些以Cesium为核心的软件案例,为大家进行介绍. 1. CesiumJS CesiumJS相信凡是GIS行业相关人员都特别熟悉了,CesiumJ ...

  8. CentOS连接网络设置

    https://blog.csdn.net/tsundere_x/article/details/104263100  用这个 VMware提供了三种将虚拟网卡和物理网卡捆绑起来的方式,即桥接(Bri ...

  9. 如何构建一个 NodeJS 影院微服务并使用 Docker 部署

    如何构建一个 NodeJS 影院微服务并使用 Docker 部署 前言 如何构建一个 NodeJS 影院微服务并使用 Docker 部署.在这个系列中,将构建一个 NodeJS 微服务,并使用 Doc ...

  10. POJ 3537 Crosses and Crosses 博弈论 SG函数 记忆化搜索

    原题链接 题意 两人在一个长为n * 1的棋盘上下棋,两人持相同棋子,如果某人下完之后,棋盘上有三个棋子相连,则此人获胜.给出n,求是否先手必胜. 思路 一开始分析成了最少取3个,最多取5个的巴什博弈 ...