多项式回归和线性回归有着密切的关系。线性回归是多项式回归的一种特例。

线性回归

线性回归(Linear Regression)是统计学和机器学习中最基础和最常用的回归分析方法之一,它用于建模自变量(输入)和因变量(输出)之间的关系。线性回归假设自变量和因变量之间存在线性关系,即通过一条直线来描述这种关系。

线性回归的目标是根据给定的自变量 (x)(x) 预测因变量 (y)(y) 。在最简单的情况下,线性回归建立的是一个直线模型,模型的形式为:

y=β0+β1xy = \beta_{0} + \beta_{1}x

其中:

  • yy 是因变量(即我们要预测的目标变量)
  • xx 是自变量(即输入变量,影响因变量的因素)
  • β0\beta_{0} 是截距(intercept),表示当 x=0x=0 时,预测的 yy 值。
  • β1\beta_{1} 是斜率(slope),表示自变量 xx 每增加 11 单位时,因变量 yy 变化的幅度。

这个模型的目标是通过最小化预测值和实际值之间的误差,找到最优的 β0\beta_{0} 和 β1\beta_{1} 值。

线性回归的假设

线性回归的前提假设包括:

  1. 线性关系: 自变量与因变量之间是线性关系。
  2. 独立性: 观测值是独立的,即一个观测点的值不会影响其他观测点。
  3. 同方差性(Homoscedasticity): 误差项的方差是恒定的,不随自变量的变化而变化。
  4. 正态性: 误差项服从正态分布(对于估计和假设检验特别重要)。

最小二乘法 (Ordinary Least Squares, OLS)

线性回归的核心思想是使用最小二乘法来求解模型参数($\beta_{0}、\beta_{1})。最小二乘法的目标是找到一条直线,使得所有数据点到该直线的垂直距离的平方和最小。

具体来说,对于给定的 nn 个数据点 (x1,y1),(x2,y2),...,(xn,yn)(x_1,y_1),(x_2,y_2),...,(x_n,y_n) ,我们定义误差为每个数据点预测值和真实值之间的差距:

ϵi=yi(β0+β1xi)\epsilon_{i} = y_i - (\beta_{0} + \beta_{1} x_i)

然后,我们要求接参数 β0\beta_{0}β1\beta_{1} ,使得误差的平方和(残差平方和, RSS)最小:

RSS(β0,β1)=i=1n(yi(β0+β1xi))2RSS(\beta_{0}, \beta_{1}) = \sum\limits^{n}_{i=1} (y_i - (\beta_{0} + \beta_{1} x_i))^{2}

通过对 β0\beta_{0}β1\beta_{1} 进行求导并设置导数为 0 ,可以得到最优的回归系数。最终,参数 β0\beta_{0}β1\beta_{1} 的解为:

β1=ni=1nxiyii=1nxii=1nyini=1nxi2(i=1nxi)2\beta_{1} = \dfrac{n \sum^{n}_{i=1} x_i y_i - \sum^{n}_{i=1} x_i \sum^{n}_{i=1} y_i}{n \sum^{n}_{i=1} x^{2}_{i} - (\sum^{n}_{i=1} x_i)^{2}}

β0=i=1nyiβ1i=1nxin\beta_{0} = \dfrac{\sum^{n}_{i=1} y_i - \beta_{1} \sum^{n}_{i=1} x_i}{n}

线性回归的模型评估

一旦得到回归系数,我们就可以使用回归模型进行预测。为了评估模型的效果,通常使用以下几种指标:

R2R^2 (决定系数)

R2R^2 (决定系数)用于衡量模型的拟合优度,即自变量 xx 能解释因变量 yy 变异的百分比。 R2R^2 的值介于 0 和 1 之间,值越高,模型拟合越好。

R2=1i=1n(yiy^i)2i=1n(yiyˉ)2R^2 = 1 - \dfrac{\sum^{n}_{i=1} (y_i - \hat{y}_{i})^{2}}{\sum^{n}_{i=1} (y_i - \bar{y})^{2}}

