统计学习方法 --- 感知机模型原理及c++实现
感知机学习旨在求出将训练数据集进行线性划分的分类超平面,为此,导入了基于误分类的损失函数,然后利用梯度下降法对损失函数进行极小化,从而求出感知机模型。感知机模型是神经网络和支持向量机的基础。下面分别从感知机学习的模型、策略和算法三个方面来介绍。
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范数。
-yi (wxi +b) > 0
所以误分类点(xi, yi)到分类超平面S的距离是:

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


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


对偶形式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++实现的更多相关文章
- [笔记-统计学习方法]感知机模型(perceptron) 原理与实现
前几天认把感知机这一章读完了,顺带做了点笔记 现在把笔记做第三次的整理 (不得不说博客园的LaTex公式和markdown排版真的不太舒服,该考虑在服务器上建一个博客了) 零.总结 适用于具有线性可分 ...
- 统计学习方法 | 感知机 | python实现
感知机是二类分类的线性分类模型,利用随机梯度下降法对基于误分类的损失函数进行极小化. 书中算法可以将所有样本和系数向量写成增广向量的形式,并将所有负样本乘以-1,统一形式,方便计算. (1)训练数据集 ...
- 统计学习方法与Python实现(一)——感知机
统计学习方法与Python实现(一)——感知机 iwehdio的博客园:https://www.cnblogs.com/iwehdio/ 1.定义 假设输入的实例的特征空间为x属于Rn的n维特征向量, ...
- 统计学习方法6—logistic回归和最大熵模型
目录 logistic回归和最大熵模型 1. logistic回归模型 1.1 logistic分布 1.2 二项logistic回归模型 1.3 模型参数估计 2. 最大熵模型 2.1 最大熵原理 ...
- 《统计学习方法》极简笔记P2:感知机数学推导
感知机模型 输入空间是$\chi\subseteq\mathbb{R}^n$,输出空间是$y={+1,-1}$ 感知机定义为:$f(x)=sign(wx+b)$ 感知机学习策略 输入空间任一点$x_0 ...
- 统计学习方法:罗杰斯特回归及Tensorflow入门
作者:桂. 时间:2017-04-21 21:11:23 链接:http://www.cnblogs.com/xingshansi/p/6743780.html 前言 看到最近大家都在用Tensor ...
- 统计学习方法—SVM推导
目录 SVM 1. 定义 1.1 函数间隔和几何间隔 1.2 间隔最大化 2. 线性可分SVM 2.1 对偶问题 2.2 序列最小最优算法(SMO) 3. 线性不可分SVM 3.1 松弛变量 3.2 ...
- word2vec模型原理与实现
word2vec是Google在2013年开源的一款将词表征为实数值向量的高效工具. gensim包提供了word2vec的python接口. word2vec采用了CBOW(Continuous B ...
- 李航《统计学习方法》CH01
CH01 统计学方法概论 前言 章节目录 统计学习 监督学习 基本概念 问题的形式化 统计学习三要素 模型 策略 算法 模型评估与模型选择 训练误差与测试误差 过拟合与模型选择 正则化与交叉验证 正则 ...
随机推荐
- Android Studio导入第三方类库的方法
Android Studio导入第三方类库的方法 本人也刚刚开始尝试做android app的开发,听说android studio是Google支持的android 应用开发工具,所以想应该肯定比E ...
- Android 常用开发工具以及Mac常用软件
Android 常用的开发工具记录.其中包括AndroidStudio(IDEA)插件.Mac 上好用的软件以及国内知名Android开发者博客等. Android Studio 插件 codota ...
- dex文件格式三
先来看看整体的结构,结构体定义在DexFile.h里面 在dexFileSetupBasicPointers中设置各个子结构体,当然是在解析DexHeader之后 源码在DexFile.c文件中 ...
- Sublime3和Chrome配置自动刷新网页【实测可用】
SublimeText2下的LiveReload在SublimeText3下无法正常使用,本文整理SublimeText3安装LiveReload的方法.win7下实测可用! 安装成功后,就不需要再手 ...
- rocketmq生产者部署的机器注意事项
报错: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'warningP ...
- Android 获得AndroidManifest文件里自定义的meta标签内容
try { ApplicationInfo appInfo= this.getPackageManager().getApplicationInfo(getPackageName(),PackageM ...
- 在input中放对象
var input = $("<input type='hidden' class='hidden-user'/>"); $(input).data("ran ...
- 阿里云windows 2012服务器部署java web程序教程
一:环境搭建 1.首先需要购买一个阿里云ECS服务器,购买时可以选择处理器核数以及内存大小(可以购买偏低配置,因为升级 方便) 2.购买后会自动创建一个实例,可以使用该实例中显示的公网地址在 ...
- 解决Maven项目pom.xml文件报xxx\target\classes\META-INF\MANIFEST.MF (系统找不到指定的路径。)问题
最近自己在公司项目修改一些代码以后,出现如题的错误,后来各种Google等,最终找到了解决办法. 错误环境:Tomcat7 + Eclipse + Maven + Spring + SpringMvc ...
- Counter Mode ( CTR )
Encryption Decryption