【统计学习方法】感知机

前言

写这个文章也是为了督促自己把短时间学到的知识搞清楚,也把记在笔记上的,书上的,程序上的知识整合一下,据说挂深度之眼的名,后续还能领点东西,就写上了,目标还是写一个自己能给自己讲明白的学习笔记。

感知机

概念简述

(1)训练一个感知机模型,试着用我的话总结一下,就是用一条线(称为超平面二维是一条线,三维是一个面)来将平面中已知的正&负点(二分类)分隔开来的工作。

感知机的数学模型(所有超平面的集合)如下:
在这里插入图片描述

(2)那么一上来随便选定的初始超平面一定是不准的,怎么衡量好坏呢,就涉及到了损失函数,表示为:误分类点到超平面的总距离,数学表示如下:在这里插入图片描述

(3)有了初始的不准确超平面,怎么一步一步得到准确超平面呢,就涉及到了感知机的学习算法:

学习算法

① 随机梯度下降法

其实就是感知机的原始方法,给定初始学习率η,以及权值w偏置b的初值,在输入的训练数据集中随机选出一个点,看在当前超平面划分下,这个点是不是分对了,对了就不做改动,再选一个,错了就更改超平面参数,数学表示如下:

当遍历了所有的点,一个感知机模型就训练好了,这也解释了两个问题:

1.想要用感知机模型,输入训练集必须是线性可分的,要不然二维平面中输入一大堆不可分的点,用来分割的这条线可能会在训练集中来回跳动,直到最大迭代次数了,也不会把所有的点分开;

2.模型不是唯一的,因为一旦所有的点全分对了,这条线就不动了,那么正序判断到第n个点停止,与倒序判断到第一个点停止,所得的模型显然是不同的。

② 对偶形式

在我看来,对偶形式是原始形式在计算逻辑上进行优化的结果,对偶形式瞄准的是w和b在遍历所有点之后的增量,对偶形式的参数更新数学表示如下:

那么就进行如下更新:
在这里插入图片描述
最终学习结束后体现到w,b上的数学表示如下:
在这里插入图片描述
其中:
在这里插入图片描述
对偶形式的逻辑,我的理解这样的:

在原始形式下,计算的逻辑是先找错误分类点,找到了则对超平面更新,然后循环到结束。这里在找误分类点以及更新的时候都需要进行一些重复冗余的计算(相比于对偶形式)

而对偶形式,相当于是一次把所有的误分类点都找一遍,最后把所有误分类点的更新进行加和,一次性更新,另外,从α(i)的更新规则可以看出,这是一个计数形式的更新,每多一个点,就增加一个步长(学习率η),在计算上,确实省下了很多功夫。

Gram矩阵

这个矩阵的来源是用w,b判断误分类点时,需要用wx(j),而在计算更新w值时,用到了w = w + ηy(i)*x(i),也就是说涉及到了x元素的一个内积,就是下图红框中的这部分:在这里插入图片描述
那么如果提前把整个内积算出来,就省下了很多的计算成本,也就是Gram矩阵了。

程序实现

这也是我第一次接触python编程,所以程序是完全或者部分参考示例程序给出的,目的是弄懂整个编程的思想以及学会各个库的使用

编程的题目如下:

在这里插入图片描述

使用工具:PyCharm & Anaconda

自编程实现

用到的库:

import numpy as np
import matplotlib.pyplot as plt

预测函数(类):

class MyPerceptron:
	def __init__(self):
	    self.w = None
	    self.b = 0
	    self.l_rate = 1

这里w参数的维度是与输入的x的维度相关的,所以需要先定义为None,b是常数设定为0,学习率设定为1。

	def fit(self,X_train,y_train):
	    #用样本点的特征数更新初始w,如x1=(3,3)T,
	    #有两个特征,则self.w=[0,0]
	    self.w=np.zeros(X_train.shape[1])
	    i=0
	    while i<X_train.shape[0]:
	        X=X_train[i]
	        y=y_train[i]
	        # 如果y*(wx+b)≤0 说明是误判点,更新w,b
	        if y*(np.dot(self.w, X) + self.b) <= 0:
	            self.w = self.w + self.l_rate * np.dot(y, X)
	            self.b = self.b + self.l_rate * y
	            i=0 #如果是误判点,从头进行检测
	        else:
	            i+=1

这里涉及到numpy的一些基础知识,我也是边看边学的:
np.zeros()函数:定义一个全0数组,大小由输入参数指定;
np.dot()函数:返回两向量的内积(对应元素乘积后求和)或者是返回两矩阵的乘积(正常的矩阵乘法)

绘图函数:
对应语句分别加了注释

def draw(X, w, b):
    # 产生分离超平面上的两点
    X_new = np.array([[0], [6]])
    y_predict = -b - (w[0] * X_new) / w[1]   
    
    plt.plot(X[:2, 0], X[:2, 1], "g*", label="1")   # 画正实例散点
    plt.plot(X[2:, 0], X[2:, 1], "rx", label="-1")  # 画负实例散点
    plt.plot(X_new, y_predict, "b-")  # 画出超平面
    plt.axis([0, 6, 0, 6])  # 设定坐标轴范围
    plt.xlabel('x1')  # X轴标签
    plt.ylabel('x2')  # Y轴标签
    plt.title('Day2_test')  # 图片标题
    plt.legend()  # 显示图例(图例由上边"label"给出)
    plt.show()    # 显示图像

最后是主函数:

def main():
    # 构造训练数据集
    X_train=np.array([[3,3],[4,3],[1,1]])
    y_train=np.array([1,1,-1])
    # 构建感知机对象,对数据集继续训练
    perceptron=MyPerceptron()
    perceptron.fit(X_train,y_train)  # 预测函数中定义
    print(perceptron.w)
    print(perceptron.b)
    # 结果图像绘制
    draw(X_train,perceptron.w,perceptron.b)

sklearn实现

用到的库:

import numpy as np
from sklearn.linear_model import Perceptron

其中sklearn库是从Anaconda中搜索scikit-learn库得到的。

代码如下:

X_train = np.array([[3, 3], [4, 3], [1, 1]])
y = np.array([1, 1, -1])
perceptron = Perceptron(max_iter=1000, tol=1e-3)
perceptron.fit(X_train, y)
print("w:", perceptron.coef_, "\n", "b:", perceptron.intercept_, "\n", "n_iter:", perceptron.n_iter_) 
# n_iter:总的迭代次数
res = perceptron.score(X_train, y)
print("correct rate:{:.0%}".format(res))

其中涉及到的perceptron类的一些参数及方法如下:
在这里插入图片描述
上述(属性-变量)是perceptron类的输出参数;
在这里插入图片描述
上图中涉及到的参数就是在调用perceptron类时,可以传入的参数;

另注:L1&L2正则化
在这里插入图片描述

运行结果如下:
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值