《统计学习方法》学习笔记(1) 感知机数学推导过程 & C++零调库代码实现

本文介绍感知机学习算法原理及其实现过程。重点讲解了基于误分类点的损失函数定义及其更新规则,并提供了一个C++实现的例子。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

假设输入空间到输出空间的映射函数为:

f\left ( x \right ) = sign\left ( \omega \cdot x+b \right )

其中:x为n维特征向量,w为n维权重向量,b为偏置,w·x 是w和x的内积。sign是符号函数:

x,\omega \in \chi ^{n}\subseteq R^{n}

b\subseteq R

f\left ( x \right ) \in \left \{ -1,1 \right \}

sign\left ( x \right )=\left\{\begin{matrix} 1,x>=0\\ -1,x<0 \end{matrix}\right.

那么对于误分类的数据\left ( x_{i},y_{i} \right )来说:

-y_{i}\left(\omega\cdot x_{i}+b \right ) >0

该点到超平面S: \omega \cdot x+b的距离为:

-\frac{1}{\left \| \omega \right \|} y_{i} \left(\omega \cdot x_{i} +b \right )

所有误分类的点到超明面S: \omega \cdot x+b的距离和为:

-\frac{1}{\left \| \omega \right \|} \sum_{x_{i}\in M} y_{i} \left(\omega \cdot x_{i} +b \right )

其中,M为误分类点的集合。

不考虑\frac{1}{\left \| \omega \right \|},就得到了感知机学习的损失函数:\triangledown _{\omega}L\left(\omega ,b \right ) = - \sum_{x_{i}\in M}y_{i}x_{i}

L\left( \omega,b\right ) = -\sum_{x_{i}\in M}y_{i}\left( \omega \cdot x_{i} +b \right )

于是在给定训练数据集的情况下,原问题转化为求参数\omega ,b,使其为损失函数极小化问题的解:

\min_{\omega , b} L\left( \omega,b\right ) = -\sum_{x_{i}\in M}y_{i}\left( \omega \cdot x_{i} +b \right ) 

其中,M为误分类点的集合。

 感知机学习算法是误分类驱动的,具体采用随机梯度下降法。首先,任意选取一个超平面\omega_{0} ,b_{0},然后用梯度下降法不断极小化目标函数(损失函数)。在极小化的过程中不是一次性使M中的所有误分类点的梯度下降,而是一次随机选取一个误分类点使其梯度下降。

假设误分类点M的集合是固定的,那么损失函数L\left( \omega,b\right )的梯度由以下给出

\triangledown_{\omega}L(\omega ,b)=-\sum_{x_{i}\in M}y_{i}x_{i}

 \triangledown_{b}L(\omega ,b)=-\sum_{x_{i}\in M}y_{i}

 随机选取一个误分类点\left(x_{i},y_{i} \right ),对于\omega ,b进行更新:

       \omega \leftarrow \omega + \eta y_{i}x_{i}

b\leftarrow b+\eta y_{i}

其中,\eta \left(0 \le \eta \leq 1 \right )是步长,在统计学习中也称为学习率。这样,通过迭代可以期待损失函数不断减小,直到为0。

C++不调库代码如下:

#include <bits/stdc++.h>
#define vi vector<int>
#define vd vector<double>
#define vvi vector<vi>
#define vvd vector<vd>
#define ull long long unsigned int
#define MY_RAND_MAX ((RAND_MAX<<15)|RAND_MAX)
using namespace std;


//随机数
inline double my_rand(){
    return (rand()<<15)|rand();
}

inline double my_rand_double(){
    return my_rand() / double(MY_RAND_MAX);
}

inline double my_rand_double(double st,double ed){
    return my_rand_double()*(ed-st)+st;
}

//向量运算
template <class T>
T operator* (const vector<T>&AT,const vector<T>&B){
    T sum=0;
    for(ull i=0;i<AT.size()&&i<B.size();i++){
        sum+=AT[i]*B[i];
    }
    return sum;
}

template <class T>
vector<T> operator*(const vector<T>&A,T k){
    vector<T> kA(A);
    for(auto&x:kA)
        x*=k;
    return kA;
}

template <class T>
vector<T> operator*(T k,const vector<T>&A){
    vector<T> kA(A);
    for(auto&x:kA)
        x*=k;
    return kA;
}

template <class T>
vector<T>& operator += (vector<T>& res , const vector<T>& add){
    for(int i=0;i<res.size()&&i<add.size();i++){
        res[i]+=add[i];
    }
    return res;
}


//训练集数量和向量维度
int n,m;
//训练集
vvd x;
vd y;
//超平面S
double b;
vd omega;
//预测超平面S
double b_star;
vd omega_star;
//学习率
double eta=0.8;
//单步学习
void step(int pos){
    omega_star += eta * y[pos] * x[pos];
    b_star += eta * y[pos];
}


//核心函数
void run(){
    bool flag=true;
    while(flag){
        flag=false;
        for(int i=0;i<n;i++)if(y[i]*(omega_star*x[i]+b_star)<=0){
            flag=true;
            step(i);
        }
    }
}


int main()
{
    //生成训练集
    n=70;
    m=3;
    omega.resize(m);
    omega[0]=2;
    omega[1]=-0.5;
    omega[2]=-1.5;
    omega_star.resize(m);
    b=1;
    x.resize(n,vd(m));
    y.resize(n);
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++)
            x[i][j]=my_rand_double(-10,10);
    }
    for(int i=0;i<n;i++){
        double sum=omega*x[i];
        if(sum+b>0)
            y[i]=1;
        else
            y[i]=-1;
    }

    //机器学习过程
    run();

    //输出训练结果
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++)
            cout<<x[i][j]<<' ';
        cout<<endl;
        double sum=0;
        sum=omega_star*x[i]+b_star;
        cout<<y[i]<<' '<<sum<<endl;
    }



    return 0;
}

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值