字节一面,贼细致。。

文摘   2024-11-19 17:15   北京  

我们在初学kaggle比赛时,可以找一些金牌or优秀解决方案参考学习。我已经整理好了,大家可以扫码领取(下滑更多干货内容)

金牌优秀解决方案
扫码领

哈喽,我是kk~

昨天,有同学反映,在字节的一面中居然问到了弹性网回归,这对于他来说,应该是非常简单。

毕竟刚刚毕业,虽然是重新找工作,但是对于基础理论的把握还是非常好的。

下面,咱们也把 弹性网回归 总结了一遍,和大家聊聊~

弹性网回归(Elastic Net Regression)是一种结合了岭回归(Ridge Regression)和Lasso回归(Lasso Regression)优点的线性回归方法。它在处理高维数据时表现得尤为出色,特别是当特征数目大于样本数目,或特征之间存在共线性时。

基本原理

弹性网回归的核心思想是通过正则化(regularization)来防止模型过拟合。在回归分析中,正则化技术用于控制模型复杂度,从而提高泛化能力。

目标函数

弹性网回归的目标函数可以表示为最小化以下损失函数:

其中:

  •  是实际输出, 是模型预测值。
  •  是样本数。
  •  是特征数。
  •  是回归系数。
  •  和  是正则化参数,分别对应Lasso和Ridge部分的惩罚。

各部分

  1. 平方误差项 是普通最小二乘法(OLS)损失,旨在最小化预测值与实际值之间的差异。

  2. L1 正则化(Lasso) 增加了对模型稀疏性的约束,通过促使某些系数为零,实现特征选择。

  3. L2 正则化(Ridge) 则用于抑制模型复杂度,使得系数分布更均匀,特别是在特征间存在多重共线性时,能够稳定系数估计。

优势

弹性网回归的主要优势在于:

  • 特征选择:通过L1正则化,弹性网可以有效地选择重要特征,同时丢弃不重要的特征。
  • 处理多重共线性:L2正则化部分能够有效处理特征之间的共线性问题,使得模型更稳定。
  • 灵活性:通过调整  和 ,可以在Lasso和Ridge之间进行平衡,适应不同的数据特征。

参数选择

选择合适的  和  是弹性网回归的关键,通常可以使用交叉验证(cross-validation)来找到最佳参数组合。具体步骤如下:

  1. 划分训练集和验证集
  2. 对不同的  和  值进行网格搜索
  3. 在验证集上评估模型性能,选择使得验证集误差最小的参数组合。

手推公式

弹性网回归的解可以通过坐标下降法(coordinate descent)来求解。在每一步中,固定所有其他变量,逐个更新回归系数 

更新公式

对于每一个系数 ,更新公式为:

其中, 是软阈值函数(soft thresholding function):

弹性网回归是一种强大且灵活的回归方法,能够有效地处理多维数据问题,兼具特征选择和稳定性的优势。通过适当的正则化参数选择,能够显著提升模型的预测性能和解释能力。

案例

在这个案例中,我们模拟一个房价预测的场景。我们将生成一些虚拟数据,包括房屋的特征(如面积、卧室数量、楼层等),然后使用弹性网回归模型来预测房价。我们将创建多种可视化图形来展示数据和模型的表现。

1. 数据生成

首先,我们需要生成一个虚拟数据集。这些特征将是随机生成的,以模拟现实世界中的特征。

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

# 设置随机种子以确保可重复性
np.random.seed(42)

# 生成样本数和特征数
n_samples = 300
n_features = 10

# 生成随机特征
X = np.random.rand(n_samples, n_features) * 100  # 特征范围在0-100
true_coefficients = np.array([3-2050-10000])  # 真实的系数
y = X @ true_coefficients + np.random.normal(010, n_samples)  # 添加一些噪声

# 创建DataFrame
feature_names = [f'Feature {i+1}' for i in range(n_features)]
data = pd.DataFrame(X, columns=feature_names)
data['Price'] = y

# 展示前5行数据
print(data.head())

2. 数据可视化

在训练模型之前,我们可以通过一些图形来观察数据的分布。

2.1 特征与目标变量的关系

我们将展示前两个特征与房价之间的关系。

# 特征与目标变量的关系
plt.figure(figsize=(146))

