共计 2709 个字符,预计需要花费 7 分钟才能阅读完成。
问题背景
房价预测一直是机器学习领域的经典问题,波士顿房价数据集包含了 13 个特征,如犯罪率、房间数、学区质量等。传统线性回归模型在处理这类数据时面临几个主要挑战:

- 特征尺度差异大(如犯罪率在 0 - 1 之间,而房间数可能达到几十)
- 特征间存在共线性(如房间数与房屋面积高度相关)
- 特征与价格的非线性关系(如学区质量对价格的影响可能是阶跃式的)
这些因素导致线性模型的预测精度往往不理想,R2 分数通常在 0.6-0.7 之间徘徊。
技术方案
网络结构选型
在深度学习模型中,我们主要考虑了两种架构:
- MLP(多层感知机):适合处理结构化数据,参数效率高
- CNN(卷积神经网络):更适合图像等网格化数据
由于我们的数据是典型的表格数据,最终选择了 MLP 架构。
BP 神经网络设计
我们的网络采用经典的三层结构:
- 输入层:13 个神经元,对应 13 个特征维度
- 隐藏层:经过实验,64 个神经元能在模型复杂度和性能间取得平衡
- 输出层:1 个神经元,输出预测的房价值
隐藏层使用 ReLU 激活函数,输出层不使用激活函数(回归任务)。
核心实现
数据预处理
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
# 加载数据
X, y = load_boston(return_X_y=True)
# 数据集划分
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 标准化处理
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test) # 注意:使用训练集的统计量来转换测试集
网络定义
import torch
import torch.nn as nn
class BostonPricePredictor(nn.Module):
def __init__(self, input_dim=13, hidden_dim=64):
super().__init__()
self.fc1 = nn.Linear(input_dim, hidden_dim)
self.relu = nn.ReLU()
self.fc2 = nn.Linear(hidden_dim, 1)
def forward(self, x):
x = self.fc1(x)
x = self.relu(x)
return self.fc2(x)
训练循环
model = BostonPricePredictor().to(device)
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
for epoch in range(100):
model.train()
optimizer.zero_grad()
outputs = model(torch.FloatTensor(X_train).to(device))
loss = criterion(outputs, torch.FloatTensor(y_train).unsqueeze(1).to(device))
loss.backward()
optimizer.step()
# 验证集评估
if epoch % 10 == 0:
model.eval()
with torch.no_grad():
val_outputs = model(torch.FloatTensor(X_test).to(device))
val_loss = criterion(val_outputs, torch.FloatTensor(y_test).unsqueeze(1).to(device))
print(f'Epoch {epoch}, Train Loss: {loss.item():.4f}, Val Loss: {val_loss.item():.4f}')
调优实践
学习率策略对比
我们测试了两种学习率策略:
- 固定学习率(0.001):简单但后期优化缓慢
- StepLR(每 30 个 epoch 乘以 0.1):能更快收敛到更优解
实验表明,StepLR 策略最终 R2 分数能提高约 0.05。
Early Stopping 实现
from torch.optim.lr_scheduler import ReduceLROnPlateau
scheduler = ReduceLROnPlateau(optimizer, 'min', patience=5)
best_loss = float('inf')
patience = 10
counter = 0
for epoch in range(100):
# ... 训练代码...
scheduler.step(val_loss)
if val_loss < best_loss:
best_loss = val_loss
counter = 0
torch.save(model.state_dict(), 'best_model.pth')
else:
counter += 1
if counter >= patience:
print('Early stopping')
break
激活函数对比
在隐藏层测试了两种激活函数:
- ReLU:训练更快,最终 R2=0.91
- Sigmoid:存在梯度消失问题,R2=0.87
生产建议
模型轻量化
PCA 分析显示前 8 个主成分可保留 95% 的方差,可以将输入维度从 13 降到 8,模型大小减少 38% 而精度仅下降 1%。
在线预测
部署时需要保存 scaler 的 mean_和 var_属性,对新数据先进行相同的标准化处理:
# 保存 scaler
import joblib
joblib.dump(scaler, 'scaler.pkl')
# 加载预测时
scaler = joblib.load('scaler.pkl')
new_data = scaler.transform([new_sample])
model.predict(new_data)
监控指标
建议设置 MAE 波动阈值(如±10%),当连续 3 次预测超过阈值时触发告警。
总结与思考
通过系统的特征工程、网络结构设计和调优策略,我们的 BP 神经网络模型在波士顿房价预测任务上取得了 R2=0.91 的优秀表现。相比传统线性模型,深度学习方法能更好地捕捉特征间的复杂非线性关系。
一个值得思考的延伸问题是:如果要处理非结构化数据(如房屋照片),应该如何扩展当前模型?一个可能的方案是将 CNN 提取的图片特征与现有的结构化特征拼接,构建多模态输入模型。这将是未来探索的一个有趣方向。
正文完