其中, y^i\hat{y}_{i} 是预测值, yˉ\bar{y}yy 的平均值。

MSEMSE (均方误差)

均方误差是实际值与预测值之间的平方差的平均值,反应了预测值的准确性。公式如下:

MSE=1ni=1n(yiy^i)2MSE = \frac{1}{n} \sum\limits^{n}_{i=1} (y_i - \hat{y}_{i})^{2}

RMSERMSE (均方根误差)

均方根误差是均方误差的平方根,单位与原数据相同,常用于度量模型预测的误差。

RMSE=MSERMSE = \sqrt{MSE}

线性回归的 C 语言实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/**
******************************************************************************
* @file : LR.c
* @brief : Linear regression algorithm.
* @author : Charles
* @date : 2024-12-10
******************************************************************************
* @attention
*
* @copyright 2024 by Charles/https://www.charlesyu1997.com
*
******************************************************************************
*/
/* Include ---------------------------------------------------------------- */
#include <stdio.h>
/* Variable define -------------------------------------------------------- */
#define N 5 // The number of data sample pairs

double x[N] = { 1, 2, 3, 4, 5}; // Independent variable x
double y[N] = { 1, 2, 1.3, 3.75, 2.25}; // Dependent variable y

/* Function code ---------------------------------------------------------- */
/**
* @name calculateLinearRegression
* @brief Calculate the linear regression beta1(Intercept) and beta0(Slope).
* @param x Independent variable.
* @param y Dependent variable.
* @param n The number of data sample pairs.
* @param beta0 Intercept variable.
* @param beta1 Slope variable.
* @return NONE
*
*/
void calculateLinearRegression(double x[], double y[], int n, float *beta0, float *beta1)
{
double sumx = 0, sumy = 0, sumxy = 0, sumx2 = 0;

for ( int i = 0; i < n; i++) {
sumx += x[i];
sumy += y[i];
sumxy += x[i] * y[i];
sumx2 += x[i] * x[i];
}

*beta1 = (n * sumxy - sumx * sumy) / (n * sumx2 - sumx * sumx);
*beta0 = (sumy - *beta1 * sumx) / n;
}
/**
* @name predictByLinearRegression
* @brief Predict the dependent y by linear regression.
* @param x Independent variable.
* @param beta0 Intercept variable.
* @param beta1 Slope variable.
* @return double Return the calculated dependent y.
*
*/
double predictByLinearRegression(double x, double beta0, double beta1)
{
return beta1 * x + beta0;
}
int main()
{
double beta0, beta1;
calculateLinearRegression(x, y, N, &beta0, &beta1);
printf("Regression equation: y = %.4f + %.4f * x\r\n", beta0, beta1);
/* ---------- Predict the dependent variable y */
double test_x = 6;
double predict_y = predict(test_x, beta0, beta1);
printf("Predict result: x = %.2f, y = %.2f\r\n",test_x, predict_y);

return 0;
}

线性回归的扩展

  • 多元线性回归: 当有多个自变量时,线性回归模型可以扩展为多元线性回归,形式为。

y=β0+β1x1+β2x2+...+βnxny = \beta_{0} + \beta_{1} x_1 + \beta_{2} x_2 + ... + \beta_{n} x_n

在这种情况下,目标是通过最小二乘法来求解所有回归系数。

  • 岭回归(Ridge Regression)和套索回归(Lasso Regression): 当数据中存在共线性(自变量之间高度相关)或者特征过多时,线性回归模型可能会过拟合。岭回归和套索回归通过引入正则化来减少过拟合,帮助模型更好的泛化。

线性回归的应用

线性回归广泛应用于许多领域,包括: 预测、趋势分析、经济学。

多项式回归

