1. 程式人生 > >吳恩達機器學習之單變數線性迴歸實現部分

吳恩達機器學習之單變數線性迴歸實現部分

C++實現

  • 程式碼實現

“linear_regression.h”

//單變數線性迴歸模型
struct elem_var1
{
	double x, y;           //訓練集元素資料:自變數、因變數
};

class var1_lin_reg
{
public:
	var1_lin_reg(const elem_var1* p, int size, double rate);     //初始化
	~var1_lin_reg();                                             //析構
	double cost_fuction();                                       //返回當前預測方程對應代價函式的值
	void update();                                               //同時更新方程引數
	void find();                                                 //最小化代價函式,找到收斂點時對應的方程引數
	void get_par(double &_par1, double &_par0);                  //獲得當前方程的引數
	double est_val(double x);                                    //使用擬合後的迴歸方程進行預測

private:
	const elem_var1 * tran_set;        //訓練集
	int setsize;                       //訓練集資料量
	double par1, par0;                 //單變數線性迴歸方程:h(x)=par1*x+par0
	double learn_rate;                 //學習速率
};

“linear_regression.cpp”

//單變數線性迴歸
var1_lin_reg::var1_lin_reg(const elem_var1* p, int size, double rate)
{//引數列表:訓練集陣列地址,訓練集資料量,學習速率
	setsize = size;           //獲取訓練集大小
	tran_set = p;             //指標指向訓練集陣列
	learn_rate = rate;        //設定學習速率
	par1 = 0;                 //線性迴歸方程引數初始化為0
	par0 = 0;
}

var1_lin_reg::~var1_lin_reg()
{
	tran_set = NULL;
	setsize = 0;
}

double var1_lin_reg::cost_fuction()
{//假設函式為h(x)=kx+b
	double hx, sum = 0;
	for (int i = 0;i < setsize;i++)
	{
		hx = par1 * tran_set[i].x + par0;
		sum += (hx - tran_set[i].y)*(hx - tran_set[i].y);
	}
	return (sum / 2.0 / setsize);
}

void var1_lin_reg::update()
{//兩引數(par0和par1)同時更新(關鍵是對微分項的處理)
	double hx, sum0 = 0, sum1 = 0;
	for (int i = 0;i < setsize;i++)
	{
		hx = par1 * tran_set[i].x + par0;
		sum0 += hx - tran_set[i].y;
		sum1 += (hx - tran_set[i].y)*tran_set[i].x;
	}
	sum0 = learn_rate * sum0 / (double)setsize;
	sum1 = learn_rate * sum1 / (double)setsize;
	par0 -= sum0;
	par1 -= sum1;
}

void var1_lin_reg::find()
{//尋找代價函式最小化時對應的單變數線性迴歸函式的引數(代價函式收斂點)
	double cost_pre, cost_last;
	cost_pre = cost_fuction();
	update();                      //更新引數
	cost_last = cost_fuction();
	while (cost_pre != cost_last)
	{//尋找收斂點
		cost_pre = cost_last;
		update();
		cost_last = cost_fuction();
	}
	//獲得假設函式最優擬合時的引數
}

void var1_lin_reg::get_par(double &_par1,double &_par0)
{//獲取迴歸方程引數
	_par1 = par1;
	_par0 = par0;
}

double var1_lin_reg::est_val(double x)
{//返回預測值
	find();               //獲得假設函式最優擬合時的引數  
	double hx;
	hx = par1 * x + par0; //計算估計值
	return hx;
}

“主函式部分”

#include "linear_regression.h"

using namespace std;

int main()
{
	elem_var1 transet[200];
	memset(transet, 0, sizeof(transet));
	int size;
	double x;
	double par1, par0;
	cout << "請輸入訓練集容量:";
	cin >> size;
	cout << "請輸入訓練集資料:" << endl;
	for (int i = 0;i < size;i++)
	{
		cout << "資料項" << i + 1 << ":  ";
		cin >> transet[i].x >> transet[i].y;
	}
	var1_lin_reg obj1(transet, size, 0.001);
	cout << "請輸入待預測資料:";
	cin >> x;
	cout << "預測資料為:" << obj1.est_val(x) << endl;
	obj1.get_par(par1, par0);
	if(par0>0)
		cout << "h(x)=" << par1 << "*x+" << par0 << endl;
	else
	{
		if(par0<0)
			cout << "h(x)=" << par1 << "*x" << par0 << endl;
		else
			cout << "h(x)=" << par1 << "*x" << endl;
	}


    return 0;
}

-執行結果
以吳恩達老師的ex1data1.txt資料集為例:在這裡插入圖片描述
用octave資料視覺化:
在這裡插入圖片描述
線性擬合應該還可以。。。。。。