算法学习笔记——感知机原理及其代码实现

摘要:
感知机器原理和代码实现第一部分以梯度下降结束,并将这种情况扩展到高维空间,如n维空间(对我们来说太高而无法可视化),然后F(x)函数可以用作线性分类器。最后,使用梯度下降法通过连续迭代获得最优解,以最小化损失函数。第一个容易想到的想法是,因为我们的目标是找到一个超平面方程来正确地分离两类点。那么最佳解决方案自然是将错误分类点的数量减少到0。
感知机原理及代码实现

上篇讲完梯度下降,这篇博客我们就来好好整理一下一个非常重要的二分类算法——感知机,这是一种二分类模型,当输入一系列的数据后,输出的是一个二分类变量,如0或1

1. 算法原理

1.1 知识引入

说起分类算法,博主想到的另一个算法是逻辑回归,而感知机从原理上来说和回归类算法最大的区别就是引入了几何的思想,将向量放到了高维空间上去想象。首先介绍一个概念——超平面(hyper plane),超平面就是比当前维度还少一个维度的数的集合。打个比方,如果是二维平面,那么超平面就是一维平面,也就是一条直线,形象地来想象,就好比是一条线切割了一张纸,并将一张纸上标记为1和标记为-1的点给分开来了;类比到三维空间,其超平面就是一个二维平面去切割一个立方体,好,下面开始进行原理的数学推导:

高中学数学的时候我们就知道,二维平面上的一条直线内的点可以用一般方程算法学习笔记——感知机原理及其代码实现第1张来表示,那么该二维平面中,满足算法学习笔记——感知机原理及其代码实现第2张的(x, y)表示在此一般方程上方的点,而满足算法学习笔记——感知机原理及其代码实现第3张的点则表示在此一般方程下方的点,将此情形推广到高维空间如n维空间(过高维度我们将无法直观想象),就可得到一超平面方程算法学习笔记——感知机原理及其代码实现第4张,那么推导后可知,满足等式左边>0的点自然就在该超平面的上方,<0的点就在该超平面的下方,自然,用这种方式将所有点分成了两类,因此,原问题就转换成了找到这么一个超平面将被点分成两类的问题了,将该方程写成两个向量相乘再加上一个常数项,或称截距项的形式,就可得到下式:

算法学习笔记——感知机原理及其代码实现第5张算法学习笔记——感知机原理及其代码实现第6张,则原式可转换为:算法学习笔记——感知机原理及其代码实现第7张,现令算法学习笔记——感知机原理及其代码实现第8张,并令算法学习笔记——感知机原理及其代码实现第9张,则F(x)函数可以用来做线性分类器。

1.2 推导过程

上面的式子得到之后,我们就要想,该如何求得w和b的值呢?模仿博主上两篇博客里的套路,那自然是分三步走咯,先随机设置w和b的初始值,然后写出一个损失函数(又称成本函数),最后使用梯度下降法通过不断迭代求得最优解使得损失函数最小。依照这个想法,第一个容易想到的思路就是既然我们的目标是要找到一个超平面方程正确无误地将两类点彻底分开,那么最优的解自然就是使得错误分类的点降到0个就行了呗,但是该方法有一个明显的缺点,函数值若是一个两个的话,就是分类变量了,其函数图像并不连续,因此第三步梯度下降我们没法用!于是第二个思路应运而生,既然我们要让函数连续,我们将求点的个数转换成误分类点到超平面方程的距离之和不就行了吗?那下面,我们首先推导点到直线的距离公式:

算法学习笔记——感知机原理及其代码实现第10张

 在二维直角坐标平面XoY内,有一直线方程算法学习笔记——感知机原理及其代码实现第11张,现需要求的是向量算法学习笔记——感知机原理及其代码实现第12张的模算法学习笔记——感知机原理及其代码实现第13张即d的长度:

首先推导d的公式:算法学习笔记——感知机原理及其代码实现第14张

设R点的坐标为算法学习笔记——感知机原理及其代码实现第15张,既然R点在直线上,那么必满足:算法学习笔记——感知机原理及其代码实现第16张,可推出算法学习笔记——感知机原理及其代码实现第17张

通过原方程可轻松计算出方程的斜率为(-b, a),那么与该方向垂直的向量通过点积为0的原理可算出是(a, b),如此一来,公式中的两个关键向量都已经计算出来,现在开始代入公式

算法学习笔记——感知机原理及其代码实现第18张,然后带入等式算法学习笔记——感知机原理及其代码实现第19张并整理,可得算法学习笔记——感知机原理及其代码实现第20张,由于距离比为正数,加上绝对值符号,最终等式为:算法学习笔记——感知机原理及其代码实现第21张

