机器学习入门的经典案例中,鸢尾花分类(K近邻KNN算法)是分类任务的代表,房价预测(线性回归算法)是回归任务的典型。这两个案例能帮助初学者快速理解机器学习的核心流程:数据加载与探索、预处理、模型构建、训练、评估与预测。

一、准备工作:安装必备库

实现这两个案例需要Python的机器学习基础库,其中scikit-learn是核心(内置经典数据集和算法),pandas用于数据处理,numpy用于数值计算,matplotlib用于数据可视化。执行以下命令安装依赖:

pip install scikit-learn pandas numpy matplotlib

库功能说明:

  • scikit-learn:提供数据集、数据划分、模型构建、评估指标等一站式机器学习工具;
  • pandas:高效处理结构化数据,查看数据特征与分布;
  • numpy:处理数组与矩阵运算,支撑机器学习的数值计算;
  • matplotlib:绘制数据可视化图表,直观展示数据特征与模型结果。

二、鸢尾花分类:K近邻(KNN)算法实战

2.1 案例背景与数据集介绍

鸢尾花数据集(Iris Dataset)是机器学习领域的“Hello World”,由统计学家Fisher于1936年提出。数据集包含150个样本,分为3个鸢尾花品种(山鸢尾、变色鸢尾、维吉尼亚鸢尾),每个样本有4个特征:花萼长度、花萼宽度、花瓣长度、花瓣宽度。我们的目标是通过这4个特征,用KNN算法实现对鸢尾花品种的分类。

2.2 步骤1:加载与探索数据集

首先从scikit-learn中加载鸢尾花数据集,并通过可视化和统计方法探索数据特征:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris

# 加载数据集
iris = load_iris()
# 转换为DataFrame,方便数据探索
iris_df = pd.DataFrame(data=iris.data, columns=iris.feature_names)
# 添加标签列(品种)
iris_df['species'] = [iris.target_names[i] for i in iris.target]

# 1. 查看数据前5行
print("数据集前5行:")
print(iris_df.head())

# 2. 数据基本统计信息
print("\n数据统计信息:")
print(iris_df.describe())

# 3. 查看样本分布(每个品种的数量)
print("\n各品种样本数量:")
print(iris_df['species'].value_counts())

# 4. 可视化:花瓣长度vs花瓣宽度(按品种着色)
plt.figure(figsize=(8, 6))
colors = ['red', 'green', 'blue']
species = iris.target_names
for i in range(3):
    # 筛选每个品种的数据
    data = iris_df[iris_df['species'] == species[i]]
    plt.scatter(data['petal length (cm)'], data['petal width (cm)'], 
                c=colors[i], label=species[i], alpha=0.8)
plt.xlabel('花瓣长度(cm)')
plt.ylabel('花瓣宽度(cm)')
plt.title('鸢尾花花瓣长度与宽度分布')
plt.legend()
plt.show()

数据探索结论:从可视化图表能明显看到,不同品种的鸢尾花在花瓣长度和宽度上有显著的聚类特征,这也是KNN算法能有效分类的基础。

2.3 步骤2:数据预处理

KNN算法基于距离计算进行分类,对特征的尺度敏感(比如花萼长度以厘米为单位,数值范围是4-7,而花瓣宽度是0.1-2.5,若不标准化,距离会被大数值特征主导)。因此需要对特征进行标准化,并划分训练集和测试集。

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

# 1. 分离特征与标签
X = iris.data  # 特征矩阵
y = iris.target  # 标签

# 2. 划分训练集(70%)和测试集(30%)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42, stratify=y)
# stratify=y:保证训练集和测试集中各品种的比例与原数据一致

# 3. 特征标准化
scaler = StandardScaler()
# 仅在训练集上拟合scaler,避免测试集数据泄露
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

print(f"训练集特征形状:{X_train_scaled.shape}")
print(f"测试集特征形状:{X_test_scaled.shape}")

2.4 步骤3:构建KNN模型并训练

KNN算法的核心参数是K值(近邻数),K值过小易过拟合,K值过大易欠拟合。这里先选择K=3,后续通过交叉验证优化K值。

from sklearn.neighbors import KNeighborsClassifier

# 构建KNN模型
knn = KNeighborsClassifier(n_neighbors=3)  # n_neighbors即K值

# 训练模型(KNN是惰性学习算法,训练过程仅存储训练集数据)
knn.fit(X_train_scaled, y_train)

2.5 步骤4:模型评估

用测试集评估模型性能,主要指标包括准确率(整体分类正确的比例)、混淆矩阵(展示各类别的预测错误情况)、分类报告(精确率、召回率、F1值)。

