机器学习之正规方程法

简介

  本篇继续进行机器学习,主要是使用opencv,用c语言实现机器学习之一元线性回归、正规方程法。
关于这部分的原理,可以参考:1、https://www.coursera.org/learn/machine-learning/home/info
                            2、http://blog.csdn.net/xiazdong/article/details/7950087

具体实现

  关于正规方程法的原理,这里不多做讲解,具体请参考如上两份资料。
  主要使用公式:
     

具体代码

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <math.h>
#include <string.h>
#include <opencv/cv.h>
#include <stdio.h>
#include "opencv2/photo/photo.hpp"
#include <unistd.h>
 
using namespace cv;
 
#define specimenNum  7
#define cir 5
 
char inputWindow[20] = "input";
int normalWidth=400, normalHeight=400;
int specimenAddr[specimenNum][2] = {{50, 150}, {150, 50}, {120, 320},{150, 150}, {300,10}, {70, 320}, {120, 370}};
 
double mat_Num[2] = {0, 0};
double mat_X[specimenNum][2] = {{1, 5}, {1, 15}, {1, 12},{1, 15}, {1,30}, {1, 7}, {1, 12}};
double mat_Y[specimenNum] = {15, 5, 32, 15, 1, 32, 37};
 
Mat mat0, mat1, mat2, mat3, mat4, mat5, mat6, mat7, mat8;
IplImage src1, src2, src3, src4, src5, src6, src7, src8;
double k0, k1;
/*******************************************
*********样本点初始化显示*******************
*******************************************/
void specimenInit(void){
	int i;
 
	mat0 = Mat(normalWidth, normalHeight, CV_8UC3, cv::Scalar(0, 0, 0));
	for(i=0; i<specimenNum; i++){
		Point center = Point(specimenAddr[i][0], specimenAddr[i][1]);
		circle(mat0, center, cir, Scalar(128,128,255), -1);
	}
	imshow(inputWindow, mat0);
}
 
/*******************************************
 *********键值处理,按下q则退出**************
 *******************************************/
void mykey(void){
	while(1){
		char c;
		c = waitKey(0);
		if(c == ‘q‘){
			break;
		}
	}
}
 
/******************************************
 *********画出当前学习曲线******************
 *******************************************/
void drawmachinaline(void){
	double i, j, m, n;
	Mat matTmp;
 
	mat1.copyTo(matTmp);
	for(i=0; i< normalWidth; i++){
		n = (double)i;
		m = k0 + k1 * n;
		if(m <= normalHeight){
			Point center = Point((int)n, (int)m);
			circle(mat0, center, 2, Scalar(255, 255, 255), -1);
		}
	}
	imshow(inputWindow, mat0);
	waitKey(10);
}
 
/*******************************************
***********显示矩阵数据*********************
*******************************************/
void showMatdate(Mat tmpMat){
	int i, j;
	CvScalar s1;
	int Width = tmpMat.rows;
	int Height = tmpMat.cols;
	IplImage tmp;
 
	tmp = tmpMat;
 
	for(i=0; i< Width; i++){
		for(j=0; j<Height; j++){
			s1 = cvGet2D(&tmp, i, j);
			printf("%lf  ", s1.val[0]);
		}
		printf("\n");
	}
	printf("\n");
}
 
void getMachineData(void){
	CvScalar s1;
	int Width = mat8.rows;
	int Height = mat8.cols;
	IplImage tmp;
 
	tmp = mat8;
 
	s1 = cvGet2D(&tmp, 0, 0);
	k0 = s1.val[0];
 
	s1 = cvGet2D(&tmp, 1, 0);
	k1 = s1.val[0];
	printf("k0:%lf, k1:%lf\n", k0, k1);
}
 
 
/*******************************************
*********计算最佳函数参数*******************
*******************************************/
void getfuncNum(void){
	int i;
 
	mat1 = Mat(2, specimenNum, CV_64FC1, mat_X);
	mat2 = Mat(specimenNum, 1, CV_64FC1, mat_Y);
	mat3 = Mat(specimenNum, 2, CV_64FC1);
	mat4 = Mat(specimenNum, specimenNum, CV_64FC1);
	mat5 = Mat(specimenNum, specimenNum, CV_64FC1);
	mat6 = Mat(specimenNum, 2, CV_64FC1);
	mat7 = Mat(2, specimenNum, CV_64FC1);
	mat8 = Mat(2, 1, CV_64FC1);
	src1 = mat1;
	src2 = mat2;
	src3 = mat3;
	src4 = mat4;
	src5 = mat5;
	src6 = mat6;
	src7 = mat7;
	src8 = mat8;
	printf("mat1:\n");
	showMatdate(mat1);
 
	printf("mat2:\n");
	showMatdate(mat2);
 
/***********mat1的转置矩阵**************************/
	cvTranspose(&src1, &src3);
	printf("mat3:\n");
	showMatdate(mat3);
 
/**************矩阵乘法*****************************/
	cvMatMulAdd(&src3, &src1, 0, &src4);
	printf("mat4:\n");
	showMatdate(mat4);
 
/**************矩阵的逆*****************************/
	cvInvert(&src4, &src5, CV_SVD_SYM);
	printf("mat5:\n");
	showMatdate(mat5);
 
	cvMatMulAdd(&src5, &src3, 0, &src6);
	printf("mat6:\n");
	showMatdate(mat6);
 
	cvTranspose(&src6, &src7);
	printf("mat7:\n");
	showMatdate(mat7);
 
	cvMatMulAdd(&src7, &src2, 0, &src8);
	printf("mat8:\n");
	showMatdate(mat8);
 
	getMachineData();
	drawmachinaline();
}
 