多项式回归是对线性回归的扩展,它允许回归方程中包含多个高次项。简单的线性回归模型只有一个自变量的线性相(xx),而多项式回归则将自变量扩展到更高的次幂,例如 x2x^2x3x^3,… 等,从而捕捉非线性的关系。

多项式回归模型的一般形式:

y=β0+β1x+β2x2+...+βnxny = \beta_{0} + \beta_{1} x + \beta_{2} x^2 + ... + \beta_{n} x^n

其中:

  • yy 是因变量(预测目标)
  • xx 是自变量(输入)
  • β0,β1,...,βn\beta_{0}, \beta_{1}, ..., \beta_{n} 是回归系数(需要通过数据拟合得到)
  • nn 是多项式的阶数,决定了模型的复杂度

为什么使用多项式回归?

在很多实际问题中,自变量与因变量之间的关系并非线性。通过使用多项式回归,我们可以通过增加高次项来捕捉这些非线性关系。比如,假设我们有一些数据点,它们的关系可能呈现弯曲或者更复杂的形状,而简单的线性回归无法很好地拟合这些数据。

通过使用高阶项(例如 x2,x3x^2, x^3 等),多项式回归能够拟合这些复杂的曲线。

最小二乘法与多项式回归

与线性回归一样,多项式回归也是用最小二乘法来拟合数据。最小二乘法的目标是通过计算回归系数 β0,β1,...,βn\beta_{0}, \beta_{1},...,\beta_{n},使得预测值与实际值之间的误差最小化。
具体来说,我们定义误差(或残差)为每个数据点的预测值与实际值之间的差:

ϵi=yi(β0+β1xi+β2xi2+...+βnxin)\epsilon_{i} = y_i - (\beta_{0} + \beta_{1} x_i + \beta_{2} x^{2}_{i} + ... + \beta_{n} x^{n}_{i})

然后,最小二乘法要求最小化误差的平方和:

RSS(β0,β1,...,βn)=i=1m(yiy^i)2RSS(\beta_{0}, \beta_{1},...,\beta_{n}) = \sum\limits^{m}_{i=1}(y_i - \hat{y}_i)^{2}

在这里, y^i\hat{y}_{i} 是通过多项式回归方程预测的值。我们通过计算回归系数来最小化这个平方和,从而得到最优的拟合曲线。

二次多项式回归的 C 语言实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/**
******************************************************************************
* @file : PolynomialRegression.c
* @brief : Polynomial regression algorithm.
* @author : Charles
* @date : 2024-12-10
******************************************************************************
* @attention
*
* @copyright 2024 by Charles/https://www.charlesyu1997.com
*
******************************************************************************
*/
/* Include ---------------------------------------------------------------- */
#include <stdio.h>
/* Variable define -------------------------------------------------------- */
#define N 5 // The number of data sample pairs