from sklearn.metrics import accuracy_score, confusion_matrix, classification_report

# 1. 测试集预测
y_pred = knn.predict(X_test_scaled)

# 2. 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"模型测试集准确率:{accuracy:.2f}")

# 3. 混淆矩阵
print("\n混淆矩阵:")
print(confusion_matrix(y_test, y_pred))

# 4. 分类报告
print("\n分类报告:")
print(classification_report(y_test, y_pred, target_names=iris.target_names))

结果解读:K=3时,鸢尾花分类的准确率通常能达到95%以上,混淆矩阵中少数错误主要出现在变色鸢尾和维吉尼亚鸢尾的边界样本上,这是因为这两个品种的特征相似度较高。

2.6 步骤5:优化K值(交叉验证)

通过网格搜索+交叉验证选择最优K值,避免单一测试集带来的结果偏差:

from sklearn.model_selection import GridSearchCV

# 定义K值候选范围
param_grid = {'n_neighbors': [1, 3, 5, 7, 9, 11]}

# 网格搜索:5折交叉验证
grid_search = GridSearchCV(KNeighborsClassifier(), param_grid, cv=5, scoring='accuracy')
grid_search.fit(X_train_scaled, y_train)

# 输出最优参数和最优得分
print(f"最优K值:{grid_search.best_params_['n_neighbors']}")
print(f"交叉验证最优准确率:{grid_search.best_score_:.2f}")

# 用最优模型评估测试集
best_knn = grid_search.best_estimator_
y_pred_best = best_knn.predict(X_test_scaled)
print(f"最优模型测试集准确率:{accuracy_score(y_test, y_pred_best):.2f}")

2.7 步骤6:用新数据进行预测

训练好的模型可用于新样本的品种预测,注意新数据需要和训练集一样进行标准化:

# 模拟新样本:[花萼长度, 花萼宽度, 花瓣长度, 花瓣宽度]
new_sample = np.array([[5.1, 3.5, 1.4, 0.2]])  # 山鸢尾的典型特征

# 特征标准化
new_sample_scaled = scaler.transform(new_sample)

# 预测品种
pred = best_knn.predict(new_sample_scaled)
pred_proba = best_knn.predict_proba(new_sample_scaled)  # 预测概率

print(f"新样本预测品种:{iris.target_names[pred[0]]}")
print(f"各品种预测概率:{pred_proba[0]}")

三、房价预测:线性回归算法实战

3.1 案例背景与数据集介绍

房价预测是典型的回归任务(预测连续值),本文使用scikit-learn加州房价数据集(California Housing Dataset),该数据集包含20640个样本,8个特征(如平均收入、房屋年龄、房间数等),目标是预测房屋的中位数价格(单位:万美元)。

3.2 步骤1:加载与探索数据集

from sklearn.datasets import fetch_california_housing

# 加载加州房价数据集
housing = fetch_california_housing()
housing_df = pd.DataFrame(data=housing.data, columns=housing.feature_names)
# 添加房价标签列
housing_df['MedHouseVal'] = housing.target

# 1. 查看数据前5行
print("数据集前5行:")
print(housing_df.head())

# 2. 数据基本统计信息
print("\n数据统计信息:")
print(housing_df.describe())

# 3. 查看缺失值(该数据集无缺失值,实际项目中需处理)
print("\n缺失值数量:")
print(housing_df.isnull().sum())

# 4. 特征与房价的相关性分析
corr = housing_df.corr()['MedHouseVal'].sort_values(ascending=False)
print("\n特征与房价的相关性:")
print(corr)

# 5. 可视化:平均收入vs房价
plt.figure(figsize=(8, 6))
plt.scatter(housing_df['MedInc'], housing_df['MedHouseVal'], alpha=0.5)
plt.xlabel('平均收入(万元)')
plt.ylabel('房屋中位数价格(万美元)')
plt.title('加州房价与平均收入的关系')
plt.show()

数据探索结论:平均收入(MedInc)与房价的相关性最高(正相关),房屋年龄、房间数等特征也有一定相关性。

3.3 步骤2:数据预处理

线性回归对特征尺度不敏感,但标准化能加速模型收敛;同时需划分训练集和测试集,避免数据泄露。

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

# 1. 分离特征与标签
X = housing.data  # 特征矩阵
y = housing.target  # 房价标签

# 2. 划分训练集(80%)和测试集(20%)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 3. 特征标准化
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

print(f"训练集特征形状:{X_train_scaled.shape}")
print(f"测试集特征形状:{X_test_scaled.shape}")

3.4 步骤3:构建线性回归模型并训练

使用scikit-learnLinearRegression实现普通最小二乘线性回归:

from sklearn.linear_model import LinearRegression

# 构建线性回归模型
lr = LinearRegression()

# 训练模型
lr.fit(X_train_scaled, y_train)

# 输出模型系数(权重)和截距
print("模型系数(各特征权重):")
for feature, coef in zip(housing.feature_names, lr.coef_):
    print(f"{feature}: {coef:.2f}")
print(f"模型截距:{lr.intercept_:.2f}")

系数解读:系数为正表示该特征与房价正相关(如平均收入),系数为负表示负相关(如平均房间数过多可能代表房屋老旧,房价偏低)。

3.5 步骤4:模型评估

回归任务的评估指标主要有平均绝对误差(MAE)均方误差(MSE)根均方误差(RMSE)决定系数(R²)

  • MAE:平均预测误差,单位与房价一致,易理解;
  • RMSE:对大误差更敏感,更能反映模型的极端错误;
  • R²:表示模型能解释的房价变异比例,越接近1越好。
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score

# 1. 测试集预测
y_pred = lr.predict(X_test_scaled)

# 2. 计算评估指标
mae = mean_absolute_error(y_test, y_pred)
mse = mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)
r2 = r2_score(y_test, y_pred)

print(f"平均绝对误差(MAE):{mae:.2f} 万美元")
print(f"均方误差(MSE):{mse:.2f}")
print(f"根均方误差(RMSE):{rmse:.2f} 万美元")
print(f"决定系数(R²):{r2:.2f}")

# 3. 可视化:真实房价vs预测房价
plt.figure(figsize=(8, 6))
plt.scatter(y_test, y_pred, alpha=0.5)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r--')  # 完美预测线
plt.xlabel('真实房价(万美元)')
plt.ylabel('预测房价(万美元)')
plt.title('加州房价预测:真实值vs预测值')
plt.show()

结果解读:普通线性回归在加州房价数据集上的R²约为0.58左右,说明模型能解释约58%的房价变异,剩余误差主要来自特征的非线性关系或未纳入的因素(如学区、交通等)。

3.6 步骤5:优化模型(正则化线性回归)

普通线性回归易出现过拟合,可使用岭回归(Ridge)Lasso回归加入正则化,约束系数大小,提升模型泛化能力:

from sklearn.linear_model import Ridge

# 构建岭回归模型(L2正则化)
ridge = Ridge(alpha=1.0)  # alpha为正则化强度,越大约束越强
ridge.fit(X_train_scaled, y_train)

# 评估岭回归模型
y_pred_ridge = ridge.predict(X_test_scaled)
r2_ridge = r2_score(y_test, y_pred_ridge)
print(f"岭回归R²:{r2_ridge:.2f}")

优化效果:岭回归的R²通常比普通线性回归略高,能小幅提升模型性能。

3.7 步骤6:用新数据预测房价

用模拟的新样本预测房价,同样需要先标准化特征:

# 模拟新样本:[平均收入, 房屋年龄, 平均房间数, 平均卧室数, 人口数, 平均家庭数, 纬度, 经度]
new_sample = np.array([[8.3, 25, 6.5, 1.0, 3000, 2.5, 37.8, -122.2]])  # 加州旧金山附近的特征

# 特征标准化
new_sample_scaled = scaler.transform(new_sample)

# 预测房价
pred_price = ridge.predict(new_sample_scaled)
print(f"新样本房屋中位数价格预测:{pred_price[0]:.2f} 万美元")

四、实战技巧与常见问题

4.1 鸢尾花分类(KNN)的技巧与问题

  1. K值选择:K值通常选择奇数(避免投票平局),可通过交叉验证从1-20的奇数中选择最优值;
  2. 距离度量:KNN默认用欧氏距离,对于高维数据,可尝试曼哈顿距离或余弦相似度;
  3. 特征选择:鸢尾花数据中花瓣特征比花萼特征更重要,可通过特征选择(如方差分析)剔除无关特征;
  4. 过拟合与欠拟合:K=1时模型过拟合(训练集准确率100%,测试集准确率低),K过大时模型欠拟合(准确率整体下降)。

4.2 房价预测(线性回归)的技巧与问题

  1. 特征工程:可对特征进行非线性变换(如对数、平方),或构建组合特征(如房间数/家庭数),挖掘特征与房价的非线性关系;
  2. 异常值处理:房价数据中存在极端值(如豪宅),可通过截断或删除异常值提升模型性能;
  3. 正则化参数:岭回归的alpha参数可通过网格搜索优化,找到最优正则化强度;
  4. 模型升级:若线性回归效果不佳,可尝试非线性模型(如决策树、随机森林),能更好地拟合房价的复杂规律。
Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