We can estimate the weight values for our training data using stochastic gradient descent.

Stochastic gradient descent requires two parameters:

  • Learning Rate: Used to limit the amount each weight is corrected each time it is updated.
  • Epochs: The number of times to run through the training data while updating the weight.

These, along with the training data will be the arguments to the function.

There are 3 loops we need to perform in the function:

  1. Loop over each epoch.
  2. Loop over each row in the training data for an epoch.
  3. Loop over each weight and update it for a row in an epoch.

As you can see, we update each weight for each row in the training data, each epoch.

The loop is over until:

  the iteration error is less than a user-specified error threshold or

  a predetermined number of iterations have been completed.

Weights are updated based on the error the model made. The error is calculated as the difference between the expected output value and the prediction made with the candidate weights.

Notice that learning only occurs when an error is made, otherwise the weights are left unchanged.

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
#include <cmath>

//the sign function
template <typename DataType, typename WeightType>
double sign(typename::std::vector<DataType> &data, typename::std::vector<WeightType> &weights) {
    double result=0.0;

for(size_t i=0; i<weights.size(); ++i) {
        result += data.at(i)*weights.at(i);
    }

if(result >= 0.0)
        return 1.0;
    else
        return 0.0;
}

template <typename DataType, typename WeightType>
void trainW(typename::std::vector<std::vector<DataType> > &vv, typename::std::vector<WeightType> &weights, const double& l_rate, const int& n_epoch) {
    std::vector<DataType> v_data;

for(size_t i=0; i<weights.size(); ++i) {
        weights.at(i)=0.0;
    }

for(size_t i=0; i<n_epoch; ++i) {
        double sum_error=0.0;

for(size_t j=0; j<vv.size(); ++j) {
            v_data.clear();
            for(size_t k=0; k<weights.size(); ++k) {
                v_data.push_back(vv[j][k]);
            }

for(typename::std::vector<DataType>::iterator it=v_data.begin();it!=v_data.end();++it) {
                std::cout<<*it<<" ";
            }

std::cout<<std::endl;

            double prediction=sign(v_data, weights);
            double error=vv[j].back()-prediction;
            std::cout<<"expected: "<<vv[j].back()<<" prediction: "<<prediction<<" error: "<<error<<std::endl;

sum_error+=pow(error, 2.0);

for(size_t k=0; k<weights.size(); ++k) {
                weights.at(k)=weights.at(k)+l_rate*error*vv[j][k];
            }
        }
        std::cout<<"epoch = "<<i<<" error = "<<sum_error<<std::endl;
    }

for(size_t i=0; i<weights.size(); ++i) {
        std::cout<<weights.at(i)<<" ";
    }
    std::cout<<std::endl;
}

//make a prediction with weights, appended to the last column
template <typename DataType, typename WeightType>
void predictTestData(typename::std::vector<std::vector<DataType> > &vv, typename::std::vector<WeightType> &weights) {
    std::vector<DataType> v_data;

for(size_t i=0;i<vv.size();++i) {
        v_data.clear();
        for(size_t j=0;j<weights.size();++j) {
            v_data.push_back(vv[i][j]);
        }

double signResult=sign(v_data,weights);
        vv[i].push_back(signResult);
    }
}

//display the data
template <typename DataType>
void DisplayData(typename::std::vector<std::vector<DataType> > &vv) {
    std::cout<<"the number of data: "<<vv.size()<<std::endl;

for(size_t i=0; i<vv.size(); ++i) {
        for(typename::std::vector<DataType>::iterator it=vv[i].begin(); it!=vv[i].end(); ++it) {
            std::cout<<*it<<" ";
        }
        std::cout<<std::endl;
    }
}

int main() {
    std::ifstream infile_feat("PLA.txt");
    std::string feature;
    float feat_onePoint;
    std::vector<float> lines;
    std::vector<std::vector<float> > lines_feat;
    lines_feat.clear();

std::vector<float> v_weights;
    v_weights.clear();
    v_weights.push_back(-0.1);
    v_weights.push_back(0.206);
    v_weights.push_back(-0.234);

while(!infile_feat.eof()) {
        getline(infile_feat, feature);
            if(feature.empty())
                break;
        std::stringstream stringin(feature);
        lines.clear();

lines.push_back(1);
        while(stringin >> feat_onePoint) {
            lines.push_back(feat_onePoint);
        }
        lines_feat.push_back(lines);
    }

infile_feat.close();

std::cout<<"display train data: "<<std::endl;

DisplayData(lines_feat);

double l_rate=0.1;

int n_epoch=5;

trainW(lines_feat, v_weights, l_rate, n_epoch);

//predictTestData(lines_feat, v_weights);

//std::cout<<"the predicted: "<<std::endl;
    //DisplayData(lines_feat);

return 0;
}