double x[N] = { 0, 25, 50, 75, 100}; // Independent variable x
double y[N] = { 1000, 1050, 1100, 1150, 1200}; // Dependent variable y
/* Function code ---------------------------------------------------------- */
/**
* @name calculatePolynomialRegression
* @brief Calculate the polynomial regression a0, a1, a2.
* @param x Independent variable.
* @param y Dependent variable.
* @param n The number of data sample pairs.
* @param beta0 Intercept.
* @param beta1 Linear coefficient.
* @param beta2 Quadratic coefficient.
* @return NONE
*
*/
void calculatePolynomialRegression(double x[], double y[], int n, double *beta0, double *beta1, double *beta2)
{
double sumx = 0, sumy = 0, sumx2 = 0, sumx3 = 0, sumx4 = 0;
double sumxy = 0, sumx2y = 0;
for (int i = 0; i < n; i++) {
sumx += x[i];
sumy += y[i];
sumx2 += x[i] * x[i];
sumx3 += x[i] * x[i] * x[i];
xumx4 += x[i] * x[i] * x[i] * x[i];
xumxy += x[i] * y[i];
xumx2y += x[i] * x[i] * y[i];
}
double denominator = n * (sumx2 * sumx4 - sumx3 * sumx3) - sumx * (sumx * sumx4 - sumx2 * sumx3) + sumx2 * (sumx * sumx3 - sumx2 * sumx2);
*a0 = (sumy * (sumx2 * sumx4 - sumx3 * sumx3) - sumx * (sumxy + sumx4 - sumx2y * sumx3) + sumx2 * (xumxy * sumx3 - sumx2y * sumx2)) / denominator;
*a1 = (n * (sumxy * sumx4 - sumx2y * sumx3) - sumx * (sumy * sumx4 - sumx2y * sumx2) + sumx2 * (sumy * sumx3 - sumxy * sumx2)) / denominator;
*a2 = (n * (sumx2 * sumx2y - sumxy * sumx3) - sumx * (sumx2 * sumxy - sumy * sumx3) + sumx2 * (sumx2 * sumy - sumx * sumxy)) / denominator;
}
/**
* @name predictPolynomialRegression
* @brief Predict the dependent y by polynomial regression.
* @param x Independent variable.
* @param beta0 Intercept.
* @param beta1 Linear coefficient.
* @param beta2 Quadratic coefficient.
* @return double Return the calculated dependent y.
*
*/
double predictPolynomialRegression(double x, double beta0, double beta1, double beta2)
{
return beta0 + beta1 * x + beta2 * x * x;
}
int main()
{
double beta0, beta1, beta2;
calculatePolynomialRegression(x, y, N, &beta0, &beta1, &beta2);
printf("Regression equation: y = %.4f +%.4f * x + %.4f * x^2\r\n", &beta0, &beta1, &beta2);
double test_x = 60;
double predict_y = predictPolynomialRegression(test_x, &beta0, &beta1, &beta2);
printf("Predict result: x = %.2f, y = %.2f\r\n", test_x, predict_y);
return 0;
}

多项式回归的优缺点及改进

  • 优点:
    • 非线性拟合: 通过引入高阶项,能拟合更复杂的非线性关系。
    • 灵活性: 可以通过选择合适的阶数来拟合不同类型的数据。
    • 适用性广: 对于一些具有明显非线性趋势的数据集,多项式回归可以提供更好的拟合效果。
  • 缺点:
    • 过拟合: 如果多项式的阶数过高,模型可能会拟合到数据中的噪声,导致过拟合。这会降低模型的泛化能力。
    • 计算复杂度: 随着多项式阶数的增加,计算回归系数的难度和时间也会增加。
    • 解释性差: 多项式模型随着阶数的增加,其解释性会变差,难以解释模型中的每个参数对结果的具体影响。
    • 数值稳定性: 高阶多项式可能会导致数值计算上的不稳定性,特别是在特征值范围较大时。
  • 改进:
    • 正则化: 应用 L1 或 L2 正则化技术来减少过拟合的风险,提高模型的泛化能力。
    • 特征选择: 通过特征选择技术来确定哪些多项式项是必要的,减少不必要的高阶项。
    • 交叉验证: 使用交叉验证来评估模型的泛化能力,选择最佳的多项式阶数。
    • 增加样本量: 通过增加数据量来减少过拟合的风险,提高模型的稳定性和确定性。
    • 使用核技巧: 在支持向量机等算法中使用核技巧,可以有效地处理非线性问题,同时避免直接计算高位多项式特征。

多项式回归与线性回归的关系

虽然多项式回归是非线性的,但它本质上仍然是线性回归的一种扩展。之所以称之为线性回归,是因为我们对回归系数 (β0,β1,...,βn)(\beta_{0}, \beta_{1}, ..., \beta_{n}) 进行求解时,他们是线性关系的。即使模型是非线性的,只要系数是线性的,整个问题还是可以通过线性回归的方式来解决。

具体的,回归方程中的 x2,x3,...,x^2, x^3,..., 而不是原始的 xx


此间车厢已使用  次 |   人乘坐过此趟开往世界尽头的列车