参考博客 Liam Q博客 和李航的《统计学习方法》

感知机学习旨在求出将训练数据集进行线性划分的分类超平面,为此,导入了基于误分类的损失函数,然后利用梯度下降法对损失函数进行极小化,从而求出感知机模型。感知机模型是神经网络和支持向量机的基础。下面分别从感知机学习的模型、策略和算法三个方面来介绍。

1. 感知机模型

感知机模型如下:

f(x)= sign(w*x+b)

其中,x为输入向量,sign为符号函数,括号里面大于等于0,则其值为1,括号里面小于0,则其值为-1。w为权值向量,b为偏置。求感知机模型即求模型参数w和b。感知机预测,即通过学习得到的感知机模型,对于新的输入实例给出其对应的输出类别1或者-1。

2. 感知机策略

假设训练数据集是线性可分的,感知机学习的目标就是求得一个能够将训练数据集中正负实例完全分开的分类超平面,为了找到分类超平面,即确定感知机模型中的参数w和b,需要定义一个损失函数并通过将损失函数最小化来求w和b。

这里选择的损失函数是误分类点到分类超平面S的总距离。输入空间中任一点x0到超平面S的距离为:

其中,||w||为w的L2范数。

其次,对于误分类点来说,当-y(wxi + b)>0时,yi=-1,当-yi(wxi + b)<0时,yi=+1。所以对误分类点(xi, yi)满足:

-y(wxi +b) > 0

所以误分类点(xi, yi)到分类超平面S的距离是:

3. 感知机算法

感知机学习问题转化为求解损失函数式(1)的最优化问题,最优化的方法是随机梯度下降法。感知机学习算法是误分类驱动的,具体采用随机梯度下降法。首先,任意选取一个超平面w0,b0,然后用梯度下降法不断极小化目标函数式(1)。极小化的过程不是一次使M中所有误分类点的梯度下降,而是一次随机选取一个误分类点使其梯度下降。

损失函数L(w,b)的梯度是对w和b求偏导,即:
其中,(0<<=1)是学习率,即学习的步长。
随机梯度下降法:假如你站在曲面的一点,要以最快的速度到达最低点,当然会沿着坡度最大的方向往下走(梯度的反方向)
综上,感知机学习算法如下:
算法1 感知机学习算法的原始形式