感知器算法 C++的更多相关文章

  1. Stanford大学机器学习公开课(三):局部加权回归、最小二乘的概率解释、逻辑回归、感知器算法

    (一)局部加权回归 通常情况下的线性拟合不能很好地预测所有的值,因为它容易导致欠拟合(under fitting).如下图的左图.而多项式拟合能拟合所有数据,但是在预测新样本的时候又会变得很糟糕,因为 ...

  2. 第三集 欠拟合与过拟合的概念、局部加权回归、logistic回归、感知器算法

    课程大纲 欠拟合的概念(非正式):数据中某些非常明显的模式没有成功的被拟合出来.如图所示,更适合这组数据的应该是而不是一条直线. 过拟合的概念(非正式):算法拟合出的结果仅仅反映了所给的特定数据的特质 ...

  3. [置顶] 局部加权回归、最小二乘的概率解释、逻辑斯蒂回归、感知器算法——斯坦福ML公开课笔记3

    转载请注明:http://blog.csdn.net/xinzhangyanxiang/article/details/9113681 最近在看Ng的机器学习公开课,Ng的讲法循循善诱,感觉提高了不少 ...

  4. 感知器算法--python实现

    写在前面: 参考: 1  <统计学习方法>第二章感知机[感知机的概念.误分类的判断]   http://pan.baidu.com/s/1hrTscza 2   点到面的距离 3   梯度 ...

  5. Perceptron Algorithm 感知器算法及其实现

    Rosenblatt于1958年发布的感知器算法,算是机器学习鼻祖级别的算法.其算法着眼于最简单的情况,即使用单个神经元.单层网络进行监督学习(目标结果已知),并且输入数据线性可分.我们可以用该算法来 ...

  6. 机器学习之感知器算法原理和Python实现

    (1)感知器模型 感知器模型包含多个输入节点:X0-Xn,权重矩阵W0-Wn(其中X0和W0代表的偏置因子,一般X0=1,图中X0处应该是Xn)一个输出节点O,激活函数是sign函数. (2)感知器学 ...

  7. 【2008nmj】Logistic回归二元分类感知器算法.docx

    给你一堆样本数据(xi,yi),并标上标签[0,1],让你建立模型(分类感知器二元),对于新给的测试数据进行分类. 要将两种数据分开,这是一个分类问题,建立数学模型,(x,y,z),z指示[0,1], ...

  8. 感知器算法PLA

    for batch&supervised binary classfication,g≈f <=> Eout(g)≥0 achieved through Eout(g)≈Ein(g ...

  9. 机器学习 —— 基础整理(六)线性判别函数:感知器、松弛算法、Ho-Kashyap算法

    这篇总结继续复习分类问题.本文简单整理了以下内容: (一)线性判别函数与广义线性判别函数 (二)感知器 (三)松弛算法 (四)Ho-Kashyap算法 闲话:本篇是本系列[机器学习基础整理]在time ...

随机推荐

  1. JS——switch case

    语法: switch(n) { case 1: 执行代码块 1 break; case 2: 执行代码块 2 break; default: n 与 case 1 和 case 2 不同时执行的代码 ...

  2. which

    功能说明:显示命令的全路径.   参数选项: -a  默认在PATH路径中由前往后查找命令,如果查找到了,就停止匹配.使用-a选项将遍历所有PATH路径,输出所有匹配项.   参数-a把所有匹配命令路 ...

  3. 如何解决Win10预览版一闪而过的disksnapshot.exe进程?

    Win10之家讯上周微软如约向Insider用户推送了Win10预览版10576更新,本次更新修复了之前版本中存在的一些问题,从日常使用的情况来看,对比之前的预览版系统要更稳定了一些,但是还是存在一些 ...

  4. Sping bean的作用域

    单例(Singleton):在整个应用中,只创建bean的一个实例.(默认) 原型(Prototype):每次注入或者通过Sping应用上下文获取的时候,都会创建一个新的bean. 回话(Sessio ...

  5. vue02 过滤器、计算和侦听属性、vue对象的生命周期、阻止事件冒泡和刷新页面

    3. Vue对象提供的属性功能 3.1 过滤器 过滤器,就是vue允许开发者自定义的文本格式化函数,可以使用在两个地方:输出内容和操作数据中. 定义过滤器的方式有两种. 3.1.1 使用Vue.fil ...

  6. Xftp 5 和 Xshell 5 基本使用方法

    软件介绍: (1)Xshell: 一个强大的安全终端模拟软件,它支持SSH1, SSH2, 以及Microsoft Windows 平台的 TELNET 协议.Xshell通过互联网可以连接到远程的服 ...

  7. CentOS7搭建KMS服务器

    使用vlmcsd搭建KMS服务器 1.下载vlmcsd: wget https://github.com/Wind4/vlmcsd/releases/download/svn1111/binaries ...

  8. jquery动态生成二维码添加自定义logo

    动态生成二维码中间带logo. jquery.qrcode.js 动态生成二维码api很简单. 引入jquer(版本任意),引入jquery.qrcode.js 不需要中间带logo这样就可以了.带l ...

  9. 新手入门学习angular.js的心得体会

    看了一天的angular.js,只要记住这是关于双向数据绑定 和单向数据绑定就可以,看看开发文档,短时间内还是可以直接入手的,看个人理解能力(我是小白). 这几天开始着手学习angularjs的有关知 ...

  10. Bullet:Python的函数中参数是引用吗?

    别的语言中关于函数有传值和传引用的区分. 关于此,流传很广的一个说法是 他们在现象的区别之一就是值传递后的变化,受到影响的就是引用,未受到影响的就是传值.   在学习中,也曾碰到过这个问题,网上关于这 ...