您的位置:首页 > 其它

Pocket_PLA算法

2016-06-27 21:51 323 查看
PLA的口袋算法,就是拿PLA训练好的Wf(从训练资料中已经不断修复好的最佳表现的权重集)和以存储的一个W作比较,如果前者很好,就替代已存储的W。

下面这个程序,前提是,现在做训练的数据是数据集的前50个样本,但是每次训练之前会用函数random_shuffle()打乱顺序,然后这种训练后比较W然后再用来测试test_data的过程重复2000次。

training_data的下载地址:https://d396qusza40orc.cloudfront.net/ntumlone%2Fhw1%2Fhw1_18_train.dat

test_data的下载地址:https://d396qusza40orc.cloudfront.net/ntumlone%2Fhw1%2Fhw1_18_test.dat

#include<fstream>
#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

#define DEMENSION 5  //数据维度,包括特征属性x的维度和标签y

//样本结构体
struct record
{
double x[DEMENSION];
int y;
};

//读取文件数据
void getData(fstream &datafile,vector<record> &dataset){
while(!datafile.eof()){
record curRecord;
curRecord.x[0] = 1;//这里初始化的值必须为1
int i;
for(i=1 ; i<DEMENSION ; i++)datafile>>curRecord.x[i];
datafile>>curRecord.y;
dataset.push_back(curRecord);
}
datafile.close();
}

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

//计算两个向量内积,判断是否需要修正
double multiply(double *v1, double *v2){
int i;
double temp = 0.0;
for(i = 0; i < DEMENSION; i++)temp += v1[i] * v2[i];
return temp;
}

//函数重载,计算向量v与整数num的积,用于计算y*x(y为+1或-1,x为向量)
void multiply(double *result,double *v,int num){
int i;
for(i = 0; i < DEMENSION; i++)result[i] =  num * v[i];
}

//计算两向量的和放入result中,用于计算w(i+1)=w(i)+y*x
void add(double *v1,double *v2)
{
int i;
for(i = 0; i < DEMENSION; i++) v1[i] += v2[i];
}

//计算错误率
double getErrorRate(double *weight,vector<record> dataset){
int n = dataset.size();//所有的样本个数为n
cout<<"样本个数为: "<<n<<endl;
double errorRate= 0.0;
int i;
for(i=0;i<n;i++)
if(sign(multiply(weight,dataset[i].x)) != dataset[i].y)errorRate++;
cout<<"error rate : "<<errorRate<<endl;
return errorRate/n;
}

//口袋PLA算法,式中的iteration是迭代次数,是每次做训练的样本的个数,但是由于每次训练之前都有一个打乱样本的过程,所以每次的50个样本是不一样的
void pocketPLA(double *pocketWeights,double *weights,vector<record> trainingSet,int iteration)
{
int index = 0;
int iter= 1;
int n = trainingSet.size();
while(iter <= iteration){
if(sign(multiply(trainingSet[index].x,weights)) != trainingSet[index].y)//判断标签不一致,准备correct
{
double temp[DEMENSION];
multiply(temp,trainingSet[index].x,trainingSet[index].y);
int i;
for(i=0;i<DEMENSION;i++)weights[i] += temp[i];//也可以用add(weight,temp)替代
if(getErrorRate(weights,trainingSet) < getErrorRate(pocketWeights,trainingSet))
{
//如果修正后的权重集比口袋里的要好,则把口袋里的权重集换成这个
int j;
for(j = 0;j<DEMENSION;j++)pocketWeights[j] = weights[j];
}
iter++;
cout<<"iter: "<<iter<<endl;
}
if(index == n-1)index = 0;
else index++;
}
}

void main()
{
vector<record> trainingSet;
vector<record> testSet;
fstream datafile1("training_data.txt");
fstream datafile2("test_data.txt");
if(datafile1.is_open()&&datafile2.is_open()){
getData(datafile1,trainingSet);
getData(datafile2,testSet);
}
else
{
cout<<"can not open file!"<<endl;
exit(1);
}
double weights[DEMENSION],pocketWeights[DEMENSION];
double ave_error = 0.0 ;
int j;
for(j = 0; j < 2000; j++ )//每次训练好的权重集去测试这个权重集在data(资料)为test_data上的表现如何(错误率多少)
{
random_shuffle(trainingSet.begin(), trainingSet.end());//只取前50个样本做训练,每次都随机打乱顺序,用函数random_shuffle
int i;
for(i=0;i<DEMENSION;i++)
{  //注意,这里需要初始化!!!不初始化值会乱码,程序出错!!!
weights[i]=0.0;
pocketWeights[i]=0.0;
}
pocketPLA(pocketWeights,weights,trainingSet,50);
double trainingError = getErrorRate(pocketWeights,trainingSet);
double testError = getErrorRate(pocketWeights,testSet);
ave_error += testError;
cout<<"第"<<j<<"次实验---"<<"training error:"<<trainingError<<" test error:"<<testError<<endl;
}
cout<<"average error rate:"<<ave_error/2000<<endl;
}
最后的结果,每个计算机应该不太一样,我的是0.12364。

参考博客:http://blog.csdn.net/a1015553840/article/details/50979640
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: