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

 #include <iostream>
#include <vector>
#include <algorithm> #define random(x) (rand()%(x)) //向量的点积
double dot_product(std::vector<double>& a, std::vector<double>& b){
if(a.size() != b.size()) return ;
double res = ;
for(int i = ; i < a.size(); ++ i){
res +=a[i]*b[i];
}
return res;
} //感知机模型类
class Preception{
public:
Preception(int iters = ,int learnRate = ,double initw = , double initb = ){
iterators = iters;
w.push_back(initw);
b = initb;
step = learnRate;
} ~Preception(){
w.clear();
b = ;
} //训练数据
//如果迭代次数完,还没有找到w和b, 则认为数据集不是线性可分的,返回false
//如果找到了w和b,则认为数据集是线性可分的,返回true
bool train(std::vector<std::vector<double> >& train_x,std::vector<int>& train_y){
if(train_x.size() != train_y.size()) return false;
initWeight(train_x[].size()); for(int iter = ; iter < iterators; ++ iter){
bool flag = true;
for(int i = ; i < train_x.size();){
if( (dot_product(w,train_x[i]) + b)*(double)train_y[i] <= ){
update(train_x[i],train_y[i]);
flag = false;
}else{
++i;
}
}
if(flag) return true;
}
return false;
} //批量预测数据
std::vector<int> predict(std::vector<std::vector<double> >& data_x){
std::vector<int> ret;
for(int i = ; i < data_x.size(); ++ i){
ret.push_back(predict(data_x[i]));
}
return ret;
} //预测x
int predict(std::vector<double>& x){
return dot_product(x,w)+ b > ? : -;
} //打印感知机模型
void printPreceptronModel(){
std::cout<<"原始形式感知机模型:f(x)=sign(";
for(int i = ; i < w.size(); ++ i){
if( i ) std::cout<<"+";
if(w[i]!=) std::cout<<w[i];
std::cout<<"x"<<i+;
}
if(b > ) std::cout<<"+";
std::cout<<b<<")"<<std::endl;
} private:
//初始化向量w的维数
void initWeight(int size){
for(int i = ; i < size; ++ i){
w.push_back(w[]);
}
} //更新w和b
void update(std::vector<double>& x, double y){
for(int i = ; i < w.size(); ++ i){
w[i] += step*y*x[i];
}
b += step*y; // for(int i = 0 ; i < w.size(); ++ i)
// std::cout<<w[i]<<",";
// std::cout<<std::endl; // std::cout<<b<<std::endl;
} private:
int iterators; //迭代次数 //f(x) = sign(wx+b)
std::vector<double> w; //注意w是向量
double b; double step; //学习速率
}; int main(){
std::vector<std::vector<double> >test_x();
test_x[].push_back();test_x[].push_back();
test_x[].push_back();test_x[].push_back();
test_x[].push_back();test_x[].push_back();
std::vector<int> test_y();
test_y[] = ;
test_y[] = ;
test_y[] = -; Preception *model = new Preception();
model->train(test_x,test_y);
model->printPreceptronModel();
}

感知机算法的原始形式

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

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

 #include <iostream>
#include <vector>
#include <algorithm> #define random(x) (rand()%(x)) //向量的点积
double dot_product(std::vector<double>& a, std::vector<double>& b){
if(a.size() != b.size()) return ;
double res = ;
for(int i = ; i < a.size(); ++ i){
res +=a[i]*b[i];
}
return res;
} //感知机模型类
class Preception{
public:
Preception(int iters = ,int learnRate = ,double initw = , double initb = ){
iterators = iters;
a.push_back(initw);
b = initb;
step = learnRate;
} ~Preception(){
a.clear();
b = ;
} //训练数据
//如果迭代次数完,还没有找到a和b, 则认为数据集不是线性可分的,返回false
//如果找到了a和b,则认为数据集是线性可分的,返回true
bool train(std::vector<std::vector<double> >& train_x,std::vector<int>& train_y){
if(train_x.size() != train_y.size()) return false;
initWeight(train_x.size());
std::vector<std::vector<double> > gram = productGram(train_x);
for(int i = ; i < a.size(); ++ i){
int iter = ;
while(iter < iterators){
double sum = b;
for(int j = ; j < a.size(); ++ j){
sum += a[j]*train_y[j]*gram[j][i];
}
sum *= train_y[i];
if(sum <= ) update(i,train_y[i]);
else break;
++iter;
}
if(iter >= iterators) return false;
}
return true;
} //批量预测数据
std::vector<int> predict(std::vector<std::vector<double> >& data_x){
std::vector<int> ret;
for(int i = ; i < data_x.size(); ++ i){
ret.push_back(predict(data_x[i]));
}
return ret;
} //预测x
int predict(std::vector<double>& x){
return dot_product(x,a)+ b > ? : -;
} //打印感知机模型
void printPreceptronModel(){
std::cout<<"原始形式感知机模型:f(x)=sign(";
for(int i = ; i < a.size(); ++ i){
if( i ) std::cout<<"+";
if(a[i]!=) std::cout<<a[i];
std::cout<<"x"<<i+;
}
if(b > ) std::cout<<"+";
std::cout<<b<<")"<<std::endl;
} private:
//初始化向量a的维数
void initWeight(int size){
for(int i = ; i < size; ++ i){
a.push_back(a[]);
}
} //生成Gram矩阵
std::vector<std::vector<double> > productGram(std::vector<std::vector<double> >& train_x){
int n = train_x.size();
std::vector<std::vector<double> > gram(n, std::vector<double>(n,));
for(int i = ; i < n ; ++ i){
for(int j = ; j < n; ++ j){
gram[i][j] = dot_product(train_x[i], train_x[j]);
}
}
return gram;
} //更新w和b
void update(int index, double y){
a[index] +=;
b += step*y;
} private:
int iterators; //迭代次数 std::vector<double> a; //注意w是向量
double b; double step; //学习速率
}; int main(){
std::vector<std::vector<double> >test_x();
test_x[].push_back();test_x[].push_back();
test_x[].push_back();test_x[].push_back();
test_x[].push_back();test_x[].push_back();
std::vector<int> test_y();
test_y[] = ;
test_y[] = ;
test_y[] = -; Preception *model = new Preception();
model->train(test_x,test_y);
model->printPreceptronModel();
}

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

