8.1 - 《机器学习基石》Home Work 2 Q.16-18

8.1 - 《机器学习基石》Home Work 2 Q.16-18_第1张图片

8.1 - 《机器学习基石》Home Work 2 Q.16-18_第2张图片

8.1 - 《机器学习基石》Home Work 2 Q.16-18_第3张图片

根据老师的要求,基于[-1,1]上的均匀分布随机生成20个样本,相应的输出有20%的错误率;20个样本将数轴分为21段,中间有19段,θ取这19段的中点当中的一个,s取1或-1。遍历所有的θ和s,找到E-in最小的(θ,s)组合就得到了那个g函数。

#include <iostream>
#include <ctime>
#include <cmath>
#include <vector>
#include <algorithm>

using namespace std;

#define SAMPLE_SIZE  20		//样本量

struct Hypothesis{
	int coef;
	double threshold;	
};

//求数字的符号
int sign(double x)
{
	if(x<0)		 return -1;
	else if(x>0) return 1;
	else		 return -1;
}

//反转数字的符号
int flipSign(int num)
{
	return num * (-1);	
}

//计算样本错误率
double calErrInSample(vector<double>& inputVec, vector<int>& outputVec, Hypothesis & hypo)
{
	int errCount = 0;

	for(int i=0;i<SAMPLE_SIZE;++i){
		if(outputVec[i] != hypo.coef*sign(inputVec[i]-hypo.threshold)){
			errCount++;
		}	
	}

	return double(errCount)/double(SAMPLE_SIZE);
}

//计算全局错误率
double calErrOutSample(Hypothesis & hypo)
{
	return 0.5 + 0.3 * double(hypo.coef) * (abs(hypo.threshold)-1.0); 	
}

//产生[-1,1]之间均匀分布的随机数
double getRand()  
{  
    return 2.0 * double(rand()) / double(RAND_MAX) - 1.0;  
}

//生成训练数据
void getTrainingData(vector<double>& inputVec)
{
	for(int i=0;i<SAMPLE_SIZE;++i){
		inputVec.push_back(getRand());	
	}
	//对inputVec做升序排列(sort函数默认升序)
	sort(inputVec.begin(),inputVec.end());
}

//根据f(x)产生输出,有20%的出错率
void calOutput(vector<double>& inputVec, vector<int>& outputVec)
{
	int output; 
	double randNum;

	for(int i=0;i<SAMPLE_SIZE;++i){
		randNum = double(rand()) / double(RAND_MAX);  //[0,1];
		output = sign(inputVec[i]);	
		if(randNum<=0.2){
			output = flipSign(output);
		}
		outputVec.push_back(output);
	}
}

//遍历所有θ,找到最小的E-in并返回
double getMinErrIn(vector<double>& inputVec, vector<int>& outputVec, Hypothesis & hypo, double & bestThres )
{
	double minErrIn = 1.0;
	double curErrIn;

	for(int i=0;i<SAMPLE_SIZE-1;++i){
		hypo.threshold = double(inputVec[i]+inputVec[i+1])/2.0;
		curErrIn = calErrInSample(inputVec,outputVec,hypo);
		if(curErrIn<minErrIn){
			minErrIn = curErrIn;
			bestThres = hypo.threshold;
		}
	}

	return minErrIn;
}

//Decision Stump 算法, 确定s和θ
double decisionStump( vector<double>& inputVec, vector<int>& outputVec, Hypothesis & hypo )
{
	double minErrInPositive = 1.0;
	double minErrInNegtive = 1.0;
	double minErrIn;

	double bestThresPositive;
	double bestThresNegtive;

	hypo.coef = 1;
	minErrInPositive = getMinErrIn(inputVec,outputVec,hypo,bestThresPositive);
	
	hypo.coef = -1;
	minErrInNegtive = getMinErrIn(inputVec,outputVec,hypo,bestThresNegtive);

	if(minErrInPositive<minErrInNegtive){
		hypo.coef = 1;	
		minErrIn = minErrInPositive; 
		hypo.threshold = bestThresPositive;
	}else{
		hypo.coef = -1;	
		minErrIn = minErrInNegtive;	
		hypo.threshold = bestThresNegtive;
	}	

	return minErrIn;
}


void main()
{
	srand((unsigned)time(NULL)); 

	double errInTotal = 0.0;
	double errOutTotal = 0.0;

	for(int i=0;i<5000;++i){
		vector<double> inputVec;
		vector<int> outputVec;	
		Hypothesis hypo;

		getTrainingData(inputVec);
		calOutput(inputVec,outputVec);		

		errInTotal += decisionStump(inputVec,outputVec,hypo);
		errOutTotal += calErrOutSample(hypo);

		cout<<"-----------------第"<<i+1<<"次计算结束-------------------\n";
		cout<<"s = "<<hypo.coef<<endl;
		cout<<"θ= "<<hypo.threshold<<endl;
	}

	cout<<"Average E-in = "<<errInTotal/5000<<"\n";
	cout<<"Average E-out = "<<errOutTotal/5000<<"\n";
}

计算结果:

8.1 - 《机器学习基石》Home Work 2 Q.16-18_第4张图片

你可能感兴趣的:(8.1 - 《机器学习基石》Home Work 2 Q.16-18)