至此,二维平面上的推导过程告一段落,现在将其扩展至高维空间,也就是计算误分类点到超平面的距离,类比上式,可得:

设误分类点的集合为M,则损失函数L的公式为:算法学习笔记——感知机原理及其代码实现第22张

下一步为对上面的损失函数求导,分两步,求函数对w的偏导数,以及函数对b的偏导数,求出后运用梯度下降迭代即可,然而,对含有绝对值的函数求导绝非易事,因此需要通过某种方式想方设法去除绝对值符号,

 注意到,对于正确分类点来说,正类标记为1,负类标记为-1,而正类位于超平面上方,负类位于超平面下方,因此对于正确分类点,必有不等式算法学习笔记——感知机原理及其代码实现第23张,那既然所有的点只能区分为正确分类点以及误分类点,那么对于误分类点就必有不等式算法学习笔记——感知机原理及其代码实现第24张,就是一个负负得正的道理,这样一来,绝对值符号可以去除,原式就变为了:算法学习笔记——感知机原理及其代码实现第25张,我们的目标就是求这个函数的最小值即可。至此,已经可以给出两个偏导数的计算公式了:算法学习笔记——感知机原理及其代码实现第26张

下面开始简单写一下梯度下降的伪代码:

1. 选定一个系数向量和截距的初值算法学习笔记——感知机原理及其代码实现第27张

2.在训练集中进行遍历,逐个选取算法学习笔记——感知机原理及其代码实现第28张

3.遍历过程中,如果出现算法学习笔记——感知机原理及其代码实现第29张的点,那就说明该点是误分类点,这时就需要更新初值了,设步长为λ,则更新函数为:算法学习笔记——感知机原理及其代码实现第30张

4.重复2、3两步,直到整个数据集没有误分类点,即可说明线性分类器已经找到

2.代码编写

下面给出上述算法的python代码实现,并将代码封装成了一个类,这个类中定义了两个不同的梯度下降代码实现,分别为批量梯度下降以及随机梯度下降:

import numpy as np
import pandas as pd
import random
from sklearn.datasets import make_blobs

class perceptron:
    
    def __init__(self, sample_size = 200, centers = [[1,1],[3,4]], cluster_std = 0.6):
        X,Y = make_blobs(n_samples = sample_size, centers = centers, cluster_std = cluster_std, random_state = 11)
        Y[Y == 0] = -1
        self.X = X
        self.Y = Y
    
    def BGDfit(self, w, b, lam):
        #This function aims to use Batch Gradient Descent algorithm to find the most suitable function
        while True:
            x_mat = np.mat(self.X)
            tmp = np.ravel(x_mat * w + b) * self.Y
            if sum(tmp < 0) == 0:
                break
            tmp_X = np.array(self.X[tmp < 0])
            tmp_Y = np.array(self.Y[tmp < 0])
            tmp_Y_final = np.column_stack((tmp_Y, tmp_Y))
            w = w + lam * np.mat((tmp_X * tmp_Y_final).sum(axis = 0)).T
            b = b + lam * sum(tmp_Y)
        return w, b
    
    def SGDfit(self, w, b, lam):
        #This function aims to use Stochastic Gradient Descent algorithm to find the most suitable function
        missing_index = 0
        while missing_index != -1:
            missing_index = -1
            for i in range(self.X.shape[0]):
                if self.Y[i] * (np.dot(w, self.X[i]) + b) < 0:
                    missing_index = i
                    break
            if missing_index != -1:
                w = w + lam * self.Y[missing_index] * self.X[missing_index]
                b = b + lam * self.Y[missing_index]
        return w, b

3.感知机的对偶形式

3.1 原理

使用原始的感知机形式时,在遇到处理海量数据的场景时,运算速度会十分缓慢,那么,存不存在一种方式,我们可以预先将某些矩阵计算好,将其缓存起来而不必每次都进行重复的运算呢?答案是肯定的,这就是感知机的对偶形式,下面开始正式介绍:在1.2章节的时候给出过w和b的更新函数,每遇到一个误分类点,就将w进行更新:算法学习笔记——感知机原理及其代码实现第31张,将b进行更新:算法学习笔记——感知机原理及其代码实现第32张,我们可以从中总结出这样一个规律,那就是,每遇到一个误分类点一次,就在w基础上多累加一次算法学习笔记——感知机原理及其代码实现第33张,在b基础上多累加一次算法学习笔记——感知机原理及其代码实现第34张,在式子中,λ是确定的,特征值数据集是确定的,特征值对应的分类也是确定的,唯一不确定的就是我们不知道何时会遇到误分类的点,因此,不确定的变量是误分类次数,那么,感知机的对偶形式呼之欲出,我们只要维护一个误分类次数的数组,每当遇到误分类点的时候,在该数组的对应位置上进行累加即可!

