代码实现感知机的核心算法

文章的开头我们先思考一个问题,对于给定的如下的两组数据,如何找到一条线将这两组数据一分为二?

负类数据:(1,2),(1.5,1.5),(2,1),(2.5,1),(3,0.5)

正类数据:(1,4),(1.5, 3),(2, 3),(2.5,2.5),(3,2)

 

感知机(perceptron)实质上解决的就是上面这种问题,找到一个超平面将两组数据一分为二。举个例子,我们如何训练出一个分类器来识别一封邮件是不是垃圾邮件呢。首先,我们需要两组标记好的邮件数据,一组是垃圾邮件,另外一组不是。然后我们可以将每一封邮件都抽象为一个坐标点(不一定是二维的),然后邮件分类问题就抓换为上述这种求解超平面的问题了。

废话不多说,直接讲解如何求解超平面。

感知器是一个线性分类模型,因此超平面也是线性超平面,不妨设超平面的方程为w\cdot x + b = 0;其中w是向量(w^{(1)}, ..., w^{(n)}),x为向量( x^{(1)},  ... , x^{(n)}),向量的维度为实例的特征个数。求解超平面方程其实就是求解参数w和b。

考虑一个具有两个特征的数据集,这时wx就是一个二维向量,超平面的方程可以写成w^{(1)}x^{(1)} + w^{(2)}x^{(2)} + b = 0;或者是我们更熟悉的形式ax + by + c = 0,即直线方程。

 

我们如何求这样一条直线方程呢?首先我们会参数w和b随机指定一个初始值,然后通过不断对其调整来求得最终的参数值。这个调整的过程就是机器学习的过程。那么我们如何调整参数的值呢(即确定一个学习策略,定义损失函数)?考虑初始情况,由于参数的值是随机指定的,那么肯定会有很多个数据点被误分类,我们希望每一次参数调整之后这个误分类的点的个数会越来越少,换言之我们希望误分类的点到超平面的距离的总和S越来越小。

这里直接给出点x^{(i)}到超平面的距离公式:s = \frac{1}{||w||}|w\cdot x^{(i)} + b|,其中\left \| w \right \|可以理解为向量w的长度。

接下来我们把距离公式中的|w\cdot x^{(i)} + b|的绝对值符号去掉。

我们知道,训练数据集中的每一个数据点x^{(i)}都会对应于一个y^{(i)}代表数据的类别,如果x^{(i)}是正类数据那么y^{(i)}的值就为1否则就为-1。

考虑误分类的两种情况:

1.如果x^{(i)}被超平面错误的分为正类,那么w\cdot x^{(i)} + b一定大于0(这点如果不明白可以复习一下解析几何)

由于x^{(i)}本身是负类y^{(i)} = -1;所以|w\cdot x^{(i)} + b| = -y^{(i)}(w\cdot x^{(i)} + b)

2.如果x^{(i)}被超平面错误的分为负类,那么w\cdot x^{(i)} + b一定小于0,由于x^{(i)}本身是正类y^{(i)} = 1;

所以|w\cdot x^{(i)} + b| = -y^{(i)}(w\cdot x^{(i)} + b)

综上两种情况可得:|w\cdot x^{(i)} + b| = -y^{(i)}(w\cdot x^{(i)} + b)

因此s = \frac{1}{||w||}|w\cdot x^{(i)} + b|等价于s = -\frac{1}{||w||}y^{(i)}(w\cdot x^{(i)} + b),接下来我们进一步对其进行优化。

 

w = \frac{w}{\left \| w \right \|}, b = \frac{b}{\left \| w \right \|},可得s = -y^{(i)}(w\cdot x^{(i)} + b)

 

至此我们就可以写出误分类的点到超平面的距离的总和S的表达式了,假设被误分类的数据集为M

S = -\sum_{x^{(i)}\epsilon M}y^{(i)}(w\cdot x^{(i)} + b)  可以看出S是关于w和b的函数。

 

至此,我们就将一个二分类问题转化成了一个求函数极小值的问题了。求极小值我们选择随机梯度下降法可得

w和b的更新方程为:w = w + \eta y^{(i)}x^{(i)}b = b + \eta y^{(i)}其中\eta为学习率。

至此感知机的原理部分讲解完毕,下面直接上代码。

 

bool Perceptron::update_wb() 
{    
    bool retval = true; 
    int data_num; 
    data_num = this->x.size(); 
    for (int i = 0; i < data_num; i++) 
    {       
        if (-y[i] * (this->w * this->x[i] + this->b) > 0) 
        {   
            retval = false; 
            //η取1 
            this->w = this->w + y[i]*this->x[i]; 
            this->b = this->b + y[i]; 
        }   
    }       
  
    return retval; 
}    
  
bool Perceptron::train(string file_name) 
{ 
    bool is_over = false; 
    if (!this->read_data(file_name))  
    { 
        return false; 
    } 
     
    //初始化w,b 
    this->w.resize(this->n, 1); 
    this->b = 1; 
  
    // 随机选取被误分类的点,进行更新w和b, 直到没有被误分类的 
    while (!is_over) 
    { 
        is_over = update_wb(); 
    } 
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值