共计 2089 个字符,预计需要花费 6 分钟才能阅读完成。
问题背景
在房价预测任务中,我们常常遇到以下数据挑战:

- 特征尺度差异:如房间数量(单位:间)与房产税(单位:万美元)数值量级相差悬殊
- 特征共线性:如 ’ 距离就业中心距离 ’ 和 ’ 高速公路可达性 ’ 可能存在相关性
- 非线性关系:房价与特征间往往存在复杂非线性关联
传统线性回归模型难以捕捉这些复杂关系。比如当尝试用线性模型拟合波士顿房价数据时,R2 分数通常只能达到 0.6-0.7,这促使我们转向更强大的 BP 神经网络。
技术方案
网络结构选型
在对比不同网络结构后,我们选择多层感知机 (MLP) 是因为:
- CNN 更适合处理网格化数据(如图像)
- RNN/LSTM 对时序数据的优势在房价预测中不显著
- MLP 的通用逼近特性适合处理结构化特征
三层架构设计
- 输入层:13 个神经元,对应数据集的特征维度(CRIM、ZN 等)
- 隐藏层:
- 通过试验确定 128 个神经元(经验公式:输入特征数×2~10 倍)
- 使用 ReLU 激活函数加速收敛
- 输出层:
- 1 个神经元输出预测价格
- 不使用激活函数(回归任务)
核心实现
数据预处理
from sklearn.preprocessing import StandardScaler
import torch
from torch.utils.data import TensorDataset, DataLoader
# 特征标准化(关键步骤)scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 转换为 PyTorch 张量
tensor_X = torch.FloatTensor(X_scaled)
tensor_y = torch.FloatTensor(y).reshape(-1,1)
# 创建 DataLoader
batch_size = 32
dataset = TensorDataset(tensor_X, tensor_y)
dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)
网络定义
import torch.nn as nn
class HousePricePredictor(nn.Module):
def __init__(self, input_dim=13):
super().__init__()
self.fc1 = nn.Linear(input_dim, 128)
self.fc2 = nn.Linear(128, 64)
self.fc3 = nn.Linear(64, 1)
self.dropout = nn.Dropout(0.2) # 防止过拟合
def forward(self, x):
x = torch.relu(self.fc1(x))
x = self.dropout(x)
x = torch.relu(self.fc2(x))
return self.fc3(x)
调优实践
学习率策略对比
- 固定学习率(0.01):
- 训练初期收敛快
-
后期在最优值附近震荡
-
StepLR(每 30 个 epoch 衰减为 0.1 倍):
- 初始 lr=0.05
- 稳定收敛至更优解
Early Stopping 实现
from copy import deepcopy
best_loss = float('inf')
patience = 10
counter = 0
best_model = None
for epoch in range(100):
model.train()
for X_batch, y_batch in dataloader:
# ... 训练代码...
val_loss = validate(model)
if val_loss < best_loss:
best_loss = val_loss
best_model = deepcopy(model)
counter = 0
else:
counter += 1
if counter >= patience:
print(f'Early stopping at epoch {epoch}')
break
激活函数对比
| 激活函数 | 验证集 R2 | 训练时间 |
|---|---|---|
| ReLU | 0.91 | 2m30s |
| Sigmoid | 0.87 | 3m15s |
生产建议
模型轻量化
- PCA 降维:当特征数从 13 减至 8 时,R2 仅下降 0.02
- 量化:FP32→INT8 使模型大小减少 75%
在线预测
# 保存 scaler 用于线上环境
import joblib
joblib.dump(scaler, 'scaler.pkl')
# 预测时使用相同的 scaler
def predict(new_data):
scaled_data = scaler.transform(new_data)
return model(torch.FloatTensor(scaled_data))
监控指标
- 设置 MAE 波动阈值:当连续 3 次预测 MAE > 0.5 时触发告警
- 特征漂移检测:定期计算线上数据与训练数据的 KL 散度
总结与思考
通过系统的特征工程、网络结构设计和调优策略,我们成功将模型 R2 分数提升至 0.9+。完整的 PyTorch 实现代码已放在 GitHub 仓库(伪代码)。
最后一个开放性问题:如果要处理非结构化数据(如房屋照片),如何扩展当前模型?可以考虑:
- 使用 CNN 提取图像特征
- 将结构化特征与图像特征在全连接层前拼接
- 设计多任务学习框架
期待在评论区看到你的创新方案!
正文完
