参考博客 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. jQuery sibings()的作用

    jQuery sibings()的作用: siblings() 获得匹配集合中每个元素的同胞,通过选择器进行筛选是可选的. 当我们要对一个<li></li>列表的操作的时候,只 ...

  2. js精简写倒计时函数

    <div class="fRight mR10" id="time"> </div> <script type="tex ...

  3. 【spoj705】 Distinct Substrings

    [题目描述] 给定一个字符串,计算其不同的子串个数. [输入格式] 一行一个仅包含大写字母的字符串,长度<=50000 [输出格式] 一行一个正整数,即不同的子串个数. [样例输入] ABABA ...

  4. 使select文本框可编辑可选择(jQuery插件)

    最近做项目中用到了这个插件,正好分享下. 1.  需要用的js包点击下载,在项目中引入该js. <script src="${pageContext.request.contextPa ...

  5. sql server2008根据经纬度计算两点之间的距离

    --通过经纬度计算两点之间的距离 create FUNCTION [dbo].[fnGetDistanceNew] --LatBegin 开始经度 --LngBegin 开始维度 --29.49029 ...

  6. 转:IOC框架

    CSND上看了王泽滨的博客关于IOC的,觉得说的很透彻,地址为:http://blog.csdn.net/wanghao72214/article/details/3969594 1 IoC理论的背景 ...

  7. 第3章 拍摄UFO——单一职责原则

    就一个类而言,应该仅有一个引起它变化的原因

  8. Latex中插入C语言代码

    Latex是一个文本排版的语言,能排版出各种我们想要的效果.而且用代码排版的优点是易于修改板式,因此在文本内容的排版时,Latex应用十分广泛. 当我们需要在Latex中插入代码时,就需要用到 \us ...

  9. 安卓真机调试 出现Installation error: INSTALL_FAILED_UPDATE_INCOMPATIBLE....

    [2016-08-20 14:38:39 - hybrid-android] Installation error: INSTALL_FAILED_UPDATE_INCOMPATIBLE[2016-0 ...

  10. crontab

    在crontab中添加了定时任务,但发现没有得到期望的结果, 这就需要查看crontab的执行历史记录,具体位置如下: cd /var/log tail -100 cron 在cron文件中即可查阅已 ...