机器学习——一元线性回归(算法实现与评估)

发布于:2025-03-24 ⋅ 阅读:(23) ⋅ 点赞:(0)

一元线性回归是统计学中最基础的回归分析方法,用于建立两个变量之间的线性关系模型。

1. 模型表达式

一元线性回归的数学模型为:


\hat{y}=kx+b

  • \hat{y}:因变量(预测值)
  • x:自变量(输入变量)
  • k:回归系数(斜率),表示xx每增加1单位时\hat{y}的变化量
  • b:截距项,表示当x=0时\hat{y}​的取值

2. 参数估计:最小二乘法

通过最小化预测值与实际值的**残差平方和(RSS)**求解kk和bb:
目标函数


min\sum_{i=1}^{n}\left ( y_{i} -\hat{y}_{i}\right )_{}^{2}=min\sum_{i=1}^{n}\left ( y_{i} -kx_{i}-b\right )_{}^{2}

参数计算公式

  • 斜率k

k=\frac{\sum_{i=1}^{n}\left ( x_{i} -\hat{x}\right )\left ( y_{i} -\hat{y} \right )}{\left ( x_{i} -\hat{x}\right )_{}^{2}}

  • 截距b
  • b=\hat{y}-k\hat{x}

  • 其中,\hat{x}\hat{y}分别表示x和y的样本均值。

3、线性回归模型的评价

(1) MAE(平均绝对误差)

  • 定义:所有样本预测值与真实值之差的绝对值的平均值。
  • 公式

  • MAE=\frac{1}{n}\sum_{i=1}^{n}\left | y_{i} -\hat{y}\right |
  • 特点
    • 单位与因变量一致,便于直观理解(如房价预测中的“万元”)。
    • 对异常值不敏感,适用于需避免大误差惩罚的场景(如稳健预测)。
    • 无法反映误差方向,仅衡量平均偏差大小

(2) MSE(均方误差)

  • 定义:预测值与真实值之差的平方和的均值。
  • 公式
  • MAE=\frac{1}{n}\sum_{i=1}^{n}\left ( y_{i}-\hat{y} \right )_{}^{2}
  • 特点
    • 单位是原变量的平方(如“万元²”),解释性较差,但数学性质优良(连续可导)。
    • 对异常值敏感,大误差会被放大,适用于需强调大误差的场景(如金融风险预测)。

(3) RMSE(均方根误差)

  • 定义:MSE的平方根,将误差单位还原为原变量单位。
  • 公式

RMSE=\sqrt{MSE}

  • 特点
    • 结合了MSE和MAE的优点:单位直观且对大误差敏感56
    • 常用于实际业务中(如房价预测误差表示为“5万美元”)

(4) R²(决定系数)

  • 定义:模型解释因变量方差的比例,衡量拟合优度。
  • 公式
  • ^{R_{}^{2}}=1-\frac{\left (y_{i} -\hat{y_{i}} \right )_{}^{2}}{\left (y_{i} -\bar{y} \right )_{}^{2}}
     
  • 特点
    • 取值范围[0,1]:越接近1,模型解释力越强;0表示模型不优于均值预测。
    • 无量纲性:不受数据量纲影响,适合跨数据集比较模型性能。
    • 局限性:样本量小时可能高估拟合效果,且不直接反映误差大小。

4、代码实现

(1)、手动实现线性回归

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

###准备数据集

#加载boston(波士顿房价)数据集
data_url = "http://lib.stat.cmu.edu/datasets/boston"
raw_df = pd.read_csv(data_url, sep="\s+", skiprows=22, header=None)
data = np.hstack([raw_df.values[::2, :], raw_df.values[1::2, :2]])
target = raw_df.values[1::2, 2]


x = data[:,5]
y = target

x = x[y<50]
y = y[y<50]

#显示
plt.scatter(x,y)
plt.show()

#划分数据集
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.3, random_state = 0)

plt.scatter(x_train, y_train)
plt.show()


###一元线性回归
def fit(x, y):
    a_up = np.sum((x-np.mean(x))*(y - np.mean(y)))
    a_bottom = np.sum((x-np.mean(x))**2)
    a = a_up / a_bottom
    b = np.mean(y) - a * np.mean(x)
    return a, b
