“模式识别与机器学习“ 学习笔记no.1:感知机算法及pocket算法简单代码实现

这篇笔记主要用来记录模式识别课程教授的第一个具体算法:感知机算法及在简单数据集上的编码实现.希望通过博客的方式,能将学习中遇到的问题和想法记录下来,供之后参考以及回顾.学习笔记中我尽量不看老师ppt和各种资料,尝试用自己的理解整理内容,并贴上自己编写的程序.python个人非常不熟练,代码美观度也很差,希望通过课程的学习不断提高.
section1.感知机算法简要介绍.
在本课程的学习中,感知机算法主要用来处理二分类问题.在样本空间中有若干个点,各带有标签1或-1,表示他属于哪一类.任务是学习得到一个分类面,(或求出权向量w),使得该分类面(或权向量w)对所有样本均能够正确分类,(构造了正确的分类器).
对于某一个权向量w和一个样本向量Xn及其标签Yn,我们有:
h(x)=dot(w,Xn)-threshold
作为感知机的输出.
我们可对w与Xn进行增广化.将-threshold放插入w向量开头,1插入Xn向量开头,就可用两个向量的乘积来表示感知机的输出.在上面所提到的二分类问题中,一般情况下threshold为0.
初始化权向量后,我们对数据集进行遍历.发现有分类错误的样本后,我们根据样本和他的标签值对权向量进行更新.更新公式为:
w(t+1)=w(t)+yn*xn
然后再检查下一个样本是否分类正确,以此类推,知道所有样本都分类正确,分类器学习结束.此时的 Wt+1即为最终权向量.

section2:感知机的缺陷和pocket算法
感知机算法有一个重要前提,也是其对数据集的重要要求,即数据集在样本空间上是线性可分的.存在一个分类面,能将两类样本完全分开.若不存在这个分类面,则该算法将陷入死循环.
pocket算法是在数据集线性不可分情况下做出的一种让步.既然数据集线性不可分,那我们就不在求一个能够完全分类正确的权向量,而是只需要让分错的样本数尽可能少就行.我们人为规定最大迭代次数,在迭代完这么多次之后不在迭代,算法中止.
除了初始权向量w,我们另外设置一个权向量w_hat,用来存放迭代得到的最佳分类权向量,作为最后算法的输出.每当w更新一次,我们就用更新后的w对数据集进行一次遍历,统计出错的数量,并从出错的样本当中随机取一个备用.
如果这个向量分类错的数量小于"最小分类错误数",即更新该"最小分类错误数",并用当前权向量替换w_hat.完成以上工作后,用之前随机选出的错误向量更新w(注意不是w_hat).最后返回分类错误最少的向量w_hat以及最少错分类数.下面以一个简单的例子进行示例,给定十个向量组成的数据集,对其使pocket算法求w_hat及最小错分数.

section3.pocket算法简单实现:

import numpy as np
import random

iterations = 20

x1 = np.array([1, 0.2, 0.7, 1])
x2 = np.array([1, 0.3, 0.3, 1])
x3 = np.array([1, 0.4, 0.5, 1])
x4 = np.array([1, 0.6, 0.5, 1])
x5 = np.array([1, 0.1, 0.4, 1])
x6 = np.array([1, 0.4, 0.6, -1])
x7 = np.array([1, 0.6, 0.2, -1])
x8 = np.array([1, 0.7, 0.4, -1])
x9 = np.array([1, 0.8, 0.6, -1])
x10 = np.array([1, 0.7, 0.5, -1])

dataset = [
    x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
]

w = np.array([0, 0, 0])
w_hat = np.array([0, 0, 0])

least_err_amount = len(dataset)
cnt=10

def counterror(dataset, w):
    errset = []
    count = 0
    for i in range(0, len(dataset)):
        x=dataset[i]
        if np.dot(w, dataset[i][:-1]) * dataset[i][-1] <= 0:
            errset.append(dataset[i])
            count += 1
    if(len(dataset)==0):
        rand_choice=np.zeros(4,1)
    else:
        rand_choice = random.choice(errset)
    return count, rand_choice


for i in range(0, iterations):
    for j in range(0, len(dataset) ):
        if np.dot(w, dataset[j][:-1]) * dataset[j][-1] <= 0:  # 分类错误
            w = w + dataset[j][-1] * dataset[j][:-1]  # 更新权向量
            count, choice = counterror(dataset=dataset,w= w)
            cnt=count
            if count < least_err_amount:
                w_hat=w
                least_err_amount = count
                w = w + choice[-1] * choice[:-1]
    print(w,cnt)

print(w_hat)
print(least_err_amount)

多次运行可以得到多个权向量,这也是算法行进的随机性造成的.以上代码展现了pocket算法的主要过程,对于之后随机数做数据集等一系列任务,也可以使用该代码框架,只需对数据集和循环边界做出调整.
编写程序过程中间也因为对python不熟练出现了数个很低级的失误,在排查错误的过程中也渐渐对python熟悉起来.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值