# Feature 1
plt.subplot(121)
sns.scatterplot(x=data['Feature 1'], y=data['Price'], color='skyblue', s=50)
plt.title('Feature 1 vs Price', fontsize=16)
plt.xlabel('Feature 1', fontsize=14)
plt.ylabel('Price', fontsize=14)
plt.grid(True)

# Feature 2
plt.subplot(122)
sns.scatterplot(x=data['Feature 2'], y=data['Price'], color='salmon', s=50)
plt.title('Feature 2 vs Price', fontsize=16)
plt.xlabel('Feature 2', fontsize=14)
plt.ylabel('Price', fontsize=14)
plt.grid(True)

plt.tight_layout()
plt.show()

3. 模型训练

现在我们可以使用弹性网回归来训练模型。我们将使用sklearn库来实现这一点。

from sklearn.model_selection import train_test_split
from sklearn.linear_model import ElasticNet
from sklearn.metrics import mean_squared_error, r2_score

# 拆分数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 初始化弹性网回归模型
elastic_net = ElasticNet(alpha=1.0, l1_ratio=0.5, random_state=42)

# 训练模型
elastic_net.fit(X_train, y_train)

# 预测
y_pred = elastic_net.predict(X_test)

# 计算模型性能
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)

print(f'Mean Squared Error: {mse:.2f}')
print(f'R^2 Score: {r2:.2f}')

4. 模型可视化

为了更好地理解模型的表现,我们可以绘制实际房价与预测房价之间的关系图。

4.1 实际与预测值的比较
# 实际值与预测值的比较
plt.figure(figsize=(106))
plt.scatter(y_test, y_pred, color='orange', alpha=0.7, s=100)
plt.plot([min(y_test), max(y_test)], [min(y_test), max(y_test)], color='blue', linestyle='--', lw=2)
plt.title('Actual vs Predicted Prices', fontsize=16)
plt.xlabel('Actual Prices', fontsize=14)
plt.ylabel('Predicted Prices', fontsize=14)
plt.grid(True)
plt.xlim(min(y_test) - 10, max(y_test) + 10)
plt.ylim(min(y_test) - 10, max(y_test) + 10)
plt.show()

4.2 系数的可视化

我们可以通过条形图展示弹性网模型所学到的系数。

# 系数可视化
coefficients = elastic_net.coef_

plt.figure(figsize=(126))
sns.barplot(x=feature_names, y=coefficients, palette='viridis')  # 使用 feature_names
plt.title('Elastic Net Coefficients', fontsize=16)
plt.xlabel('Features', fontsize=14)
plt.ylabel('Coefficient Values', fontsize=14)
plt.xticks(rotation=45)
plt.grid(True)
plt.show()

5. 调参与交叉验证

为了找到最佳的正则化参数,我们可以使用交叉验证的方法来评估不同的  和 

from sklearn.model_selection import GridSearchCV

# 网格搜索参数
param_grid = {
    'alpha': [0.10.51.01.52.0],
    'l1_ratio': [0.10.30.50.70.9]
}

# 初始化弹性网回归模型
elastic_net_cv = ElasticNet(random_state=42)

# 网格搜索
grid_search = GridSearchCV(elastic_net_cv, param_grid, cv=5, scoring='neg_mean_squared_error')
grid_search.fit(X_train, y_train)

# 输出最佳参数
print(f'Best Alpha: {grid_search.best_params_["alpha"]}')
print(f'Best L1 Ratio: {grid_search.best_params_["l1_ratio"]}')

6. 最终模型评估

使用最佳参数重新训练模型并进行最终评估。

# 使用最佳参数训练模型
best_model = ElasticNet(alpha=grid_search.best_params_['alpha'], 
                         l1_ratio=grid_search.best_params_['l1_ratio'], 
                         random_state=42)
best_model.fit(X_train, y_train)
y_pred_final = best_model.predict(X_test)

# 计算最终模型性能
final_mse = mean_squared_error(y_test, y_pred_final)
final_r2 = r2_score(y_test, y_pred_final)

print(f'Final Mean Squared Error: {final_mse:.2f}')
print(f'Final R^2 Score: {final_r2:.2f}')

7. 完整代码总结

将以上所有代码整合到一起,形成一个完整的示例。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.linear_model import ElasticNet
from sklearn.metrics import mean_squared_error, r2_score

