PLA算法---C++

最近在看PLA算法,以下是觉得写得比较好的博客,通俗易通。

Coursera上台大老师林轩田的机器学习基石这门课,个人觉得讲的非常好,非常适合入门。以下是关于这门课的一些相关童鞋的博客,总结得特别好。

1.http://wizmann.tk/ml-foundations-pla.html 

这篇博客用Python语言描述了PLA算法的过程,还有PLA的改进算法Pocket。

2.http://blog.csdn.net/u013455341/article/details/46747343

假设数据集在图上的反映的效果如下图所示,红色和白色的圈圈分为2类

PLA算法---C++_第1张图片

#include  
#include 
#include

using namespace std;  
//以二维空间为例,x1 x2为属性,x0是假设机器从原点处开始,然后再在被测试的数据集里找一个数开始训练 
struct Item{  
    int x0;  
    double x1,x2;  
    int label;  
};  
//权重结构体,w1 w2为属性x1 x2的权重,初始值全设为0  
struct Weight{  
    double w0,w1,w2;//  
}Wit0={0,0,0};  
  
//符号函数,根据向量内积和的正负和数据集本身的标签进行比较,如果不一样,则需要调整权重  
int sign(double x)
{  
    if(x>0)  
        return 1;  
    else if(x<0)  
        return -1;  
    else return 0;  
}  
//两个向量的内积  
double DotPro(Item item,Weight wight)
{  
    return item.x0*wight.w0+item.x1*wight.w1+item.x2*wight.w2;  
}  
//更新权重  
Weight UpdateWeight(Item item,Weight weight)
{  
    Weight newWeight;  
    newWeight.w0=weight.w0+item.x0*item.label;  
    newWeight.w1=weight.w1+item.x1*item.label;  
    newWeight.w2=weight.w2+item.x2*item.label;  
    return newWeight;  
}  
int main()
{   
    vector ivec;  
    Item data;  
    cout<<"Please input x1,x2,label;"<>data.x1>>data.x2>>data.label)
	{   
        data.x0=0;  
        ivec.push_back(data); 
		//cout<<"Please input x1,x2,label:"<::iterator iter=ivec.begin();iter!=ivec.end();++iter)
	{  
        if((*iter).label!=sign(DotPro(*iter,wit)))
		{  
            wit=UpdateWeight(*iter,wit);  
            iter=ivec.begin();//  
        }  
    }  
    cout<

测试数据集如下

PLA算法---C++_第2张图片

那么PLA算法修正多少次才能得出左右的线性分类的解呢?还是用上面的测试数据集,用以下代码实现

#include
#include
#include
using namespace std;

#define DEMENSION 3

double weight[DEMENSION];//权重值
int step = 0;//修改次数
int n = 0;//训练样本数
char *file = "training_data3.txt";//读取文件名

//存储训练样本,input为x and y,output为label
struct record{
    double input[DEMENSION];
    int output;
};

//把记录存在向量里而不是存在结构体数组内,这样可以根据实际一项项添加
vector trainingSet;

//将数据读入训练样本向量中
void getData(ifstream &datafile)
{
    while(!datafile.eof())
    {
        record curRecord;
        curRecord.input[0] = 1;
        int i;
        for(i = 1; i < DEMENSION; i++){
            datafile>>curRecord.input[i];
        }
        datafile>>curRecord.output;
        trainingSet.push_back(curRecord);
    }
    datafile.close();
    n = trainingSet.size(); 
}

//计算sign值
int sign(double x){
    if(x <= 0)return -1;
    else return 1;
}

//两向量相加(实际为数组相加),将结果保存在第一个数组内,用于计算w(i+1)=w(i)+y*x
void add(double *v1,double *v2,int demension){
    int i;
    for(i = 0;i < demension; i++)v1[i] += v2[i];
}

//计算两数值相乘值,用于判断w*x是否小于0,若小于0要执行修正算法
double multiply(double *v1,double *v2,int demension){
    double temp = 0.0;
    int i;
    for(i = 0; i < demension; i++)temp += v1[i] * v2[i];
    return temp;
}

//计算实数num与向量乘积放在result中,用于计算y*x
void multiply(double *result,double *v,int demension,int num){
    int i;
    for(i = 0; i < demension; i++)result[i] = num * v[i];
}

void PLA()
{
    int correctNum = 0;//当前连续正确样本数,当等于n则表明轮完一圈,则表示全部正确,算法结束
    int index = 0;//当前正在计算第几个样本
    bool isFinished = 0;//算法是否全部完成的表示,=1表示算法结束
    while(!isFinished){
        if(trainingSet[index].output == sign(multiply(weight,trainingSet[index].input,DEMENSION)))correctNum++;//当前样本无错,连续正确样本数+1
        else{//出错,执行修正算法
            double temp[DEMENSION];
            multiply(temp,trainingSet[index].input,DEMENSION,trainingSet[index].output);//计算y*x
            add(weight,temp,DEMENSION);//计算w(i+1)=w(i)+y*x
            step++;//进行一次修正,修正次数+1
            correctNum = 0;//由于出错了,连续正确样本数归0
            cout<<"step"<

得到的结果如下:

PLA算法---C++_第3张图片

这里还有一个4维的测试数据,大家可以拿过去试试~,注意程序中的DEMENSION要改成5哦,读取文件中的数据,靠这个来分组的哦。

https://d396qusza40orc.cloudfront.net/ntumlone%2Fhw1%2Fhw1_15_train.dat 下为训练数据

答案是45哦~

你可能感兴趣的:(机器学习)