機器學習基石 (Machine Learning Foundations) 作业1 Q18-20的C++实现(pocket)

        大家好,我是Mac Jiang,今天和大家分享Coursera---台湾大学---機器學習基石 (Machine Learning Foundations)---作业1:Q18-20的C++实现。尽管我的代码得到了较为正确的结果,可是肯定不是最好的。假设各位博友有更好的实现思路,请留言指正,谢谢。希望我的博客能给您带来一些学习上的帮助。Q15-17的实现过程已经在:http://blog.csdn.net/a1015553840/article/details/50979434中给出,有须要的博友能够前往阅读。


其它解答看汇总帖:http://blog.csdn.net/a1015553840/article/details/51085129


        尽管已经有非常多博友给出了这个算法的Phython实现过程。说实话,利用Phython的实现比C++来的简答。可是不是每位博友都会Phython。所以在这里提供C++的实现过程,以备各位博友的不时之需。


        好的,话不多说。

这次主要任务是实现PLA的pocket过程,前面博客提到。当训练样本是线性可分的,我们用PLA能够非常快的实现样本的分类。可是假设样本不是线性可分的,那么我们就须要对PLA进行改进。这里採用的是贪心算法,他的思想是把当前最好的分类线保存在口袋中,然后对曲线进行修正得到新的线。假设得到新的线对训练样本的错误率更小。那么我们把这条线保存下来。继续执行程序,直到达到足够的迭代次数。

0.初始化口袋曲线w

{

    1.寻找分类错误点(x,y)

    2.修正错误:w(t+1) = w(t) + y*x

    3.假设w(t+1)对训练样本的错误率比口袋里的w更小,则用w(t+1)替代w

}until(达到足够的迭代次数)


        假设知道训练样本D是线性可分的,则执行PLA比較好,应为PLA速度快(不用推断对全部样本的错误率)

        假设训练样本不是线性可分的(绝大多数情况)。则执行pocket,可是pocket得执行速度慢


1.第18题

(1)题意:首先分别从题目中写的两个网址中下载训练样本和測试样本。然后执行pocket算法,每次迭代50次,共执行2000次,计算他对測试样本的平均错误率

(2)实现:

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

using namespace std;

#define DEMENSION 5  //数据维度

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

//读取文件数据
void getData(fstream &datafile,vector<record> &dataset){
	while(!datafile.eof()){
		record curRecord;
		curRecord.x[0] = 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 *result,double *v1,double *v2){
	int i;
	for(i = 0; i < DEMENSION; i++)result[i] = v1[i] + v2[i];
}

//计算错误率
double getErrorRate(double *weight,vector<record> dataset){
	int n = dataset.size();
	double errorRate= 0.0;
	int i;
	for(i=0;i<n;i++)
		if(sign(multiply(weight,dataset[i].x)) != dataset[i].y)errorRate++;
	return errorRate/n;
}

//口袋PLA算法
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){
			double temp[DEMENSION];
			multiply(temp,trainingSet[index].x,trainingSet[index].y);
			int i;
			for(i=0;i<DEMENSION;i++)weights[i] += temp[i];
	    	if(getErrorRate(weights,trainingSet) < getErrorRate(pocketWeights,trainingSet)){
				int j;
				for(j = 0;j<DEMENSION;j++)pocketWeights[j] = weights[j]; 
			}
			iter++;
		}
		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++ ){

		random_shuffle(trainingSet.begin(), trainingSet.end());

		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; }

(3)实验结果:个人的计算机计算出来为0.132011


2.第19题

(1)题意:假设不採用贪心算法。而是採用第50次迭代结果为终于曲线。执行2000次。求对測试样本的平均错误率

(2)分析:非常easy。仅仅要把pocketPLA函数中

	if(getErrorRate(weights,trainingSet) < getErrorRate(pocketWeights,trainingSet)){
				int j;
				for(j = 0;j<DEMENSION;j++)pocketWeights[j] = weights[j]; 
			}

这个if推断去掉就能够了

(3)答案:个人计算机结果为0.271567


3.第19题

(1)题意:假设把每次调用口袋算法的迭代次数从50次调为100次,求对測试样本的平均错误率

(2)分析:这个更简单。我写的pocketPLA函数有个參数iteration这个就是迭代次数。在main调用时,把pocketPLA(pocketWeights,weights,trainingSet,50)的50改为100就能够了。因为迭代次数添加,所以错误率应该比18中的错误率小一些。

(3)答案:个人计算机得到的结果为0.114024


from:http://blog.csdn.net/a1015553840/article/details/50979640


其它解答看汇总帖:http://blog.csdn.net/a1015553840/article/details/51085129


posted @ 2017-08-14 18:54  jzdwajue  阅读(201)  评论(0编辑  收藏  举报