# 设置随机种子
np.random.seed(42)

# 生成样本数和特征数
n_samples = 300
n_features = 10
X = np.random.rand(n_samples, n_features) * 100
true_coefficients = np.array([3-2050-10000])
y = X @ true_coefficients + np.random.normal(010, n_samples)

# 创建DataFrame
feature_names = [f'Feature {i+1}' for i in range(n_features)]
data = pd.DataFrame(X, columns=feature_names)
data['Price'] = y

# 可视化特征与价格关系
plt.figure(figsize=(146))
plt.subplot(121)
sns.scatterplot(x=data['Feature 1'], y=data['Price'], color='skyblue', s=50)
plt.title('Feature 1 vs Price', fontsize=16)
plt.xlabel('Feature 1', fontsize=14)
plt.ylabel('Price', fontsize=14)
plt.grid(True)

plt.subplot(122)
sns.scatterplot(x=data['Feature 2'], y=data['Price'], color='salmon', s=50)
plt.title('Feature 2 vs Price', fontsize=16)
plt.xlabel('Feature 2', fontsize=14)
plt.ylabel('Price', fontsize=14)
plt.grid(True)
plt.tight_layout()
plt.show()

# 拆分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 训练弹性网回归模型
elastic_net = ElasticNet(alpha=1.0, l1_ratio=0.5, random_state=42)
elastic_net.fit(X_train, y_train)
y_pred = elastic_net.predict(X_test)

# 计算模型性能
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f'Mean Squared Error: {mse:.2f}')
print(f'R^2 Score: {r2:.2f}')

# 实际值与预测值比较
plt.figure(figsize=(106))
plt.scatter(y_test, y_pred, color='orange', alpha=0.7, s=100)
plt.plot([min(y_test), max(y_test)], [min(y_test), max(y_test)], color='blue', linestyle='--', lw=2)
plt.title('Actual vs Predicted Prices', fontsize=16)
plt.xlabel('Actual Prices', fontsize=14)
plt.ylabel('Predicted Prices', fontsize=14)
plt.grid(True)
plt.xlim(min(y_test) - 10, max(y_test) + 10)
plt.ylim(min(y_test) - 10, max(y_test) + 10)
plt.show()

# 系数可视化
coefficients = elastic_net.coef_

plt.figure(figsize=(126))
sns.barplot(x=feature_names, y=coefficients, palette='viridis')  # 使用 feature_names
plt.title('Elastic Net Coefficients', fontsize=16)
plt.xlabel('Features', fontsize=14)
plt.ylabel('Coefficient Values', fontsize=14)
plt.xticks(rotation=45)
plt.grid(True)
plt.show()


# 网格搜索参数
param_grid = {
    'alpha': [0.10.51.01.52.0],
    'l1_ratio': [0.10.30.50.70.9]
}

elastic_net_cv = ElasticNet(random_state=42)
grid_search = GridSearchCV(elastic_net_cv, param_grid, cv=5, scoring='neg_mean_squared_error')
grid_search.fit(X_train, y_train)

print(f'Best Alpha: {grid_search.best_params_["alpha"]}')
print(f'Best L1 Ratio: {grid_search.best_params_["l1_ratio"]}')

# 最终模型评估
best_model = ElasticNet(alpha=grid_search.best_params_['alpha'],
                         l1_ratio=grid_search.best_params_['l1_ratio'],
                         random_state=42)
best_model.fit(X_train, y_train)
y_pred_final = best_model.predict(X_test)

final_mse = mean_squared_error(y_test, y_pred_final)
final_r2 = r2_score(y_test, y_pred_final)
print(f'Final Mean Squared Error: {final_mse:.2f}')
print(f'Final R^2 Score: {final_r2:.2f}')

总结

在这个案例中,我们通过生成虚拟数据集来模拟房价预测的场景,使用弹性网回归模型进行训练和评估,并通过多种可视化手段展示了数据的分布和模型的性能。

都到这里了,点赞~

我们在初学kaggle比赛时,可以找一些金牌or优秀解决方案参考学习。我已经整理好了,大家可以扫码领取(下滑更多干货内容)

金牌优秀解决方案
扫码领


kk机器学习算法
机器学习基础、计算机视觉…
 最新文章