原始形式C++实现的源代码

  1 #include <iostream>
  2 #include <vector>
  3 #include <algorithm>
  4
  5 #define random(x) (rand()%(x))
  6
  7 //向量的点积
  8 double dot_product(std::vector<double>& a, std::vector<double>& b){
  9     if(a.size() != b.size()) return 0;
 10     double res = 0;
 11     for(int i = 0 ; i < a.size(); ++ i){
 12         res +=a[i]*b[i];
 13     }
 14     return res;
 15 }
 16
 17 //感知机模型类
 18 class Preception{
 19 public:
 20     Preception(int iters = 100,int learnRate = 1,double initw = 0, double initb = 0){
 21         iterators = iters;
 22         w.push_back(initw);
 23         b = initb;
 24         step = learnRate;
 25     }
 26
 27     ~Preception(){
 28         w.clear();
 29         b = 0;
 30     }
 31
 32     //训练数据
 33     //如果迭代次数完,还没有找到w和b, 则认为数据集不是线性可分的,返回false
 34     //如果找到了w和b,则认为数据集是线性可分的,返回true
 35     bool train(std::vector<std::vector<double> >& train_x,std::vector<int>& train_y){
 36         if(train_x.size() != train_y.size()) return false;
 37         initWeight(train_x[0].size());
 38
 39         for(int iter = 0 ; iter  < iterators; ++ iter){
 40             bool flag = true;
 41             for(int i = 0; i < train_x.size();){
 42                 if( (dot_product(w,train_x[i]) + b)*(double)train_y[i] <= 0){
 43                     update(train_x[i],train_y[i]);
 44                     flag = false;
 45                 }else{
 46                     ++i;
 47                 }
 48             }
 49             if(flag) return true;
 50         }
 51         return false;
 52     }
 53
 54     //批量预测数据
 55     std::vector<int> predict(std::vector<std::vector<double> >& data_x){
 56         std::vector<int> ret;
 57         for(int i = 0 ; i < data_x.size(); ++ i){
 58             ret.push_back(predict(data_x[i]));
 59         }
 60         return ret;
 61     }
 62
 63     //预测x
 64     int predict(std::vector<double>& x){
 65         return dot_product(x,w)+ b > 0 ? 1 : -1;
 66     }
 67
 68     //打印感知机模型
 69     void printPreceptronModel(){
 70         std::cout<<"原始形式感知机模型:f(x)=sign(";
 71         for(int i = 0 ; i < w.size(); ++ i){
 72             if( i ) std::cout<<"+";
 73             if(w[i]!=1) std::cout<<w[i];
 74             std::cout<<"x"<<i+1;
 75         }
 76         if(b > 0) std::cout<<"+";
 77         std::cout<<b<<")"<<std::endl;
 78     }
 79
 80 private:
 81     //初始化向量w的维数
 82     void initWeight(int size){
 83         for(int i = 1; i < size; ++ i){
 84             w.push_back(w[0]);
 85         }
 86     }
 87
 88     //更新w和b
 89     void update(std::vector<double>& x, double y){
 90         for(int i = 0 ; i < w.size(); ++ i){
 91             w[i] += step*y*x[i];
 92         }
 93         b += step*y;
 94
 95        // for(int i = 0 ; i < w.size(); ++ i)
 96        //      std::cout<<w[i]<<",";
 97        //  std::cout<<std::endl;
 98
 99       //  std::cout<<b<<std::endl;
100     }
101
102 private:
103     int iterators;          //迭代次数
104
105     //f(x) = sign(wx+b)
106     std::vector<double> w;    //注意w是向量
107     double b;
108
109     double step;  //学习速率
110 };
111
112 int main(){
113     std::vector<std::vector<double> >test_x(3);
114     test_x[0].push_back(3);test_x[0].push_back(3);
115     test_x[1].push_back(4);test_x[1].push_back(3);
116     test_x[2].push_back(1);test_x[2].push_back(1);
117     std::vector<int> test_y(3);
118     test_y[0] = 1;
119     test_y[1] = 1;
120     test_y[2] = -1;
121
122     Preception *model = new Preception();
123     model->train(test_x,test_y);
124     model->printPreceptronModel();
125 }

感知机算法的原始形式

算法2 感知机学习算法的对偶形式
对偶形式的基本想法是,将w和b表示为实例xi和标记yi的线性组合形式,通过求解其系数而求得w和b。对误分类点(xi, yi)通过
所以,感知机学习算法的对偶形式如下:

对偶形式C++实现的源代码

  1 #include <iostream>
  2 #include <vector>
  3 #include <algorithm>
  4
  5 #define random(x) (rand()%(x))
  6
  7 //向量的点积
  8 double dot_product(std::vector<double>& a, std::vector<double>& b){
  9     if(a.size() != b.size()) return 0;
 10     double res = 0;
 11     for(int i = 0 ; i < a.size(); ++ i){
 12         res +=a[i]*b[i];
 13     }
 14     return res;
 15 }
 16
 17 //感知机模型类
 18 class Preception{
 19 public:
 20     Preception(int iters = 100,int learnRate = 1,double initw = 0, double initb = 0){
 21         iterators = iters;
 22         a.push_back(initw);
 23         b = initb;
 24         step = learnRate;
 25     }
 26
 27     ~Preception(){
 28         a.clear();
 29         b = 0;
 30     }
 31
 32     //训练数据
 33     //如果迭代次数完,还没有找到a和b, 则认为数据集不是线性可分的,返回false
 34     //如果找到了a和b,则认为数据集是线性可分的,返回true
 35     bool train(std::vector<std::vector<double> >& train_x,std::vector<int>& train_y){
 36         if(train_x.size() != train_y.size()) return false;
 37         initWeight(train_x.size());
 38         std::vector<std::vector<double> > gram = productGram(train_x);
 39         for(int i = 0 ; i < a.size(); ++ i){
 40             int iter = 0;
 41             while(iter < iterators){
 42                 double sum = b;
 43                 for(int j = 0; j < a.size(); ++ j){
 44                     sum += a[j]*train_y[j]*gram[j][i];
 45                 }
 46                 sum *= train_y[i];
 47                 if(sum <= 0) update(i,train_y[i]);
 48                 else break;
 49                 ++iter;
 50             }
 51             if(iter >= iterators) return false;
 52         }
 53         return true;
 54     }
 55
 56     //批量预测数据
 57     std::vector<int> predict(std::vector<std::vector<double> >& data_x){
 58         std::vector<int> ret;
 59         for(int i = 0 ; i < data_x.size(); ++ i){
 60             ret.push_back(predict(data_x[i]));
 61         }
 62         return ret;
 63     }
 64
 65     //预测x
 66     int predict(std::vector<double>& x){
 67         return dot_product(x,a)+ b > 0 ? 1 : -1;
 68     }
 69
 70     //打印感知机模型
 71     void printPreceptronModel(){
 72         std::cout<<"原始形式感知机模型:f(x)=sign(";
 73         for(int i = 0 ; i < a.size(); ++ i){
 74             if( i ) std::cout<<"+";
 75             if(a[i]!=1) std::cout<<a[i];
 76             std::cout<<"x"<<i+1;
 77         }
 78         if(b > 0) std::cout<<"+";
 79         std::cout<<b<<")"<<std::endl;
 80     }
 81
 82 private:
 83     //初始化向量a的维数
 84     void initWeight(int size){
 85         for(int i = 1; i < size; ++ i){
 86             a.push_back(a[0]);
 87         }
 88     }
 89
 90     //生成Gram矩阵
 91     std::vector<std::vector<double> > productGram(std::vector<std::vector<double> >& train_x){
 92         int n = train_x.size();
 93         std::vector<std::vector<double> > gram(n, std::vector<double>(n,0));
 94         for(int i = 0 ; i < n ; ++ i){
 95             for(int j = 0 ; j  < n; ++ j){
 96                 gram[i][j] = dot_product(train_x[i], train_x[j]);
 97             }
 98         }
 99         return gram;
100     }
101
102     //更新w和b
103     void update(int index, double y){
104         a[index] +=1;
105         b += step*y;
106     }
107
108 private:
109     int iterators;          //迭代次数
110
111     std::vector<double> a;    //注意w是向量
112     double b;
113
114     double step;  //学习速率
115 };
116
117 int main(){
118     std::vector<std::vector<double> >test_x(3);
119     test_x[0].push_back(3);test_x[0].push_back(3);
120     test_x[1].push_back(4);test_x[1].push_back(3);
121     test_x[2].push_back(1);test_x[2].push_back(1);
122     std::vector<int> test_y(3);
123     test_y[0] = 1;
124     test_y[1] = 1;
125     test_y[2] = -1;
126
127     Preception *model = new Preception();
128     model->train(test_x,test_y);
129     model->printPreceptronModel();
130 }

感知机学习算法的对偶形式

转载于:https://www.cnblogs.com/xiongqiangcs/p/4185648.html

