1. 为什么load_boston被移除了?

如果你最近在用Python 3.11或者更高版本的scikit-learn做机器学习项目,可能会发现一个奇怪的现象:以前常用的 load_boston() 函数突然报错了。这不是你的代码写错了,而是scikit-learn在1.2版本中主动移除了这个函数。

背后的原因其实很有意思。波士顿房价数据集是机器学习领域最经典的数据集之一,从1978年发布以来一直被广泛使用。但近年来,数据科学社区发现这个数据集存在一个严重的伦理问题——它包含了一个名为"B"的变量,这个变量实际上反映了社区的种族构成比例。原始研究假设这个因素会影响房价,这种假设本身就带有种族歧视的色彩。

scikit-learn维护团队经过讨论后决定,除非是专门研究机器学习伦理问题的场景,否则不应该继续使用这个数据集。这也是为什么在1.2版本后,你直接调用 load_boston() 会收到一个明确的错误提示,而不是默默地加载数据。

2. 官方推荐的替代方案

既然官方不建议使用波士顿房价数据集了,那我们应该用什么数据来做回归分析的练习呢?scikit-learn官方文档给出了两个不错的替代选择:

2.1 加州房价数据集

这是scikit-learn现在主推的回归分析数据集,使用方法非常简单:

from sklearn.datasets import fetch_california_housing

housing = fetch_california_housing()
X = housing.data
y = housing.target

这个数据集包含了1990年加州人口普查中的房价信息,特点是:

  • 样本量更大:20640条记录
  • 特征更丰富:8个特征维度
  • 没有伦理争议
  • 数据更新:相比波士顿数据集晚了十几年

我实测下来发现,这个数据集做回归分析的效果其实比波士顿数据集更好,因为样本量更大,特征工程的空间也更广。

2.2 Ames房价数据集

如果你想要一个更接近波士顿数据集规模的选择,可以试试Ames数据集:

from sklearn.datasets import fetch_openml

housing = fetch_openml(name="house_prices", as_frame=True)

这个数据集包含了2011年爱荷华州Ames市的房价信息,特点是:

  • 样本量适中:2930条记录
  • 特征详细:80个特征维度
  • 包含更多现代房屋特征
  • 需要从OpenML平台下载

不过要注意,这个数据集返回的是Pandas DataFrame格式,如果你习惯用NumPy数组,需要额外做转换。

3. 如何继续使用波士顿数据集

我知道有些教学场景还是需要用到波士顿数据集,毕竟那么多教材和教程都是基于它写的。如果你确实需要使用这个数据集,官方也提供了从原始来源直接加载的方法:

import pandas as pd
import numpy as np

data_url = "http://lib.stat.cmu.edu/datasets/boston"
raw_df = pd.read_csv(data_url, sep="\s+", skiprows=22, header=None)
data = np.hstack([raw_df.values[::2, :], raw_df.values[1::2, :2]])
target = raw_df.values[1::2, 2]

这段代码看起来有点复杂,我来解释下:

  1. 数据来自卡内基梅隆大学的统计库
  2. 原始数据是固定宽度的文本格式
  3. 需要跳过前22行说明文字
  4. 特征数据和目标值被交替存储,所以需要特殊处理

我建议把这部分代码封装成一个函数,方便重复使用:

def load_boston_alternative():
    data_url = "http://lib.stat.cmu.edu/datasets/boston"
    raw_df = pd.read_csv(data_url, sep="\s+", skiprows=22, header=None)
    data = np.hstack([raw_df.values[::2, :], raw_df.values[1::2, :2]])
    target = raw_df.values[1::2, 2]
    return data, target

4. 不同方案的对比与选择

面对这么多选择,到底该用哪个呢?我整理了一个对比表格帮你决策:

方案 数据来源 样本量 特征数 伦理风险 加载速度 适用场景
原load_boston sklearn内置 506 13 快(已移除) 不推荐
加州房价 sklearn内置 20640 8 推荐首选
Ames房价 OpenML 2930 80 慢(需下载) 复杂分析
原始URL CMU统计库 506 13 中等 必须用原数据时

