《统计学习方法》-感知机笔记和python源码

写在前面:最近正在学习机器学习,为了养成好的习惯,就按章节做了笔记并用python实现。文章中必不可少出现错误,还请大家谅解。写出来是为了激励自己努力学习,可以写出更多的东西和大家分享学习心得和体会。

感知机(perceptron

感知机是二类分类的线性分类模型,其输入为实例的特征向量,输出为实例的类别,取+1和-1。

例如,人们总是可以轻而易举的分辨出橘子和苹果,但机器怎么分辨出橘子和苹果呢?所以人们提出了感知机这个线性分类模型。就拿这个例子来说,为了成功地分辨出苹果和橘子,机器需要输入量,包括重量、光滑度、颜色和形状等特点,将这些特点组成一个向量,就是特征向量。分类结果只包括橘子和苹果,这些结果就是类别,在机器中用+1和-1来表示。

机器通过对特征向量计算,经行判断。但各个特征占的权重各不相同,比如,对苹果和橘子来说,颜色这个特征就比较明显,苹果偏向红色而橘子偏向橘黄色,所以颜色特征权重应该稍大。特种明显的权重应该较大,特征不明显的权重较小。所以在感知机中为每一个特征分配了一个权重值w。有时加上权重依然分辨不出结果,就需要加上偏置bias

初始化的感知机针对特定问题的适应度不够,错误率很高,所以需要一组已知结果的训练集,(x,y)。通过训练,改变的模型中的权重值和偏置,降低分类的错误率。

那么通过训练,该如何改变权值和偏置呢?

梯度下降法,具体的推导公式可以google。但其思想就是总是朝着负方向改变,直到找到极小值。初中数学中,对一个函数求导可以得到函数在某一点的斜率k(表示函数的增长速率,朝着正方向改变),如果我们将斜率取负号-k,那么就得到了朝着负方向增长的速率。在感知机中定义了损失函数,为了得到适当的权值和偏置,采取的策略是损失函数极小化。简单的,我们将函数的最大值比作山峰,将极小值比作谷底,解比作人。那么极小化,就是使人总是朝向谷底移动,移动的方向就是梯度的负方向。

感知机这部分之知识在神经网络中也有提到。

下面是一些相关公式。

分类模型

分离超平面

当 ,

当 , 

策略:极小化损失函数

在三维空间内,点到面距离定义为:

对于误分类数据来说:

不考虑,损失函数定义为:   

感知机学习算法

损失函数对w的梯度为:

损失函数对b的梯度为:

梯度指向使函数值增大,因此w的变化方向应是梯度的反方向,使得函数值下降。偏置b也是一样的。




其中 为学习速度。

判定条件:

框架:

输入:训练数据集,学习速度

输出:权值w和偏置b,感知机模型


(1)选取初值

(2)在训练数据集中选取数据

(3)如果,

(4)  转至(2),直至训练集中没有误分类点。

---------------------------------------------------分割线--------------------------------------------------

感知机学习算法的对偶性

将判定条件中的w展开:

其中对应的学习速率 的增量。

将判定公式展开,针对每一个 都有:


若成立,则更新:



其中的 内积,可以提前算出来内积,并以矩阵存储。称为Gram矩阵。


针对对偶性,可以对原始框架经行修改。

输入:训练数据集,学习速度

输出: ;感知机模型

(1) 初始 等于0

(2)在训练数据集中选取数据

(3)若,

则更新,

(4)转至(2),直到没有误分类点。

最后计算权值w,

----------------------------------------------分割线--------------------------------------------------

python源码

#__author__ = 'altaman'
#coding = utf-8
import numpy as np
import matplotlib.pyplot as plt


class showPicture:
    def __init__(self,data,w,b):
        self.b = b
        self.w = w
        plt.figure(1)
        plt.title('Plot 1', size=14)
        plt.xlabel('x-axis', size=14)
        plt.ylabel('y-axis', size=14)

        xData = np.linspace(0, 5, 100)
        yData = self.expression(xData)
        plt.plot(xData, yData, color='r', label='y1 data')

        plt.scatter(data[0][0],data[0][1],s=50)
        plt.scatter(data[1][0],data[1][1],s=50)
        plt.scatter(data[2][0],data[2][1],marker='x',s=50,)
        plt.savefig('2d.png',dpi=75)
    def expression(self,x):
        y = (-self.b - self.w[0]*x)/self.w[1]
        return y
    def show(self):
        plt.show()
class perceptron:
    def __init__(self,x,y,a=1):
        self.x = x
        self.y = y
        self.w = np.zeros((x.shape[1],1))
        self.b = 0
        self.a = 1
    def sign(self,w,b,x):
        result = 0
        y = np.dot(x,w)+b
        return int(y)
    def train(self):
        flag = True
        length = len(self.x)
        while flag:
            count = 0
            for i in range(length):
                tmpY = self.sign(self.w,self.b,self.x[i,:])
                if tmpY*self.y[i]<=0:
                    tmp = self.y[i]*self.a*self.x[i,:]
                    tmp = tmp.reshape(self.w.shape)
                    self.w = tmp +self.w
                    self.b = self.b + self.y[i]
                    count +=1
            if count == 0:
                flag = False
        return self.w,self.b

#原始数据
data = [[3,3],[4,3],[1,1]]
xArray = np.array([3,3,4,3,1,1])
xArray = xArray.reshape((3,2))
yArray = np.array([1,1,-1])
#感知机计算权值
myPerceptron = perceptron(x=xArray,y=yArray)
weight,bias = myPerceptron.train()
#画图
picture = showPicture(data,w=weight,b=bias)
picture.show()


实验结果如下图:


从上图可以看到,分割面即超平面。




  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值