统计学习方法 --- 感知机模型原理及c++实现相关推荐

  1. 统计学习方法|感知机原理剖析及实现

    欢迎直接到我的博客查看最近文章:www.pkudodo.com.更新会比较快,评论回复我也能比较快看见,排版也会更好一点. 原始blog链接: http://www.pkudodo.com/2018/ ...

  2. 统计学习方法|支持向量机(SVM)原理剖析及实现

    欢迎直接到我的博客查看最近文章:www.pkudodo.com.更新会比较快,评论回复我也能比较快看见,排版也会更好一点. 原始blog链接: http://www.pkudodo.com/2018/ ...

  3. 统计学习方法|K近邻原理剖析及实现

    欢迎直接到我的博客查看最近文章:www.pkudodo.com.更新会比较快,评论回复我也能比较快看见,排版也会更好一点. 原始blog链接: http://www.pkudodo.com/2018/ ...

  4. 统计学习方法感知机(附简单模型代码)

    1. 感知机模型 输入为实例的特征向量, 输出为实例的类别, 取+1和-1:感知机对应于输入空间中将实例划分为正负两类的分离超平面, 属于判别模型:导入基于误分类的损失函数:利用梯度下降法对损失函数进 ...

  5. 统计学习方法——感知机

    1. 感知机原理 感知机是一个二类分类模型,输入为实例的特征向量,输出为实例的类别,取值为+1和-1. 定义1-1:数据的线性可分性 假设训练数据集是线性可分的,感知机学习的目标是求得一个能够将训练数 ...

  6. 统计学习方法-感知机概括和补充

    前言 <统计学习方法>第二版出了有段时间了,最近得空可以拜读一下.之前看第一版的时候还是一年多以前,那个时候看的懵懵懂懂的,很吃力.希望这一次能够有所收获,能够收获新的东西,这些文章只是用 ...

  7. 【统计学习方法】模型评估与模型选择

    一.训练误差与测试误差 首先引入误差的概念,误差(error)是指:学习器的实际预测输出与样本的真实输出之间的差异.类似地,学习器在训练集上的误差被称之为训练误差(training error)或者经 ...

  8. 李航统计学习方法----感知机章节学习笔记以及python代码

    目录 1 感知机模型 2 感知机学习策略 2.1 数据集的线性可分性 2.2 感知机学习策略 3 感知机学习算法 3.1 感知机学习算法的原始形式 3.2 感知机算法的对偶形式 4 感知机算法pyth ...

  9. 统计学习方法-最大熵模型

    最大熵模型(maximum entropy model)是由最大熵原理推导而来的. 一.最大熵原理 最大熵原理认为,学习概率模型的时候,在所有可能的概率模型分布中,熵最大的模型是最好的模型.模型通常要 ...

最新文章

  1. 施工日志管理软件app_康智颐app下载-康智颐客户端下载v1.4.9 安卓官方版
  2. tomcat linux dump,Linux下Tomcat常用命令与配置
  3. Oracle-内存管理解读
  4. 肇庆配送启动运营 谋定·农业大健康-李喜贵:共筑湾区“菜篮子”
  5. Android事件机制详解
  6. 程序员的职业选择:打工者、独立开发者、创业者
  7. 前端学习(2461):打包发布
  8. 野火开发版屏幕_鸿蒙2.0手机开发者版发布,华为多数自研设备明年升级鸿蒙
  9. mongodb----副本集搭建及故障自动切换
  10. 数据科学和人工智能技术笔记 八、特征选择
  11. C# using 使用方法
  12. gitlab 修改存储为mysql_gitlab仓库存储位置的修改方法
  13. 数据库服务器禁用虚拟内存,SQLServer因为OS虚拟内存不足而hang住异常解决-锁定内存页 (LPIM)...
  14. 1006 小明与隔壁老王之间不得不说的故事(简单)
  15. 数据结构与算法之美-队列
  16. 【音视频】实操YUV与RGB互转(planar模式 YUV420、YUV422、YUV444与RGB888)
  17. 将图片url转换成 BufferedImage
  18. plt图像保存到pdf文件
  19. vue框架对接手机app
  20. unity3D professional专业主题——黑色主题设置

热门文章

  1. cocos2d-x-3.0 build不成功
  2. Web Page Request Principle
  3. 计算机网络 时延、发送时延、传输时延、处理时延、排队时延、时延带宽积
  4. 1060. 爱丁顿数(25)-PAT乙级真题
  5. gradle 替换java类_Gradle字符串替换
  6. AIX详细查看用户/进程使用内存
  7. list -- set方法——替换列表中指定位置的元素
  8. weblogic 10 及以后版本需要单独生成Weblogic10.3客户端jar文件
  9. maven jar包下载
  10. 织梦dedecms 相关文档标签(likearticle)实现关联整站文档