int main(int argc, char *argv[]){
	specimenInit();
	getfuncNum();
	mykey();
 
	return 0;
}

代码讲解

  1、首先也是初始化操作。样本值保存在specimenAddr,接着将这些样本,根据正规方程法的原理,封装到mat_Y/mat_X中。
对应用来初始化矩阵X和矩阵Y,然后将样本点在图像上模拟的画出来。
int specimenAddr[specimenNum][2] = {{50, 150}, {150, 50}, {120, 320},{150, 150}, {300,10}, {70, 320}, {120, 370}};
 
double mat_X[specimenNum][2] = {{1, 5}, {1, 15}, {1, 12},{1, 15}, {1,30}, {1, 7}, {1, 12}};
double mat_Y[specimenNum] = {15, 5, 32, 15, 1, 32, 37};
 
void specimenInit(void){
	int i;
 
	mat0 = Mat(normalWidth, normalHeight, CV_8UC3, cv::Scalar(0, 0, 0));
	for(i=0; i<specimenNum; i++){
		Point center = Point(specimenAddr[i][0], specimenAddr[i][1]);
		circle(mat0, center, cir, Scalar(128,128,255), -1);
	}
	imshow(inputWindow, mat0);
}
   图像效果如下:
        
  2、初始化了一票矩阵,然后将mat_X和mat_Y用来初始化mat1和mat2,然后就开始,根据正规方程法的公式,进行矩阵计算:
        1、计算mat1的转置,结果放到mat3。
        2、将mat1的转置矩阵和mat1相乘,结果放到mat4。
        3、求矩阵mat4的逆,结果放到mat5。
        4、将mat1的转置矩阵mat3和之前计算得到的mat5相乘,结果放入mat6。
        5、计算mat6的转置,结果放入mat7。(公式上没有这一步应该,但不知道为什么,我获得的mat6,不先做转置的话,没法和Y相乘)。
        6、将mat7和mat2,也就是Y矩阵相乘,结果放入mat8。
   最后mat8中的数据,就是我们计算出来的参数,取出参数的代码如下:
void getMachineData(void){
	CvScalar s1;
	int Width = mat8.rows;
	int Height = mat8.cols;
	IplImage tmp;
 
	tmp = mat8;
 
	s1 = cvGet2D(&tmp, 0, 0);
	k0 = s1.val[0];
 
	s1 = cvGet2D(&tmp, 1, 0);
	k1 = s1.val[0];
	<a href="http://www.opengroup.org/onlinepubs/%3Cspan%20class=" nu19"="" style="text-decoration: none; color: rgb(11, 0, 128); background-image: none; background-position: initial initial; background-repeat: initial initial;">009695399/functions/printf.html">printf("k0:%lf, k1:%lf\n", k0, k1);
}
  3、如上所诉,参数结果放入到了k0、k1中,然后将他们在图像上模拟画出来。
void drawmachinaline(void){
	double i, j, m, n;
	Mat matTmp;
 
	mat1.copyTo(matTmp);
	for(i=0; i< normalWidth; i++){
		n = (double)i;
		m = k0 + k1 * n;
		if(m <= normalHeight){
			Point center = Point((int)n, (int)m);
			circle(mat0, center, 2, Scalar(255, 255, 255), -1);
		}
	}
	imshow(inputWindow, mat0);
	waitKey(10);
}

效果演示

  最后的效果演示如下:
            
    效果很差,总感觉opencv求矩阵的逆那有问题。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-18 22:13:16

机器学习之正规方程法的相关文章

机器学习之——正规方程法

1.梯度下降法 (1)需要选择学习率a (2)需要多次迭代 优点:梯度下降法在特征变量很多的情况下也能运行地相当好 2.正规方程法 (1)不需要选择学习率a (2)不需要迭代 (3) 正规方程法不需要做特征缩放 缺点:当正规方程法的特征矩阵维度比较大时,会慢很多 总结:当n维比较小时,正规方程法比较好. 当n维比较大时,选择梯度下降法比较好. 什么时候n 算比较大.n>= 10000时,计算机算逆矩阵就比较慢了. 原文地址:https://www.cnblogs.com/gylhaut/p/93

正规方程法

