你好,我是kk~
继续总结大家在面试中遇到的各种情况。
最近有一个小伙伴面试了小红薯,结果一系列失误的情况出现了。在面试之前听有的小伙伴说小红书注重项目,结果面试的时候,由于面试官性格的原因,一直怼基础。
第一个问题就是关于「岭回归」的问题。咱们今儿来好好说说~
首先,岭回归是一种用于解决多重共线性问题的线性回归方法。
当数据的自变量(特征)之间存在较强的相关性时,普通最小二乘(Ordinary Least Squares, OLS)回归的结果可能会变得不稳定,导致模型的方差增大,进而影响预测的精度。
岭回归通过在损失函数中加入惩罚项,能够在一定程度上抑制这种不稳定性。
1. 岭回归基本原理
岭回归的损失函数
岭回归的目标是在最小化均方误差(MSE)的基础上增加一个对模型参数的惩罚项。其损失函数可以表示为:
其中:
表示实际值 是预测值,定义为 表示第 个样本的特征向量 是模型参数向量 是正则化参数(或称为惩罚系数),控制惩罚项对损失的影响
当 时,岭回归退化为普通的线性回归;而当 时,模型参数会被强制趋近于 0,从而实现更强的正则化。
问题的推导
首先,回归的损失函数可以表示为:
展开后得到:
为简化运算,我们对 求导并设其为零,从而得到岭回归的闭式解:
化简得:
因此,岭回归的参数解可以表示为:
其中, 是一个 的单位矩阵。通过引入 ,原本不可逆的 矩阵得以变成可逆矩阵,从而可以求出解。
2. 岭回归的作用与优势
抑制多重共线性
当特征之间高度相关时, 可能会接近奇异矩阵,导致其逆矩阵不稳定或不可求。通过在 中加入 ,岭回归可以使得该矩阵变得更加稳定。
防止过拟合
岭回归的惩罚项限制了模型的参数幅度,从而避免模型对训练数据的过度拟合。对于噪声较大的数据集,岭回归能够减少方差,使得模型的预测更加鲁棒。
3. 使用 Python 进行岭回归建模
接下来,我们通过一个虚拟数据集的实际案例来演示如何使用 Python 进行岭回归的模型训练、评估以及绘图。
数据生成与数据可视化
我们首先生成一个包含多重共线性的虚拟数据集。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import Ridge
from sklearn.metrics import mean_squared_error
from mpl_toolkits.mplot3d import Axes3D
# 设置随机种子以便复现
np.random.seed(42)
# 生成虚拟数据
n_samples = 100
X = np.random.rand(n_samples, 2) * 10 # 两个特征,范围在0到10之间
y = 3 * X[:, 0] + 2 * X[:, 1] + np.random.randn(n_samples) * 2 # 加入噪声
# 数据拆分
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 绘制数据分布
fig = plt.figure(figsize=(12, 6))
ax = fig.add_subplot(121, projection='3d')
sc = ax.scatter(X[:, 0], X[:, 1], y, c=y, cmap='viridis', edgecolor='k', s=50)
plt.colorbar(sc)
ax.set_xlabel("Feature 1")
ax.set_ylabel("Feature 2")
ax.set_zlabel("Target")
ax.set_title("3D Scatter Plot of the Data")
ax2 = fig.add_subplot(122)
plt.scatter(X[:, 0], y, color='b', label='Feature 1', alpha=0.6, edgecolor='k')
plt.scatter(X[:, 1], y, color='r', label='Feature 2', alpha=0.6, edgecolor='k')
plt.xlabel("Feature Value")
plt.ylabel("Target Value")
plt.legend()
plt.title("Projection of Features vs Target")
plt.show()
岭回归模型训练与测试
# 定义不同的惩罚系数
lambdas = [0.1, 1, 10, 100, 1000]
ridge_models = []
mse_train = []
mse_test = []
for lam in lambdas:
ridge = Ridge(alpha=lam)
ridge.fit(X_train, y_train)
ridge_models.append(ridge)
# 计算训练和测试误差
y_train_pred = ridge.predict(X_train)
y_test_pred = ridge.predict(X_test)
mse_train.append(mean_squared_error(y_train, y_train_pred))
mse_test.append(mean_squared_error(y_test, y_test_pred))
# 绘制不同惩罚系数下的MSE变化
plt.figure(figsize=(10, 6))
plt.plot(lambdas, mse_train, label='Train MSE', marker='o', color='blue', linewidth=2)
plt.plot(lambdas, mse_test, label='Test MSE', marker='o', color='red', linewidth=2)
plt.xscale('log')
plt.xlabel('Lambda (Regularization Strength)')
plt.ylabel('Mean Squared Error')
plt.title('Effect of Regularization on Training and Testing Error')
plt.legend()
plt.grid(True)
plt.show()
参数影响的可视化
我们进一步分析不同的正则化参数对模型系数的影响。
# 绘制不同惩罚系数下的系数变化
coeffs = [ridge.coef_ for ridge in ridge_models]
plt.figure(figsize=(10, 6))
plt.plot(lambdas, [coef[0] for coef in coeffs], label='Coefficient of Feature 1', marker='o', color='purple', linewidth=2)
plt.plot(lambdas, [coef[1] for coef in coeffs], label='Coefficient of Feature 2', marker='o', color='green', linewidth=2)
plt.xscale('log')
plt.xlabel('Lambda (Regularization Strength)')
plt.ylabel('Coefficient Value')
plt.title('Effect of Regularization on Coefficients')
plt.legend()
plt.grid(True)
plt.show()
通过图像我们可以发现:
当 较小(接近于 0)时,岭回归与普通最小二乘法的结果相近,模型较容易出现过拟合; 随着 的增大,模型的系数逐渐被收缩,有效抑制了特征之间的共线性,降低了模型的方差,从而改善了泛化性能。