根据我的经验,如果是教学演示,加州房价数据集完全够用;如果是真实项目,Ames数据集可能更有价值;只有当你必须复现旧代码时,才考虑从原始URL加载波士顿数据。

5. 迁移现有代码的实用技巧

如果你手头已经有基于波士顿数据集的代码,迁移到新数据集需要注意几个关键点:

  1. 特征名称变化:新数据集的列名完全不同,需要调整特征选择代码
  2. 数据规模差异:加州数据集大了40倍,可能需要调整测试集比例
  3. 数据分布不同:新数据的目标值范围需要重新探索
  4. 模型评估标准:误差范围可能需要重新设定

这里提供一个迁移示例,把原来的波士顿代码适配到加州数据集:

# 原波士顿代码
from sklearn.datasets import load_boston
from sklearn.linear_model import LinearRegression

boston = load_boston()
X, y = boston.data, boston.target
model = LinearRegression().fit(X, y)

# 迁移后的加州代码
from sklearn.datasets import fetch_california_housing

housing = fetch_california_housing()
X, y = housing.data, housing.target
model = LinearRegression().fit(X, y)

看起来改动不大,但实际使用中你可能需要:

  • 调整可视化代码的坐标轴范围
  • 修改特征工程的管道
  • 重新调参优化模型

我在迁移自己的项目时发现,加州数据集对线性回归的挑战更大,因为特征间相关性更强,可能需要引入正则化。

6. 常见问题与解决方案

在实际操作中,你可能会遇到这些问题:

问题1 :从原始URL加载的数据没有特征名怎么办?

解决方案:可以手动添加特征名列表:

feature_names = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 
                 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT']
df = pd.DataFrame(data, columns=feature_names)

问题2 :加州数据集加载速度慢?

解决方案:第一次加载会下载约2MB的数据,可以缓存到本地:

from sklearn.datasets import fetch_california_housing
from joblib import Memory

memory = Memory(location='./cache')
fetch_california_housing_cached = memory.cache(fetch_california_housing)
housing = fetch_california_housing_cached()

问题3 :Ames数据集太大,内存不够?

解决方案:可以只加载部分特征:

housing = fetch_openml(name="house_prices", as_frame=True)
selected_features = ['LotArea', 'OverallQual', 'YearBuilt', 'TotRmsAbvGrd']
X = housing.data[selected_features]
y = housing.target

7. 最佳实践建议

经过多次项目实践,我总结出几个经验:

  1. 新项目一律使用加州或Ames数据集,避免伦理风险
  2. 教学场景可以继续使用波士顿数据,但要说明其历史背景
  3. 从原始URL加载时,建议添加异常处理:
try:
    raw_df = pd.read_csv(data_url, sep="\s+", skiprows=22, header=None)
except Exception as e:
    print(f"加载失败: {e}")
    # 备用方案
    data_url = "备用镜像URL"
    raw_df = pd.read_csv(data_url, sep="\s+", skiprows=22, header=None)
  1. 对数据做探索性分析时,特别注意检查特征间的相关性
  2. 考虑数据集的时效性,加州数据是1990年的,对现代房价预测可能不够准确

8. 更深入的数据探索

如果你不满足于基本用法,可以尝试这些进阶操作:

获取完整的数据描述

print(housing.DESCR)  # 加州数据集
print(fetch_openml(name="house_prices", as_frame=True).DESCR)  # Ames数据集

转换为Pandas DataFrame并添加目标列

df = pd.DataFrame(housing.data, columns=housing.feature_names)
df['MedHouseVal'] = housing.target

可视化特征分布

import seaborn as sns
import matplotlib.pyplot as plt

sns.pairplot(df[['MedInc', 'HouseAge', 'AveRooms', 'AveBedrms', 'MedHouseVal']])
plt.show()

创建交互式可视化

import plotly.express as px

fig = px.scatter_3d(df, x='MedInc', y='AveRooms', z='MedHouseVal',
                    color='HouseAge', opacity=0.7)
fig.show()

这些技巧能帮你更深入地理解数据,为后续建模打下更好基础。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