哈喽,我是小白~
今儿在和大家聊聊回归算法,非常详细,大家收藏起来慢慢学习!~
回归算法,用于预测连续数值变量的输出,帮助分析变量之间的关系。它们广泛应用于金融、经济、健康等领域的数据建模和预测。通过回归分析,能够揭示特征变量与目标变量的线性或非线性关系,有助于优化决策和提高模型的准确性。
今儿和大家分享的回归类算法有:
线性回归
Ridge 回归
Lasso 回归
弹性网络回归
多项式回归
决策树回归
随机森林回归
支持向量回归
K近邻回归
梯度提升回归
如果需要本文PDF版本的同学,文末获取~
另外,文末有总结性的干货~
一起来看下今天的内容!
1. 线性回归
线性回归是一种用于描述两个或多个变量之间线性关系的统计模型。假设 是响应变量(目标变量), 是解释变量(特征),线性回归模型通过拟合一条直线来预测目标变量。
原理
线性回归的基本假设是:
其中, 是截距, 是回归系数, 是误差项(即残差),假设其服从正态分布。
核心公式
线性回归的目标是通过最小化均方误差(MSE)来拟合参数:
其中, 是样本数量, 是实际值, 是预测值。
公式推导
梯度下降推导
最小化 MSE 的损失函数可以使用梯度下降法。损失函数 表示为:
其中, 是输入特征向量, 是参数向量。对 进行梯度计算:
更新规则为:
其中, 是学习率。
正规方程推导
对于小规模的数据集,线性回归可以直接通过求解解析解来找到最优参数。最小化均方误差时,损失函数的梯度为:
令其等于 0,解得:
其中, 是特征矩阵, 是目标向量。
Python实现
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
# 生成虚拟数据集
np.random.seed(42)
X = np.random.rand(1000, 1) * 10 # 生成1000个0到10之间的随机数
y = 2.5 * X + np.random.randn(1000, 1) * 3 # 生成服从线性关系的y值,加上一定的噪声
# 创建线性回归模型并训练
model = LinearRegression()
model.fit(X, y)
y_pred = model.predict(X)
# 计算残差
residuals = y - y_pred
# 绘图
plt.figure(figsize=(12, 10))
# 子图1: 散点图与回归线
plt.subplot(2, 2, 1)
plt.scatter(X, y, color='blue', label='Actual Data', alpha=0.6)
plt.plot(X, y_pred, color='red', linewidth=2, label='Regression Line')
plt.title('Scatter Plot with Regression Line')
plt.xlabel('X')
plt.ylabel('y')
plt.legend()
# 子图2: 残差图
plt.subplot(2, 2, 2)
plt.scatter(X, residuals, color='green', alpha=0.6)
plt.hlines(y=0, xmin=min(X), xmax=max(X), color='red', linestyle='--')
plt.title('Residual Plot')
plt.xlabel('X')
plt.ylabel('Residuals')
# 子图3: 预测值与实际值对比
plt.subplot(2, 2, 3)
plt.scatter(y, y_pred, color='purple', alpha=0.6)
plt.plot([min(y), max(y)], [min(y), max(y)], color='red', linestyle='--', label='Perfect Fit')
plt.title('Predicted vs Actual')
plt.xlabel('Actual y')
plt.ylabel('Predicted y')
plt.legend()
# 子图4: 残差直方图
plt.subplot(2, 2, 4)
plt.hist(residuals, bins=20, color='orange', edgecolor='black', alpha=0.7)
plt.title('Residuals Distribution')
plt.xlabel('Residuals')
plt.ylabel('Frequency')
plt.tight_layout()
plt.show()
数据生成:使用 np.random.rand()
生成100个随机的自变量 ,通过 模拟线性回归数据,其中 为加入的噪声,模拟实际数据中的波动。回归模型训练:通过 LinearRegression
类对数据进行拟合,获得预测值 。残差计算:残差 用于评估模型的拟合效果。
散点图与回归线:展示数据及模型拟合的情况,红色回归线直观展示了线性拟合效果。 残差图:查看模型误差分布,残差应随机均匀分布在零上下。 预测值与实际值对比:检查预测结果与实际数据的拟合程度。 残差分布直方图:展示残差的分布特征,以确认误差分布的形态是否呈现正态分布。
2. Ridge 回归
岭回归是线性回归的一种改进,用于处理多重共线性问题。在普通线性回归中,如果特征之间存在较高的相关性,模型可能变得不稳定且参数估计不准确。为了解决这个问题,岭回归在损失函数中加入了 正则化项,从而限制参数的大小,防止过拟合。
原理
岭回归的目标是最小化带有正则化项的损失函数:
其中, 是正则化参数,用于控制模型的复杂度。如果 很大,模型的复杂度将受到严格约束,可能导致欠拟合;如果 很小,则正则化效果减弱,回归模型趋于普通的线性回归。
核心公式
岭回归的目标函数为:
其中, 控制正则化项的权重。
公式推导
岭回归可以通过修改线性回归的正规方程来解决。在线性回归中,参数估计公式为:
为了引入正则化,我们将目标修改为最小化:
对其求导并令其等于零,可以得到更新后的解析解:
其中, 是单位矩阵, 是正则化参数。
Python实现
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import Ridge, RidgeCV
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error
# 生成虚拟数据集
np.random.seed(42)
X = np.random.rand(1000, 5) # 1000个样本,5个特征
y = 3 * X[:, 0] + 1.5 * X[:, 1] - 2 * X[:, 2] + np.random.randn(1000) # 线性组合加噪声
# 划分数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 标准化特征
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# 设置不同的α值来训练岭回归模型
alphas = np.logspace(-4, 4, 100)
ridgecv = RidgeCV(alphas=alphas, store_cv_values=True)
ridgecv.fit(X_train_scaled, y_train)
# 预测
y_train_pred = ridgecv.predict(X_train_scaled)
y_test_pred = ridgecv.predict(X_test_scaled)
# 计算均方误差
mse_train = mean_squared_error(y_train, y_train_pred)
mse_test = mean_squared_error(y_test, y_test_pred)
# 岭回归系数路径
ridge_coefs = []
for alpha in alphas:
ridge = Ridge(alpha=alpha)
ridge.fit(X_train_scaled, y_train)
ridge_coefs.append(ridge.coef_)
# 创建图形
fig, axs = plt.subplots(2, 2, figsize=(14, 10))
# 图1:散点图和回归曲线
axs[0, 0].scatter(X_test[:, 0], y_test, color='blue', label='True Values', s=40, alpha=0.6)
axs[0, 0].scatter(X_test[:, 0], y_test_pred, color='red', label='Predicted Values', s=40, alpha=0.6)
axs[0, 0].set_title('Scatter Plot with Regression Curve', fontsize=14)
axs[0, 0].set_xlabel('Feature 1', fontsize=12)
axs[0, 0].set_ylabel('Target', fontsize=12)
axs[0, 0].legend()
# 图2:残差图
axs[0, 1].scatter(y_test_pred, y_test_pred - y_test, color='green', s=40, alpha=0.6)
axs[0, 1].hlines(y=0, xmin=min(y_test_pred), xmax=max(y_test_pred), colors='red', linestyles='dashed')
axs[0, 1].set_title('Residual Plot', fontsize=14)
axs[0, 1].set_xlabel('Predicted Values', fontsize=12)
axs[0, 1].set_ylabel('Residuals', fontsize=12)
# 图3:岭回归系数路径
axs[1, 0].plot(alphas, ridge_coefs)
axs[1, 0].set_xscale('log')
axs[1, 0].set_title('Ridge Coefficients as a Function of the Regularization', fontsize=14)
axs[1, 0].set_xlabel('Alpha', fontsize=12)
axs[1, 0].set_ylabel('Coefficients', fontsize=12)
# 图4:MSE 曲线
cv_values_mean = np.mean(ridgecv.cv_values_, axis=0)
axs[1, 1].plot(alphas, cv_values_mean, color='purple', label='Mean CV Error')
axs[1, 1].set_xscale('log')
axs[1, 1].set_title('Mean Cross-Validation Error', fontsize=14)
axs[1, 1].set_xlabel('Alpha', fontsize=12)
axs[1, 1].set_ylabel('Mean Squared Error', fontsize=12)
axs[1, 1].legend()
plt.tight_layout()
plt.show()
散点图和回归曲线:帮助我们查看自变量与目标变量之间的实际关系以及模型拟合的效果,比较真实值和预测值的差异,判断模型是否合理。
残差图:用于分析预测值与实际值的差异是否具有系统性的偏差,检查模型假设是否被满足,是否存在任何未捕捉的趋势。
岭回归系数路径:展示了不同正则化强度下模型系数的变化,帮助我们直观了解正则化对模型复杂度的影响。
MSE 曲线:展示不同α值下模型在交叉验证中的表现,用来选出最优的正则化参数,帮助我们减少过拟合。
这些图结合起来,可以多维度地分析岭回归模型的效果,评估模型的预测能力和正则化对结果的影响。
3. Lasso 回归
拉索回归是另一种正则化的线性回归方法,与岭回归不同,它使用 正则化项。拉索回归的优势在于它不仅可以限制模型的复杂度,还可以实现特征选择,因为 正则化倾向于将某些回归系数缩为零。
原理
拉索回归的损失函数为:
通过引入 正则化项,模型会倾向于将某些系数缩小到零,从而实现自动的特征选择。
核心公式
拉索回归的目标函数为:
公式推导
拉索回归没有像岭回归那样的解析解,因为 正则化项的绝对值函数不可微。因此,拉索回归的参数通常通过迭代优化方法(如坐标下降法)求解。
坐标下降法推导:
我们通过交替优化每个回归系数,使用坐标轴下降法来求解。对于每个 ,我们固定其他参数,解决以下优化问题:
这个优化过程依赖于软阈值算法,将某些系数强制为零。
Python实现
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import Lasso
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error
# 生成虚拟数据
np.random.seed(42)
n_samples = 1000
n_features = 10
# 生成随机特征数据矩阵
X = np.random.randn(n_samples, n_features)
# 生成权重,其中部分权重为0,模拟实际不相关特征
true_coef = np.array([10, -5, 0, 0, 3, 0, 2, 0, 0, 1])
# 生成目标变量,并添加噪声
y = np.dot(X, true_coef) + np.random.normal(0, 1, size=n_samples)
# 数据集划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 数据标准化
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# Lasso回归模型
lasso = Lasso(alpha=0.1) # L1正则化强度
lasso.fit(X_train_scaled, y_train)
# 预测
y_pred_train = lasso.predict(X_train_scaled)
y_pred_test = lasso.predict(X_test_scaled)
# 计算均方误差
mse_train = mean_squared_error(y_train, y_pred_train)
mse_test = mean_squared_error(y_test, y_pred_test)
# 绘图
plt.figure(figsize=(12, 8))
# 1. 特征重要性条形图
plt.subplot(2, 2, 1)
plt.bar(np.arange(n_features), lasso.coef_, color='cyan', label='Lasso Coefficients')
plt.axhline(0, color='black', linestyle='--')
plt.xlabel('Feature Index')
plt.ylabel('Coefficient Value')
plt.title('Feature Importance (Lasso Coefficients)')
plt.legend()
# 2. 实际值 vs 预测值的散点图
plt.subplot(2, 2, 2)
plt.scatter(y_test, y_pred_test, color='magenta', edgecolor='black', label='Predicted vs Actual')
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], color='blue', lw=2, linestyle='--', label='Ideal Fit')
plt.xlabel('Actual Value')
plt.ylabel('Predicted Value')
plt.title(f'Predicted vs Actual (MSE={mse_test:.2f})')
plt.legend()
# 3. 残差图
plt.subplot(2, 2, 3)
residuals = y_test - y_pred_test
plt.scatter(y_pred_test, residuals, color='orange', edgecolor='black', label='Residuals')
plt.axhline(0, color='black', linestyle='--')
plt.xlabel('Predicted Value')
plt.ylabel('Residuals')
plt.title('Residuals Plot')
plt.legend()
# 4. 特征与目标值的散点图 + 回归线(针对前两个特征)
plt.subplot(2, 2, 4)
for i in range(2): # 绘制前两个特征的关系
plt.scatter(X_test_scaled[:, i], y_test, color=np.random.rand(3,), edgecolor='black', label=f'Feature {i+1}')
plt.plot(X_test_scaled[:, i], lasso.predict(X_test_scaled), color=np.random.rand(3,), lw=2, linestyle='--')
plt.xlabel('Feature Value')
plt.ylabel('Target Value')
plt.title('Feature vs Target with Lasso Fit')
plt.legend()
plt.tight_layout()
plt.show()
特征重要性条形图:Lasso回归的一个重要特点是其特征选择能力。通过可视化各个特征的系数,我们可以直接观察到Lasso如何将某些不重要的特征的系数压缩为0,直观地展示模型的正则化效果。
实际值 vs 预测值的散点图:用来观察模型的拟合效果,理想情况下,所有的点应接近参考线(实际值等于预测值)。这个图表明模型是否在测试集上表现良好,以及预测的偏差如何。
残差图:残差图可以帮助我们进一步理解模型的误差情况,检查残差是否存在系统性偏差,残差应该是随机分布的。
特征与目标值的散点图 + 回归线:展示Lasso回归如何在特征和目标之间拟合出线性关系,尤其是前两个特征。通过回归线,可以直观地看到模型的拟合效果,以及各个特征对目标变量的影响。
4. 弹性网络回归
弹性网络回归结合了岭回归的 正则化和拉索回归的 正则化。它可以同时处理特征选择(通过 正则化)和共线性问题(通过 正则化)。
原理
弹性网络回归的损失函数为:
通过同时使用 和 正则化,弹性网络可以解决拉索回归在处理多重共线性时不稳定的缺点。
核心公式
弹性网络回归的损失函数可以表示为:
公式推导
弹性网络回归的解通常通过坐标轴下降法或其他迭代优化方法求解。它没有简单的解析解,因为存在两个正则化项。
Python实现
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.linear_model import ElasticNet
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, r2_score
# 生成虚拟数据集
np.random.seed(42)
X = np.random.rand(1000, 10) # 1000个样本,10个特征
coefficients = np.array([1.5, -2.0, 3.0, 0, 0, 0, 0.5, -1.5, 2.0, -3.0])
y = X @ coefficients + np.random.randn(1000) * 0.5 # 加入噪声
# 数据划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 标准化特征
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# 构建弹性网络回归模型
elastic_net = ElasticNet(alpha=0.1, l1_ratio=0.7, random_state=42)
elastic_net.fit(X_train_scaled, y_train)
# 预测
y_pred = elastic_net.predict(X_test_scaled)
# 计算回归系数
coefficients = elastic_net.coef_
# 计算模型评估指标
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
# 创建子图
fig, axs = plt.subplots(2, 2, figsize=(14, 10))
fig.suptitle('Elastic Net Regression Analysis', fontsize=16)
# 图1:残差图(Residual Plot)
residuals = y_test - y_pred
axs[0, 0].scatter(y_pred, residuals, color='red', edgecolor='k')
axs[0, 0].axhline(0, color='black', linestyle='--')
axs[0, 0].set_title('Residuals vs Fitted')
axs[0, 0].set_xlabel('Fitted values')
axs[0, 0].set_ylabel('Residuals')
# 图2:回归系数的可视化(Coefficient Plot)
axs[0, 1].bar(range(len(coefficients)), coefficients, color='blue')
axs[0, 1].set_title('Coefficient Magnitude')
axs[0, 1].set_xlabel('Feature index')
axs[0, 1].set_ylabel('Coefficient value')
# 图3:预测值与实际值对比图(Predicted vs Actual Plot)
axs[1, 0].scatter(y_test, y_pred, color='green', edgecolor='k')
axs[1, 0].plot([min(y_test), max(y_test)], [min(y_test), max(y_test)], color='black', linestyle='--')
axs[1, 0].set_title('Predicted vs Actual')
axs[1, 0].set_xlabel('Actual values')
axs[1, 0].set_ylabel('Predicted values')
# 图4:残差的直方图(Residual Histogram)
axs[1, 1].hist(residuals, bins=20, color='purple', edgecolor='k')
axs[1, 1].set_title('Histogram of Residuals')
axs[1, 1].set_xlabel('Residuals')
axs[1, 1].set_ylabel('Frequency')
plt.tight_layout(rect=[0, 0, 1, 0.96])
plt.show()
虚拟数据集生成:我们生成了1000个样本,每个样本有10个特征。目标值 y
是特征的线性组合,并加入噪声模拟现实情况。弹性网络回归模型:通过设定 alpha
和l1_ratio
参数,我们构建了一个弹性网络回归模型,既进行特征选择又减轻多重共线性问题。
残差图:残差图用于观察预测值与实际值的差异。如果残差呈随机分布,表明模型拟合良好。 回归系数的可视化:展示每个特征的回归系数,帮助理解特征的重要性及其对目标变量的影响。 预测值与实际值对比图:该图展示模型预测值与实际值之间的对比。如果点分布在对角线附近,表示模型预测较为准确。 残差的直方图:用于检查残差是否符合正态分布,这是回归模型假设之一。
5. 多项式回归
多项式回归是一种扩展的线性回归方法,通过增加特征的多项式项(如平方、立方等),可以捕捉到非线性关系。
原理
假设输入特征为 ,多项式回归模型为:
其中 是多项式的阶数。虽然模型看似非线性,但本质上它仍然是线性回归,只是通过对输入进行非线性变换来增强表达能力。
核心公式
多项式回归模型可以表示为:
可以通过增加特征维度,将原始特征 转换为 ,然后应用标准的线性回归方法。
公式推导
将输入特征映射到多项式特征空间后,问题转化为一个多元线性回归问题。可以使用梯度下降或正规方程来求解参数。
Python实现
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
# 生成虚拟数据集:面积 (平方英尺) 和房价 (千美元)
np.random.seed(42)
n_samples = 1000
X = np.random.uniform(500, 5000, size=n_samples) # 房屋面积
y = 0.05 * X**2 - 20 * X + 3000 + np.random.normal(0, 20000, size=n_samples) # 房价,加入噪声
# 将X形状变为矩阵形式 (n_samples, 1)
X = X.reshape(-1, 1)
# 设置不同的多项式阶数
degrees = [1, 2, 3, 4]
# 画布设置
plt.figure(figsize=(12, 8))
# 存储残差
residuals = []
# 遍历不同的多项式阶数
for i, degree in enumerate(degrees, 1):
# 创建多项式特征
poly_features = PolynomialFeatures(degree=degree)
X_poly = poly_features.fit_transform(X)
# 使用线性回归拟合
model = LinearRegression()
model.fit(X_poly, y)
# 预测房价
y_pred = model.predict(X_poly)
# 计算残差
residuals.append(y - y_pred)
# 第一个子图:实际数据和拟合曲线
plt.subplot(2, 2, 1)
X_range = np.linspace(X.min(), X.max(), 100).reshape(-1, 1)
X_range_poly = poly_features.transform(X_range)
y_range_pred = model.predict(X_range_poly)
plt.scatter(X, y, color='gray', alpha=0.6, label="Actual data" if i == 1 else "", s=10)
plt.plot(X_range, y_range_pred, label=f"Degree {degree} fit", linewidth=2)
plt.xlabel('House Size (sq ft)')
plt.ylabel('Price ($1000)')
plt.title('Actual Data vs Polynomial Fit')
plt.legend()
# 第二个子图:残差图
plt.subplot(2, 2, 2)
plt.scatter(X, residuals[i-1], alpha=0.7, label=f'Degree {degree} Residuals', s=10)
plt.hlines(0, X.min(), X.max(), colors='black', linestyles='dashed')
plt.xlabel('House Size (sq ft)')
plt.ylabel('Residuals')
plt.title('Residuals Analysis')
plt.legend()
# 第三个子图:多项式阶次与均方误差(MSE)
plt.subplot(2, 2, 3)
mse = mean_squared_error(y, y_pred)
plt.scatter(degree, mse, color='red', s=50, zorder=5)
plt.plot(degrees[:i], [mean_squared_error(y, LinearRegression().fit(PolynomialFeatures(deg).fit_transform(X), y).predict(PolynomialFeatures(deg).fit_transform(X))) for deg in degrees[:i]], color='blue', linewidth=2, label='MSE vs Degree')
plt.xlabel('Polynomial Degree')
plt.ylabel('Mean Squared Error')
plt.title('MSE vs Polynomial Degree')
plt.grid(True)
if i == 1:
plt.legend()
# 布局调整
plt.tight_layout()
plt.show()
实际数据和回归模型的拟合曲线图:通过拟合曲线展示了不同多项式阶数下的模型如何对数据进行拟合。随着多项式阶数的增加,拟合曲线逐渐变得复杂,可以更好地逼近数据。图形的颜色鲜艳,能够区分不同阶数的拟合效果。
残差图:残差图展示了模型预测值与真实值之间的误差。通过观察残差,我们可以发现模型是否存在系统性偏差。如果残差分布随机且均匀,则模型效果较好;如果存在明显的模式,则表明模型可能存在欠拟合或过拟合问题。
多项式阶次与均方误差(MSE)关系图:该图展示了不同多项式阶数下模型的均方误差。随着阶数的增加,模型的MSE可能会下降,但过高的阶数也可能导致过拟合,使得MSE反而增大。这有助于我们选择合适的多项式阶数,从而避免过拟合或欠拟合。
6. 决策树回归
决策树回归是一种非参数回归方法,基于递归划分数据集,将数据划分为不同的子集并在每个子集上拟合一个常数值。
原理
决策树通过选择一个特征和分裂点将数据划分成多个部分。在每个分裂点,算法选择最优的特征和阈值,以最大化分裂前后目标变量的纯度(通常使用最小化方差或均方误差作为准则)。对每个叶节点,输出的是该叶节点内所有数据的平均值。
核心公式
假设一个节点包含样本集 ,选择某个特征 和分裂点 ,将节点分成两部分:
分裂后的损失为:
目标是选择 和 ,使得分裂后的均方误差最小化。
公式推导
通过计算每个可能的分裂点的方差或均方误差,决策树找到最优分裂点,并递归地应用该过程,直到满足停止条件。
Python实现
import numpy as np
import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
# 生成虚拟数据集
np.random.seed(42)
X = np.sort(5 * np.random.rand(80, 1), axis=0)
y = np.sin(X).ravel() + np.random.normal(0, 0.1, X.shape[0])
# 将数据集分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建决策树回归模型
regr = DecisionTreeRegressor(max_depth=4)
regr.fit(X_train, y_train)
# 预测
y_pred = regr.predict(X_test)
# 计算残差
residuals = y_test - y_pred
# 创建子图
fig, axs = plt.subplots(3, 1, figsize=(8, 12))
# 1. 特征与目标值的散点图
axs[0].scatter(X_train, y_train, color="blue", label="Train Data", alpha=0.7)
axs[0].scatter(X_test, y_test, color="red", label="Test Data", alpha=0.7)
axs[0].set_title("Feature vs Target (Scatter Plot)")
axs[0].set_xlabel("Feature (X)")
axs[0].set_ylabel("Target (y)")
axs[0].legend()
# 2. 真实值 vs 预测值
axs[1].scatter(y_test, y_pred, color="purple", label="Predicted vs Actual", alpha=0.7)
axs[1].plot([min(y_test), max(y_test)], [min(y_test), max(y_test)], color="black", lw=2, linestyle="--", label="Ideal Fit")
axs[1].set_title("Actual vs Predicted Values")
axs[1].set_xlabel("Actual Values")
axs[1].set_ylabel("Predicted Values")
axs[1].legend()
# 3. 残差图
axs[2].scatter(X_test, residuals, color="green", label="Residuals", alpha=0.7)
axs[2].axhline(y=0, color="black", lw=2, linestyle="--")
axs[2].set_title("Residuals (Actual - Predicted)")
axs[2].set_xlabel("Feature (X)")
axs[2].set_ylabel("Residuals")
axs[2].legend()
# 设置整体标题和布局
plt.suptitle("Decision Tree Regression Analysis", fontsize=16)
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
# 显示图形
plt.show()
散点图(第一张图):蓝色和红色散点分别表示训练数据和测试数据,观察数据的分布以及特征与目标之间的关系。 真实值 vs 预测值(第二张图):显示了预测值与真实值的散点对比。如果模型预测较好,散点会围绕在理想拟合的虚线(黑线)附近。 残差图(第三张图):残差图展示了模型预测与真实值之间的差异(误差),理想的残差应当随机分布并围绕在 0 附近。
通过这些图形,可以分析模型的拟合能力及其误差分布情况。
7. 随机森林回归
随机森林是决策树的集成方法,通过构建多个决策树并将它们的预测结果进行平均来提高预测的准确性和鲁棒性。随机森林通过对训练数据进行有放回的随机抽样来构建多个不同的决策树(即袋装法),并且每个树只使用部分特征进行训练。
原理
随机森林利用“袋装法(Bagging)”构建多个决策树。每棵树独立训练,并给出一个预测结果,最后的预测结果是所有树预测值的平均值。通过随机选取特征和样本,随机森林减小了单棵决策树的方差,提升了模型的鲁棒性。
核心公式
随机森林的预测公式为:
其中, 是决策树的数量, 是第 棵树的预测结果。
Python实现
import numpy as np
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
import pandas as pd
# 生成虚拟数据集
np.random.seed(42)
X = np.random.rand(1000, 3) # 3个特征
y = (np.sin(X[:, 0] * 2 * np.pi) + np.log1p(X[:, 1]) + X[:, 2]**2 + np.random.randn(1000) * 0.1) * 10 # 非线性带噪声
# 数据集拆分
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 随机森林回归模型
rf = RandomForestRegressor(n_estimators=100, random_state=42)
rf.fit(X_train, y_train)
# 预测
y_pred = rf.predict(X_test)
# 计算残差
residuals = y_test - y_pred
# 特征重要性
importances = rf.feature_importances_
feature_names = ['Feature 1', 'Feature 2', 'Feature 3']
df_importances = pd.DataFrame({'Feature': feature_names, 'Importance': importances})
df_importances = df_importances.sort_values(by='Importance', ascending=False)
# 绘制图形
fig, axes = plt.subplots(2, 2, figsize=(12, 10), gridspec_kw={'hspace': 0.3, 'wspace': 0.3})
# 图1: 实际值 vs 预测值散点图
axes[0, 0].scatter(y_test, y_pred, color='blue', label='Predicted vs Actual')
axes[0, 0].plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], color='red', linestyle='--', label='Ideal Line')
axes[0, 0].set_xlabel('Actual Values')
axes[0, 0].set_ylabel('Predicted Values')
axes[0, 0].set_title('Actual vs Predicted')
axes[0, 0].legend()
axes[0, 0].grid(True)
# 图2: 残差图
axes[0, 1].scatter(y_pred, residuals, color='green')
axes[0, 1].axhline(y=0, color='red', linestyle='--')
axes[0, 1].set_xlabel('Predicted Values')
axes[0, 1].set_ylabel('Residuals')
axes[0, 1].set_title('Residuals Plot')
axes[0, 1].grid(True)
# 图3: 特征重要性柱状图
axes[1, 0].bar(df_importances['Feature'], df_importances['Importance'], color=['purple', 'orange', 'cyan'])
axes[1, 0].set_xlabel('Features')
axes[1, 0].set_ylabel('Importance')
axes[1, 0].set_title('Feature Importance')
axes[1, 0].grid(True)
# 图4: 预测值与真实值的直线拟合图
axes[1, 1].plot(y_test, y_pred, 'o', color='magenta', label='Predicted vs Actual')
axes[1, 1].plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], color='black', linestyle='--', label='Ideal Line')
axes[1, 1].set_xlabel('Actual Values')
axes[1, 1].set_ylabel('Predicted Values')
axes[1, 1].set_title('Prediction vs Actual Fit Line')
axes[1, 1].legend()
axes[1, 1].grid(True)
plt.show()
生成数据:使用 np.random
生成 100 个样本,3 个特征,目标变量 是一个非线性函数(带有噪声)。模型训练和预测:使用 RandomForestRegressor
对数据进行训练并预测。残差计算:残差是真实值与预测值之间的差距,用于残差图绘制。 特征重要性:通过随机森林回归模型的 feature_importances_
属性提取特征的重要性。
实际值 vs 预测值散点图:展示了预测值和实际值的关系,如果模型拟合得好,点应该接近红色虚线的对角线。 残差图:用于检测模型误差的分布情况,理想情况下,残差应随机分布在0附近,无明显趋势。 特征重要性图:帮助我们理解哪些特征对模型贡献最大。 预测值与真实值的直线拟合图:模型的拟合曲线,如果预测值和真实值在图中接近对角线,表示模型性能良好。
8. 支持向量回归
支持向量回归(SVR)是支持向量机(SVM)的扩展,适用于回归问题。SVR 的目标是找到一个函数,使得大多数样本点落在该函数的 容忍范围内。
原理
SVR 的目标是找到一个函数 ,使得绝大多数点满足:
即预测值与实际值之间的误差在 范围内。SVR 同样会使用正则化来最大化函数的“边界”,从而提高泛化能力。
核心公式
SVR 的损失函数为:
其中, 是正则化项, 是惩罚系数,控制对违背 区间的样本的惩罚。
Python实现
import numpy as np
import matplotlib.pyplot as plt
from sklearn.svm import SVR
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
# 生成虚拟数据集
np.random.seed(0)
X = np.sort(5 * np.random.rand(80, 1), axis=0)
y = np.sin(X).ravel() + 0.2 * np.random.randn(80)
# 将数据集划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建支持向量回归模型(RBF核)
svr_rbf = SVR(kernel='rbf', C=100, gamma=0.1, epsilon=0.1)
svr_rbf.fit(X_train, y_train)
# 预测
y_pred_train = svr_rbf.predict(X_train)
y_pred_test = svr_rbf.predict(X_test)
# 计算训练集和测试集的误差
train_mse = mean_squared_error(y_train, y_pred_train)
test_mse = mean_squared_error(y_test, y_pred_test)
# 创建图形
fig, axs = plt.subplots(2, 2, figsize=(12, 10))
# 图 1:原始数据与支持向量回归拟合曲线(训练集)
axs[0, 0].scatter(X_train, y_train, color='red', label='Training data', alpha=0.6)
axs[0, 0].plot(X_train, y_pred_train, color='blue', label='SVR fit (train)')
axs[0, 0].set_title('Training Data and SVR Fit')
axs[0, 0].legend()
# 图 2:原始数据与支持向量回归拟合曲线(测试集)
axs[0, 1].scatter(X_test, y_test, color='green', label='Test data', alpha=0.6)
axs[0, 1].plot(X_test, y_pred_test, color='orange', label='SVR fit (test)')
axs[0, 1].set_title('Test Data and SVR Fit')
axs[0, 1].legend()
# 图 3:残差图(训练集)
axs[1, 0].scatter(X_train, y_train - y_pred_train, color='purple', label='Residuals (train)', alpha=0.6)
axs[1, 0].hlines(0, min(X_train), max(X_train), colors='black', linestyles='dashed')
axs[1, 0].set_title('Residuals on Training Data')
axs[1, 0].legend()
# 图 4:残差图(测试集)
axs[1, 1].scatter(X_test, y_test - y_pred_test, color='cyan', label='Residuals (test)', alpha=0.6)
axs[1, 1].hlines(0, min(X_test), max(X_test), colors='black', linestyles='dashed')
axs[1, 1].set_title('Residuals on Test Data')
axs[1, 1].legend()
# 总标题和显示图形
plt.suptitle('Support Vector Regression Analysis', fontsize=16)
plt.tight_layout(rect=[0, 0, 1, 0.95])
plt.show()
散点图 + 拟合曲线:展示支持向量回归模型在训练集上的拟合效果。红色点表示训练集中的数据点,蓝色曲线表示支持向量回归模型的拟合结果。通过这个图形,我们可以观察模型在训练数据上的表现如何。
散点图 + 拟合曲线:检查模型在未见过的测试集上的表现。绿色点表示测试集中的数据点,橙色曲线显示模型的预测结果。通过这个图形,我们可以比较训练集和测试集的拟合情况,判断模型是否过拟合或欠拟合。
残差图:观察预测值与实际值之间的误差。残差图帮助我们更好地了解模型的预测误差分布情况。如果残差图中的点大多围绕零线随机分布,则表明模型的预测是合理的。如果残差有系统性的偏差,则表明模型可能存在不足。
散点图 直观地展示了原始数据分布和模型拟合情况。 拟合曲线 展示了支持向量回归模型对数据的拟合能力,可以直观地看出模型的效果。 残差图 是评估回归模型性能的常用方法,通过观察残差的分布情况可以发现模型的不足之处,如是否存在系统性偏差或是否过拟合。
9. K近邻回归
KNN 回归是一种基于实例的非参数方法,通过找到与测试样本距离最近的 个训练样本,并通过这些邻居的平均值来预测目标值。
原理
KNN 回归的思想是,给定一个测试样本 ,找到训练集中与它最近的 个样本,然后通过这些样本的目标值进行加权平均来预测。
核心公式
对于给定的测试样本 ,预测值为:
其中, 是 的 个最近邻居。
Python实现
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsRegressor
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import learning_curve
# 生成虚拟数据集
np.random.seed(42)
X = np.random.rand(1000, 2) * 10 # 两个特征
y = 2 * X[:, 0] + 3 * X[:, 1] + np.random.randn(1000) * 2 # 目标值带噪声
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 定义并训练K近邻回归模型
knn = KNeighborsRegressor(n_neighbors=5)
knn.fit(X_train, y_train)
# 进行预测
y_pred_train = knn.predict(X_train)
y_pred_test = knn.predict(X_test)
# 计算均方误差
mse_train = mean_squared_error(y_train, y_pred_train)
mse_test = mean_squared_error(y_test, y_pred_test)
# 生成图形
fig, axs = plt.subplots(2, 2, figsize=(12, 10))
plt.subplots_adjust(hspace=0.4)
# 图1: 训练集和测试集的真实值 vs 预测值散点图
axs[0, 0].scatter(y_train, y_pred_train, color='blue', label='Train set', alpha=0.7)
axs[0, 0].scatter(y_test, y_pred_test, color='red', label='Test set', alpha=0.7)
axs[0, 0].plot([min(y_train), max(y_train)], [min(y_train), max(y_train)], color='green', linestyle='--')
axs[0, 0].set_title('True vs Predicted Values (Train & Test)')
axs[0, 0].set_xlabel('True Values')
axs[0, 0].set_ylabel('Predicted Values')
axs[0, 0].legend()
# 图2: 残差图(测试集)
residuals = y_test - y_pred_test
axs[0, 1].scatter(y_test, residuals, color='purple', alpha=0.7)
axs[0, 1].hlines(0, min(y_test), max(y_test), color='green', linestyle='--')
axs[0, 1].set_title('Residual Plot (Test Set)')
axs[0, 1].set_xlabel('True Values')
axs[0, 1].set_ylabel('Residuals')
# 图3: 预测曲面(测试集预测 vs 特征)
from mpl_toolkits.mplot3d import Axes3D
ax3 = fig.add_subplot(223, projection='3d')
ax3.scatter(X_test[:, 0], X_test[:, 1], y_test, color='blue', label='True Values', alpha=0.6)
ax3.scatter(X_test[:, 0], X_test[:, 1], y_pred_test, color='red', label='Predicted Values', alpha=0.6)
ax3.set_xlabel('Feature 1')
ax3.set_ylabel('Feature 2')
ax3.set_zlabel('Target')
ax3.set_title('3D Plot of True vs Predicted')
ax3.legend()
# 图4: 学习曲线
train_sizes, train_scores, test_scores = learning_curve(knn, X, y, cv=5, train_sizes=np.linspace(0.1, 1.0, 10))
train_scores_mean = np.mean(train_scores, axis=1)
test_scores_mean = np.mean(test_scores, axis=1)
axs[1, 1].plot(train_sizes, train_scores_mean, color='blue', label='Training Score')
axs[1, 1].plot(train_sizes, test_scores_mean, color='red', label='Validation Score')
axs[1, 1].set_title('Learning Curve')
axs[1, 1].set_xlabel('Training Set Size')
axs[1, 1].set_ylabel('Score')
axs[1, 1].legend()
plt.show()
数据生成:我们生成了一个1000个样本的虚拟数据集,具有两个特征。目标值
y
是由两个特征的线性组合加上一定的噪声生成的。模型训练:使用
KNeighborsRegressor
进行回归拟合,设置邻居数为5。
图1:绘制真实值和预测值的散点图,以评估模型的拟合情况。红色点为测试集,蓝色点为训练集。绿色虚线表示理想情况下的完美拟合线。 图2:绘制残差图,观察预测值与真实值之间的误差。残差越接近0,表示模型的拟合效果越好。 图3:用三维图显示测试集的两个特征及其真实值和预测值,便于从多个维度直观观察模型的拟合效果。 图4:通过学习曲线分析模型的偏差和方差,展示训练集大小与模型性能的关系。
10. 梯度提升回归
梯度提升是一种集成学习方法,它通过构建多个弱学习器(通常是决策树)来提高预测的精度。每一棵新树都拟合前一棵树的残差,从而逐步优化模型。
原理
梯度提升模型通过逐步添加决策树,每一棵新的树都是对前一棵树的残差进行拟合。新加入的树通过梯度下降的方式最小化损失函数,从而提高整体模型的表现。
核心公式
假设当前模型为 ,则更新后的模型为:
其中, 是学习率, 是拟合的残差。
梯度提升的目标是最小化损失函数 。对每一轮,我们计算残差:
然后拟合一个弱学习器来逼近残差,更新模型为:
Python实现
import numpy as np
import matplotlib.pyplot as plt
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_regression
from sklearn.metrics import mean_squared_error
# 生成虚拟回归数据集
X, y = make_regression(n_samples=1000, n_features=10, noise=0.5, random_state=42)
# 将数据集分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建梯度提升回归模型
gbr = GradientBoostingRegressor(n_estimators=100, learning_rate=0.1, max_depth=3, random_state=42)
gbr.fit(X_train, y_train)
# 预测测试集
y_pred = gbr.predict(X_test)
# 计算残差
residuals = y_test - y_pred
# 获取特征重要性
feature_importance = gbr.feature_importances_
# 创建子图,所有图绘制在一个图像中
fig, axs = plt.subplots(2, 2, figsize=(12, 10))
# 图1:实际值与预测值的散点图
axs[0, 0].scatter(y_test, y_pred, color='cyan', alpha=0.6, edgecolor='k')
axs[0, 0].plot([min(y_test), max(y_test)], [min(y_test), max(y_test)], 'r--', lw=2)
axs[0, 0].set_title('Actual vs Predicted')
axs[0, 0].set_xlabel('Actual Values')
axs[0, 0].set_ylabel('Predicted Values')
# 图2:残差图
axs[0, 1].scatter(y_pred, residuals, color='magenta', alpha=0.6, edgecolor='k')
axs[0, 1].axhline(y=0, color='r', linestyle='--', lw=2)
axs[0, 1].set_title('Residual Plot')
axs[0, 1].set_xlabel('Predicted Values')
axs[0, 1].set_ylabel('Residuals')
# 图3:特征重要性图
axs[1, 0].barh(np.arange(len(feature_importance)), feature_importance, color='limegreen', edgecolor='k')
axs[1, 0].set_yticks(np.arange(len(feature_importance)))
axs[1, 0].set_yticklabels([f'Feature {i}' for i in range(X.shape[1])])
axs[1, 0].set_title('Feature Importance')
axs[1, 0].set_xlabel('Importance')
# 调整布局
plt.tight_layout()
plt.show()
实际值与预测值的散点图:通过绘制真实值与预测值的关系,能够直观地查看模型预测的准确度。当数据点接近红色虚线时,表示模型预测得较好。
残差图:残差图通过展示预测值与残差的关系,帮助发现模型是否存在系统性的误差。理想情况下,残差应均匀分布在0附近,而不是呈现某种模式。
特征重要性条形图:这个图形帮助我们理解哪些特征对模型预测结果影响较大。特征的重要性值越高,说明该特征对模型预测结果的贡献越大。
最后