前言            以下内容是个人学习之后的感悟,如果有错误之处,还请多多包涵~ 正规方程法 一.函数参数向量化 在计算机中,我们需要用同样的算法计算大量数据样本时,一般有两种方式:循环.参数向量化. 循环~,可想而知,计算量不是一般的大,不建议. 参数向量化的效率就高多了,把全部样本转换为向量,一次执行就搞定了.具体向量化方法,如下图所示,以线性回归 方程hθ(x)=θ0+θ1x1为例,最终转换为θ的等价公式,为正规方程法做好准备. 二.正规方程法 直接根据上图中的θ等价公式,采用所给

ng机器学习视频笔记(三) ——线性回归的多变量、特征缩放、标准方程法

ng机器学习视频笔记(三) --线性回归的多变量.特征缩放.标准方程法 (转载请附上本文链接--linhxx) 一.多变量 当有n个特征值,m个变量时,h(x)= θ0+θ1x1+θ2x2-+θnxn,其中可以认为x0=1.因此,h(x)= θTx,其中θ是一维向量,θ=[θ0, θ1-θn] T,x也是一维向量,x=[x0,x1..xn] T,其中x0=1. 二.特征缩放(Feature Scaling) 特征缩放的目的,是为了让每个特征值在数量上更加接近,使得每个特征值的变化的影响相对比较"

【机器学习】多项式回归python实现

[机器学习]多项式回归原理介绍 [机器学习]多项式回归python实现 [机器学习]多项式回归sklearn实现 使用python实现多项式回归,没有使用sklearn等机器学习框架,目的是帮助理解算法的原理. 使用一个简单的数据集来模拟,只有几条数据. 代码 从数据集中读取X和y. 为X添加二次方项,用Z替换. 给Z添加 1 列,初始化为 1 ,用来求偏置项. 划分训练集和测试集. 将Z和y的训练集转换为矩阵形式. 和线性回归类似,使用正规方程法,先验证矩阵的可逆性. 去掉Z中全为1的列. 使

机器学习之正则化

前言            以下内容是个人学习之后的感悟,如果有错误之处,还请多多包涵~ 正则化 一.过拟合 过拟合是一种现象.当我们提高在训练数据上的表现时,在测试数据上反而下降,这就被称为过拟合,或过配.过拟合发生 的本质原因,是由于监督学习问题的不适定:在高中数学我们知道,从n个(线性无关)方程可以解n个变量,解n+1个变量就会解 不出.在监督学习中,当样本数远远少于特征数时,会发生过拟合现象. 为了更直观地了解过拟合,请观察下面的图片.可以看到,左边是欠拟合,中间是正好拟合,右边是过拟合

【机器学习】对梯度下降算法的进一步理解

单一变量的线性回归 让我们依然以房屋为例,如果输入的样本特征是房子的尺寸,我们需要研究房屋尺寸和房屋价格之间的关系,假设我们的回归模型训练集如下 其中我们用 m表示训练集实例中的实例数量, x代表特征(输入)变量, y代表目标变量 (x,y)代表实例 根据线性回归模型hΘ(x) = Θ0+Θ1*x1       (Θ是模型参数) 需要找出Θ0,Θ1,使得平均误差最小.J(Θ0,Θ1)称为代价函数. 根据不同的特征值,我们按照如下步骤进行迭代更新,以此来得到不同的Θ: 执行过程中,同步更新Θ0,Θ

机器学习:线性回归——理论与代码实现(基于正规方程与梯度下降)

一 线性模型 给定由n个属性描述的列向量\(f(\mathbf{x})={(x^{(1)};x^{(2)};...;x^{(n)})}\),其中 \(x^{(j)}\)是\(\textbf{x}\)在第\(j\)个属性的取值.线性模型即为通过对属性进行线性组合的函数,即 \[f(\mathbf{x})=w_0+w_1x^{(1)}+...+w_nx^{(n)}\] 写成向量形式如下: \[f(\textbf{x})=\mathbf{w}^\mathrm{T}\mathbf{x}\] 其中列向量\

关于模型

一.基本 1.模型也被称为学习器,学习器更为准确.学习器是指能从已有的数据中学习到所需知识的数学模型. 2.模型分类:按照学习的数据分类, (1)监督学习(supervised learning):训练的数据有标记信息.又由标记信息的 [1]分类:标记信息呈现离散状态.KNN.朴素贝叶斯.逻辑回归.随机森林.支持向量机.决策树.神经网络 [2]回归:标记信息呈现的是连续值.线性回归.Adaboost.Gradient Boosting.神经网络 (2)无监督学习(unsupervised lea

线性回归模型(Linear Regression)及Python实现

线性回归模型(Linear Regression)及Python实现 http://www.cnblogs.com/sumai 1.模型 对于一份数据,它有两个变量,分别是Petal.Width和Sepal.Length,画出它们的散点图.我们希望可以构建一个函数去预测Sepal.Length,当我们输入Petal.Width时,可以返回一个预测的Sepal.Length.从散点图可以发现,可以用一条直线去拟合,这时我们可以构建一元线性回归模型:hθ(x) = θ0 + θ1x1 (x1= Pe