a, b = fit(x_train, y_train)
print(a,b) #结果:(8.056822140369603, -28.49306872447786)

#训练回归线
plt.scatter(x_train, y_train)
plt.plot(x_train, a*x_train+ b, c='r')
plt.show()

#测试回归线
plt.scatter(x_test, y_test)
plt.plot(x_test, a*x_test+ b, c='r')
plt.show()



(2)、sklearn 实现一元线性回归

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt 

#准备数据集
data_url = "http://lib.stat.cmu.edu/datasets/boston"
raw_df = pd.read_csv(data_url, sep="\s+", skiprows=22, header=None)
data = np.hstack([raw_df.values[::2, :], raw_df.values[1::2, :2]])
target = raw_df.values[1::2, 2]

x=data[:,5]
y=target 

x=x[y<50]
y=y[y<50]

#划分数据集
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.3, random_state = 0)

#实现回归

from sklearn.linear_model import LinearRegression
lin_reg = LinearRegression()

lin_reg.fit(x_train.reshape(-1,1), y_train)

y_predict = lin_reg.predict(x_test.reshape(-1,1))

plt.scatter(x_test, y_test)
plt.plot(x_test, y_predict, c='r')
plt.show()

(3)、sklearn 实现多元线性回归(注意多元不用归一化)

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt 

#准备数据集
data_url = "http://lib.stat.cmu.edu/datasets/boston"
raw_df = pd.read_csv(data_url, sep="\s+", skiprows=22, header=None)
data = np.hstack([raw_df.values[::2, :], raw_df.values[1::2, :2]])
target = raw_df.values[1::2, 2]

x=data
y=target 

x=x[y<50]
y=y[y<50]

#划分数据集
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.3, random_state = 0)

#实现回归

from sklearn.linear_model import LinearRegression
lin_reg = LinearRegression()

lin_reg.fit(x_train, y_train)

lin_reg.score(x_test, y_test) #结果:0.7455942658788952

5、模型评价

import numpy as np
import pandas as pd
from sklearn import datasets
import matplotlib.pyplot as plt


###数据准备

data_url = "http://lib.stat.cmu.edu/datasets/boston"
raw_df = pd.read_csv(data_url, sep=r"\s+", skiprows=22, header=None)
data = np.hstack([raw_df.values[::2, :], raw_df.values[1::2, :2]])
target = raw_df.values[1::2, 2]

x=data[:, -1].reshape(-1, 1) 
y=target.reshape(-1, 1) 

from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.3, random_state = 0)

###实现一元线性回归

from sklearn.linear_model import LinearRegression
linearReg = LinearRegression()
#适配数据
model = linearReg.fit(x_train, y_train)
#得到预测函数
y_predict = model.predict(x_test)
#显示
plt.scatter(x_test, y_test, s = 10)
plt.plot(x_test, y_predict, c = 'r')
plt.show()

### MSE

y_real = y_test
mse = np.sum((y_real - y_predict) ** 2) / len(y_test)
print(mse )#公式计算 39.81715050474416
from sklearn.metrics import mean_squared_error
mean_squared_error(y_real, y_predict)# sklearn计算 39.81715050474416


### RMSE
rmse = np.sqrt(mse) 
print(rmse )#公式计算 6.310083240714354
mean_squared_error(y_real, y_predict)# sklearn计算 6.310083240714354

### MAE
mae = np.sum(np.abs(y_real - y_predict)) / len(y_test) 
print(mae ) #公式计算 4.4883446998468415
from sklearn.metrics import mean_absolute_error
mean_absolute_error(y_real, y_predict) # sklearn计算  4.4883446998468415



###R方
r2 = 1 - (np.sum((y_real - y_predict) ** 2)) / (np.sum((y_real - np.mean(y_real)) ** 2))
print(r2)  #公式计算 0.5218049526125568 等效:1 - mse / np.var(y_real)
from sklearn.metrics import r2_score
r2_score(y_real, y_predict)# sklearn计算  0.5218049526125568