设数据集中一共有n个点,并设误分类点次数向量为算法学习笔记——感知机原理及其代码实现第35张,根据上面的思路,w和b就可以写成,算法学习笔记——感知机原理及其代码实现第36张算法学习笔记——感知机原理及其代码实现第37张,我们将w的初始值设置成零向量,那么w就变成了:算法学习笔记——感知机原理及其代码实现第38张,将这个式子代入至判断某个点是否是误分类点的判别式中,如果是误分类点,那就更新a和b,具体的伪代码如下:

1.选定a和b的初始值:算法学习笔记——感知机原理及其代码实现第39张,b = 0

2.在训练集中进行遍历,逐个选取算法学习笔记——感知机原理及其代码实现第28张

3.如果发现某个点算法学习笔记——感知机原理及其代码实现第41张,那就更新a和b,算法学习笔记——感知机原理及其代码实现第42张算法学习笔记——感知机原理及其代码实现第43张

4.重复2、3步直到没有误分类点,算法停止

3.2 代码实现

下面给出感知机对偶形式的python代码实现,使用的是随机梯度下降法:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import random
from sklearn.datasets import make_blobs

sample_size = 200
centers = [[1,1], [3,4]]
X, Y = make_blobs(n_samples = sample_size, centers = centers, cluster_std = 0.6, random_state = 11)
Y[Y == 0] = -1
gram = np.array(np.mat(X) * np.mat(X).T)
a = np.zeros(X.shape[0])
b = 0
lam = 0.1
count = 0
while True:
    count += 1
    missing_index = -1
    for i in range(X.shape[0]):
        checking = Y[i] * ((a * Y * gram[i, :]).sum() + b)
        if checking <=0 :
            missing_index = i
            break
    if missing_index == -1:
        break
    a[missing_index] += lam
    b += lam * Y[missing_index]
theta = np.ravel(np.mat(a * Y) * np.mat(X))
theta, b

免责声明:文章转载自《算法学习笔记——感知机原理及其代码实现》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇JS获取浏览器信息及屏幕分辨率elk集群配置并破解x-pack下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

[Google Guava] 8-区间

原文链接 译文链接 译文:沈义扬 范例 1 List scores; 2 Iterable belowMedian =Iterables.filter(scores,Range.lessThan(median)); 3 ... 4 Range validGrades = Range.closed(1, 12); 5 for(i...

hsql整理

一、行转列的使用1、问题hive如何将a       b       1a       b       2a       b       3c       d       4c       d       5c       d       6变为:a       b       1,2,3c       d       4,5,6 2、数据test.txt...

ICP算法使用遇到的问题

这几天在学习数据关联的方法,本来想使用ICP算法进行距离测距数据的配准,但是用的过程中出现问题,配的不准,而且偏差更大了。 红色的和黄色的2维激光点进行ICP配准,但将变换矩阵和黄色进行乘之后偏差更大了。怀疑是因为两个点集只有部分数据重合,而ICP算法最好是点能一一对应。 之后使用PCL进行点集匹配测试,出现同样的问题。 于是我自己构造了一个数据,将A...

npm查看本地包版本号和远程包的版本号

npm 查看远程包 第一种方法: npm info <packageName> 第二种方法: npm view <packageName> versions --json npm查看本地安装的包版本号 npm ls <packageName> // 本地包 npm ls <packageName&...

C语言之Sleep函数

Sleep函数: 功 能: 执行挂起一段时间   用 法: unsigned sleep(unsigned seconds);   注意:   在VC中使用带上头文件#include <windows.h>,在Linux下,gcc编译器中,使用的头文件因gcc版本的不同而不同#include <unistd.h>  在VC中,Sle...

原创-PromQL语法

匹配标签值时可以是等于,也可以使用正则表达式。总共有下面几种匹配操作符: =:完全相等 !=: 不相等 =~: 正则表达式匹配 !~: 正则表达式不匹配 Prometheus的4种数据类型如下。·瞬时向量(Instant vector):一组时间序列,每个时间序列包含单个样本,它们共享相同的时间戳。也就是说,表达式的返回值中只会包含该时间序列中最新的一...