# Revision history [back]

### High cv::solve error if trained on single line

I use cv::solve to solve two dimensional linear regression. If the training data happen to be on single line (that is, y is equal for all training variables, then the extrapolation produces large error.

Say, the training data are:

X     Y     Z
----  ----  -----
4     7     458
5     7     554
7     7     735
8     7     826


The calculated coefficients are (notice the last two are very large numbers):

{92.8825, 3.74394e+007, -2.62076e+008}


If I use these to extrapolate the original values, large error is produced:

X     Y     Z'
----  ----  -----
4     7     427.53
5     7     520.412
7     7     706.177
8     7     799.06


All values are smaller by about 26-30. Why?

Here is the code:

static void print(float a, float b, float c, int x, int y) {
cout << "x=" << x << ", y=" << y << ", z=" << (a*x + b*y + c) << endl;
}

int main() {
Mat matX(4, 3, CV_32F);
Mat matZ(4, 1, CV_32F);

int idx = 0;
matX.at<float>(idx, 0) = 4;
matX.at<float>(idx, 1) = 7;
matX.at<float>(idx, 2) = 1;
matZ.at<float>(idx++, 0) = 458;

matX.at<float>(idx, 0) = 5;
matX.at<float>(idx, 1) = 7;
matX.at<float>(idx, 2) = 1;
matZ.at<float>(idx++, 0) = 554;

matX.at<float>(idx, 0) = 7;
matX.at<float>(idx, 1) = 7;
matX.at<float>(idx, 2) = 1;
matZ.at<float>(idx++, 0) = 734;

matX.at<float>(idx, 0) = 8;
matX.at<float>(idx, 1) = 7;
matX.at<float>(idx, 2) = 1;
matZ.at<float>(idx++, 0) = 826;

Mat res(3, 1, CV_32F);

cv::solve(matX, matZ, res, CV_QR);

float a = res.at<float>(0);
float b = res.at<float>(1);
float c = res.at<float>(2);

cout << "a=" << a << ", b=" << b << ", c=" << c << endl;
print(a, b, c, 4, 7);
print(a, b, c, 5, 7);
print(a, b, c, 6, 7);
print(a, b, c, 7, 7);
print(a, b, c, 8, 7);
}


### High cv::solve error if trained on single line

I use cv::solve to solve two dimensional linear regression. If the training data happen to be on single line (that is, y is equal for all training variables, then the extrapolation produces large error.

Say, the training data are:

X     Y     Z
----  ----  -----
4     7     458
5     7     554
7     7     735
8     7     826


The calculated coefficients are (notice the last two are very large numbers):

{92.8825, 3.74394e+007, -2.62076e+008}


If I use these to extrapolate the original values, large error is produced:

X     Y     Z'
----  ----  -----
4     7     427.53
5     7     520.412
7     7     706.177
8     7     799.06


All values are smaller by about 26-30. Why?This seems to be an edge case. In my use case, if I have values all on single line (horizontal or vertical), I will predict the values only for that line, turning it effectively into one-dimensional linear regression. But the error is unacceptable.

Here is the code:

static void print(float a, float b, float c, int x, int y) {
cout << "x=" << x << ", y=" << y << ", z=" << (a*x + b*y + c) << endl;
}

int main() {
Mat matX(4, 3, CV_32F);
Mat matZ(4, 1, CV_32F);

int idx = 0;
matX.at<float>(idx, 0) = 4;
matX.at<float>(idx, 1) = 7;
matX.at<float>(idx, 2) = 1;
matZ.at<float>(idx++, 0) = 458;

matX.at<float>(idx, 0) = 5;
matX.at<float>(idx, 1) = 7;
matX.at<float>(idx, 2) = 1;
matZ.at<float>(idx++, 0) = 554;

matX.at<float>(idx, 0) = 7;
matX.at<float>(idx, 1) = 7;
matX.at<float>(idx, 2) = 1;
matZ.at<float>(idx++, 0) = 734;

matX.at<float>(idx, 0) = 8;
matX.at<float>(idx, 1) = 7;
matX.at<float>(idx, 2) = 1;
matZ.at<float>(idx++, 0) = 826;

Mat res(3, 1, CV_32F);

cv::solve(matX, matZ, res, CV_QR);

float a = res.at<float>(0);
float b = res.at<float>(1);
float c = res.at<float>(2);

cout << "a=" << a << ", b=" << b << ", c=" << c << endl;
print(a, b, c, 4, 7);
print(a, b, c, 5, 7);
print(a, b, c, 6, 7);
print(a, b, c, 7, 7);
print(a, b, c, 8, 7);
}


### High cv::solve error if trained on single line

I use cv::solve to solve two dimensional linear regression. If the training data happen to be on single line (that is, y is equal for all training variables, then the extrapolation produces large error.

Say, the training data are:

X     Y     Z
----  ----  -----
4     7     458
5     7     554
7     7     735
8     7     826


The calculated coefficients are (notice the last two are very large numbers):

{92.8825, 3.74394e+007, -2.62076e+008}


If I use these to extrapolate the original values, large error is produced:

X     Y     Z'
----  ----  -----
4     7     427.53
5     7     520.412
7     7     706.177
8     7     799.06


All values are smaller by about 26-30. This seems to be an edge case. In my use case, if I have values all on single line (horizontal or vertical), I will predict the values only for that line, turning it effectively into one-dimensional linear regression. But the error is unacceptable.

Here is the code:

static void print(float a, float b, float c, int x, int y) {
cout << "x=" << x << ", y=" << y << ", z=" << (a*x + b*y + c) << endl;
}

int main() {
Mat matX(4, 3, CV_32F);
Mat matZ(4, 1, CV_32F);

int idx = 0;
matX.at<float>(idx, 0) = 4;
matX.at<float>(idx, 1) = 7;
matX.at<float>(idx, 2) = 1;
matZ.at<float>(idx++, 0) = 458;

matX.at<float>(idx, 0) = 5;
matX.at<float>(idx, 1) = 7;
matX.at<float>(idx, 2) = 1;
matZ.at<float>(idx++, 0) = 554;

matX.at<float>(idx, 0) = 7;
matX.at<float>(idx, 1) = 7;
matX.at<float>(idx, 2) = 1;
matZ.at<float>(idx++, 0) = 734;

matX.at<float>(idx, 0) = 8;
matX.at<float>(idx, 1) = 7;
matX.at<float>(idx, 2) = 1;
matZ.at<float>(idx++, 0) = 826;

Mat res(3, 1, CV_32F);

cv::solve(matX, matZ, res, CV_QR);
DECOMP_QR);

float a = res.at<float>(0);
float b = res.at<float>(1);
float c = res.at<float>(2);

cout << "a=" << a << ", b=" << b << ", c=" << c << endl;
print(a, b, c, 4, 7);
print(a, b, c, 5, 7);
print(a, b, c, 6, 7);
print(a, b, c, 7, 7);
print(a, b, c, 8, 7);
}