统计学习方法 --- 感知机模型原理及c++实现的更多相关文章

  1. [笔记-统计学习方法]感知机模型(perceptron) 原理与实现

    前几天认把感知机这一章读完了,顺带做了点笔记 现在把笔记做第三次的整理 (不得不说博客园的LaTex公式和markdown排版真的不太舒服,该考虑在服务器上建一个博客了) 零.总结 适用于具有线性可分 ...

  2. 统计学习方法 | 感知机 | python实现

    感知机是二类分类的线性分类模型,利用随机梯度下降法对基于误分类的损失函数进行极小化. 书中算法可以将所有样本和系数向量写成增广向量的形式,并将所有负样本乘以-1,统一形式,方便计算. (1)训练数据集 ...

  3. 统计学习方法与Python实现(一)——感知机

    统计学习方法与Python实现(一)——感知机 iwehdio的博客园:https://www.cnblogs.com/iwehdio/ 1.定义 假设输入的实例的特征空间为x属于Rn的n维特征向量, ...

  4. 统计学习方法6—logistic回归和最大熵模型

    目录 logistic回归和最大熵模型 1. logistic回归模型 1.1 logistic分布 1.2 二项logistic回归模型 1.3 模型参数估计 2. 最大熵模型 2.1 最大熵原理 ...

  5. 《统计学习方法》极简笔记P2:感知机数学推导

    感知机模型 输入空间是$\chi\subseteq\mathbb{R}^n$,输出空间是$y={+1,-1}$ 感知机定义为:$f(x)=sign(wx+b)$ 感知机学习策略 输入空间任一点$x_0 ...

  6. 统计学习方法:罗杰斯特回归及Tensorflow入门

    作者:桂. 时间:2017-04-21  21:11:23 链接:http://www.cnblogs.com/xingshansi/p/6743780.html 前言 看到最近大家都在用Tensor ...

  7. 统计学习方法—SVM推导

    目录 SVM 1. 定义 1.1 函数间隔和几何间隔 1.2 间隔最大化 2. 线性可分SVM 2.1 对偶问题 2.2 序列最小最优算法(SMO) 3. 线性不可分SVM 3.1 松弛变量 3.2 ...

  8. word2vec模型原理与实现

    word2vec是Google在2013年开源的一款将词表征为实数值向量的高效工具. gensim包提供了word2vec的python接口. word2vec采用了CBOW(Continuous B ...

  9. 李航《统计学习方法》CH01

    CH01 统计学方法概论 前言 章节目录 统计学习 监督学习 基本概念 问题的形式化 统计学习三要素 模型 策略 算法 模型评估与模型选择 训练误差与测试误差 过拟合与模型选择 正则化与交叉验证 正则 ...

随机推荐

  1. Angularjs2 入门

    1.创建文件夹 mkdir angular2-app cd angular2-app 2.配置Typescript 需要通过一些特殊的设置来指导Typesript进行编译.新建一个 tsconfig. ...

  2. Flask安装过程中“配置虚拟环境”步骤报错,找不到activate.bat

    Run virtualenv venv --no-setuptools http://stackoverflow.com/questions/21826859/setting-up-a-virtual ...

  3. ubuntu 12.04 install docker-engine1.12.3

    root@node3:/data/src# cat /etc/issueUbuntu 12.04.4 LTS \n \l   root@node3:/data/src# cat /etc/apt/so ...

  4. MVC 文件上传问题

    在用MVC作文件上传处理时,最开始是这样的. html代码 <div id="dialog" title="Upload files">       ...

  5. RSA非对称性前端加密后端解密

    前端加密代码 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> ...

  6. 如何将 Windows Server 2012 r2 打造成 Windows 8.1?

    Server 系列相对于桌面系统Windows 8.1 .嵌入式系统Embedded 8.1来说,还是有所不同的,有其独特性,所以,标题写着“打造”充其量不过是不断接近的意思.还有很多地方存在进一步深 ...

  7. [转]加速Android Studio/Gradle构建

    加速Android Studio/Gradle构建 android android studio gradle   已经使用Android Studio进行开发超过一年,随着项目的增大,依赖库的增多, ...

  8. context:component-scan标签的use-default-filters属性的作用以及原理分析

    一.背景 我们在Spring+SpringMVC+Mybatis的集成开发中,经常会遇到事务配置不起作用等问题,那么本文就来分析下出现这种问题可能的原因以及解决方式. 二.分析及原理窥探 1.项目结构 ...

  9. 【纯css】响应式图片列表

    示例演示 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF- ...

  10. 非旋treap模板

    bzoj3580 非旋转treap 在大神教导下发现split一段区间时先split右边再split左边比较好写 #include <cstdio> #include <cstdli ...