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

转载 2015年11月18日 16:13:59

参考博客 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++实现的源代码 

 感知机算法的原始形式
算法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 }

网址:http://www.cnblogs.com/xiongqiangcs/p/4185648.html?utm_source=tuicool&utm_medium=referral

李航·统计学习方法笔记·第6章 logistic regression与最大熵模型(2)·最大熵模型

李航·统计学习方法笔记·第6章 logistic regression与最大熵模型(2)·最大熵模型标签(空格分隔): 机器学习教程·李航统计学习方法李航统计学习方法笔记第6章 logistic re...
  • tina_ttl
  • tina_ttl
  • 2016年12月09日 17:17
  • 1147

统计学习方法——模型与问题分类

0. 写在前面在这一讲中,我们主要介绍一下模型的类别以及问题的类别,并对课后习题进行相应的分析。1. 模型的类型我们知道,统计学习主要包括监督学习、非监督学习、半监督学习和强化学习。那么在统计学习方法...
  • qq_35082030
  • qq_35082030
  • 2017年03月04日 16:31
  • 801

李航《统计学习方法》第十章——用Python实现隐马尔科夫模型

相关文章: 李航《统计学习方法》第二章——用Python实现感知器模型(MNIST数据集) 李航《统计学习方法》第三章——用Python实现KNN算法(MNIST数据集) 李航...
  • wds2006sdo
  • wds2006sdo
  • 2017年07月16日 22:52
  • 2524

统计学习方法 李航---第10章 隐马尔可夫模型

第10章隐马尔可夫模型 隐马尔可夫模型(hidden Markov model, HMM)是可用于标注问题的统计学习模型,描述由隐藏的马尔可夫链随机生成观测序列的过程,属于生成模型。 10.1 隐...
  • demon7639
  • demon7639
  • 2016年03月30日 09:54
  • 1369

数学之美笔录(1):统计语言模型

统计语言模型 (Statistical Language Models)介绍: 在语言处理领域,比如翻译、识别语音、文字识别和进行海量文献的自动检索,出现了两种最基本的方法。第一种方法比较直接,就是...
  • kzq_qmi
  • kzq_qmi
  • 2015年07月01日 19:28
  • 695

统计学习方法 李航---第6章 逻辑回归与最大熵模型

第6章 逻辑回归与最大熵模型 逻辑回归(logistic regression)是统计学习中的经典分类方法。最大嫡是概率模型学习的一个准则将其推广到分类问题得到最大熵模型(maximum ent...
  • demon7639
  • demon7639
  • 2016年03月30日 09:54
  • 1408

《统计学习方法》-KNN笔记和python源码

K近邻法 K近邻法(k-nearest neighbor,k-NN)是一种基本分类与回归方法。 k近邻法实际上利用训练数据集对特征向量空间经行划分,并作为其分类的“模型”。 1.算法: 输入:训练数据...
  • V_victor
  • V_victor
  • 2016年04月12日 12:19
  • 711

李航《统计学习方法》第三章——用Python实现KNN算法(MNIST数据集)

相关文章: 李航《统计学习方法》第二章——用Python实现感知器算法(MNIST数据集) 李航《统计学习方法》第四章——用Python实现朴素贝叶斯分类器(MNIST数据集) ...
  • wds2006sdo
  • wds2006sdo
  • 2016年07月17日 16:42
  • 9601

《统计学习方法》+感知机+C++代码(简单)实现

感知机的定义:     感知机学习算法的原始形式算法描述:     以例2.1为例,编程实现该算法:     C++编程实现,程序代码,在...
  • yansmile1
  • yansmile1
  • 2015年11月18日 17:30
  • 429

《统计学习方法》笔记(十二)--Adaboost

通过改变样本的权重来学习多个分类器并将这些分类器进行线性组合,提高分类性能。 理论依据:在PAC(probably approximately correct)的框架下强可学习与弱可学习的等价性 ...
  • si_ma_yu_he
  • si_ma_yu_he
  • 2015年07月10日 10:33
  • 230
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:统计学习方法 --- 感知机模型原理及c++实现
举报原因:
原因补充:

(最多只允许输入30个字)