统计学习方法 --- 感知机模型原理及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 统计学方法概论 前言 章节目录 统计学习 监督学习 基本概念 问题的形式化 统计学习三要素 模型 策略 算法 模型评估与模型选择 训练误差与测试误差 过拟合与模型选择 正则化与交叉验证 正则 ...
随机推荐
- spring中InitializingBean接口使用理解
InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候会执行该方法. 测试程序如下: imp ...
- Java课程设计--山寨版QQ
Java课设要求做一个聊天通讯窗口,索性直接照着QQ撸了一个Demo出来 界面高仿qq,初学JAVA,技术比较渣,不喜勿喷 线程开的比较多性能不是太好,一般电脑开两个客户端聊天就卡卡的 先上图 使用方 ...
- View & Controller 一些方法的执行顺序
一. 加载视图 init-初始化程序 viewDidLoad-加载视图 viewWillAppear-UIViewController对象的视图即将加入窗口时调用: viewDidApper-UI ...
- 学习CSS 笔记
1.动态修改div的大小 Html: <div> Hello </div> css: div { resize:both; overflow:auto; } 2. box-si ...
- caffe机器学习自带图片分类器classify.py实现输出预测结果的概率及caffe的web_demo例子运行实例
caffe机器学习环境搭建及python接口编译参见我的上一篇博客:机器学习caffe环境搭建--redhat7.1和caffe的python接口编译 1.运行caffe图片分类器python接口 还 ...
- windows下常查看端口占用方法总结
启动Tomcat时又出现端口占用错误.现在把对端口的处理命令和方法进行汇总. 1.查看所有连接的PID 开始--运行--cmd ,输入netstat -ano 找到端口号对应的PID后,从任务管理器 ...
- javaScript判断浏览器类型
<script type="text/javascript"> function getBrowserInfo(){ var OsObject=navigator.us ...
- 安装Python环境时遇到的问题
问题描述:An error occurred during the installation of assembly 'Microsoft.VC90.MFC,version="9.0.210 ...
- Javascript、Jquery获取浏览器和屏幕各种高度宽度
Javascript: IE中:document.body.clientWidth ==> BODY对象宽度document.body.clientHeight ==> BODY对象高度d ...
- 【leetcode】Pascal's Triangle II
题目简述: Given an index k, return the kth row of the Pascal's triangle. For example, given k = 3, Retur ...