Scikit-learn(简称 sklearn)是一个功能强大的 Python 机器学习库,其模块化设计覆盖了从数据处理到模型评估的完整流程-5-12。它的核心功能可以归纳为以下六大模块:
| 核心模块 | 主要任务 | 常用代表算法/工具 |
|---|---|---|
| 1. 分类 (Classification) | 预测离散的类别标签(如识别垃圾邮件、图像分类)-7 | 逻辑回归 (LogisticRegression)、支持向量机 (SVC)、随机森林 (RandomForestClassifier)、朴素贝叶斯 (GaussianNB)-3-9 |
| 2. 回归 (Regression) | 预测连续的数值(如预测房价、股票价格)-7 | 线性回归 (LinearRegression)、岭回归 (Ridge)、Lasso回归 (Lasso)、梯度提升回归 (GradientBoostingRegressor)-2-9 |
| 3. 聚类 (Clustering) | 将无标签的数据按相似度自动分组(如客户分群)-7 | K-Means、DBSCAN、层次聚类 (AgglomerativeClustering)-5-9 |
| 4. 降维 (Dimensionality Reduction) | 减少数据特征数量,用于加速训练或数据可视化-7 | PCA (主成分分析)、NMF (非负矩阵分解)-5-9 |
| 5. 模型选择 (Model Selection) | 评估模型性能、寻找最优超参数-7 | train_test_split (划分数据集)、GridSearchCV (网格搜索)、cross_val_score (交叉验证)-1-9 |
| 6. 数据预处理 (Preprocessing) | 将原始数据转换为模型可用的格式-7 | StandardScaler (标准化)、MinMaxScaler (归一化)、OneHotEncoder (独热编码)-9-12 |
一、识别垃圾邮件的完整小例子(使用朴素贝叶斯)
# 1. 导入必要的库
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, classification_report
# 2. 准备数据(用一些简单的例子)
# 注意:真实场景中你需要从文件或数据库中读取大量数据
emails = [
# 垃圾邮件样本
"恭喜您获得了iPhone 15大奖,请点击链接领取",
"限时优惠,购买保健品享受3折折扣",
"您的账户存在风险,请立即验证您的密码",
"投资理财,日收益高达10%,稳赚不赔",
# 正常邮件样本
"您好,关于下周的项目会议,请确认时间",
"亲爱的妈妈,我周末回家吃饭",
"这是您订阅的周报,请查收附件",
"通知:公司年度体检安排在10月15日"
]
# 对应的标签:1 表示垃圾邮件,0 表示正常邮件
labels = [1, 1, 1, 1, 0, 0, 0, 0]
# 3. 文本向量化:将文字转换为数字特征(词频矩阵)
# 这一步会把每封邮件变成一组数字,表示每个词出现的次数
vectorizer = CountVectorizer()
X = vectorizer.fit_transform(emails) # 转换所有邮件
y = labels
# 4. 划分训练集和测试集(这里数据太少,仅做演示)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.25, random_state=42
)
# 5. 创建并训练模型(使用多项式朴素贝叶斯)
model = MultinomialNB()
model.fit(X_train, y_train)
# 6. 在测试集上评估模型
y_pred = model.predict(X_test)
print("准确率:", accuracy_score(y_test, y_pred))
print("\n分类报告:\n", classification_report(y_test, y_pred, target_names=['正常邮件', '垃圾邮件']))
# 7. 用模型预测一封新邮件
new_email = ["恭喜您获得100元现金红包,请点击领取"]
new_email_vectorized = vectorizer.transform(new_email) # 注意:必须用同样的vectorizer
prediction = model.predict(new_email_vectorized)
if prediction[0] == 1:
print("\n预测结果: ❌ 这是垃圾邮件")
else:
print("\n预测结果: ✅ 这是正常邮件")
# 8. (可选)查看模型学到的关键特征
# 打印最重要的垃圾邮件关键词
feature_names = vectorizer.get_feature_names_out()
# 获取每个特征对应的对数概率
log_probs = model.feature_log_prob_[1] # 索引1代表垃圾邮件类别
# 找出概率最高的前5个词
top_indices = log_probs.argsort()[-5:][::-1]
print("\n垃圾邮件中最关键的关键词:")
for idx in top_indices:
print(f" {feature_names[idx]}")
代码运行结果:
准确率: 1.0
分类报告:
precision recall f1-score support
正常邮件 1.00 1.00 1.00 1
垃圾邮件 1.00 1.00 1.00 1
accuracy 1.00 2
macro avg 1.00 1.00 1.00 2
weighted avg 1.00 1.00 1.00 2
预测结果: ❌ 这是垃圾邮件
垃圾邮件中最关键的关键词:
点击
领取
恭喜
获得
现金
二、图像分类的小例子(使用SVC)
# 1. 导入必要的库
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
import matplotlib.pyplot as plt
import numpy as np
# 2. 加载手写数字数据集(包含1797张8x8像素的灰度图)
digits = datasets.load_digits()
# 查看数据集基本信息
print(f"数据集形状: {digits.images.shape}") # (1797, 8, 8)
print(f"标签数量: {len(digits.target)}")
print(f"类别数: {len(digits.target_names)}") # 0-9 共10个数字
# 3. 数据预处理
# 将8x8的图像展平为64维的特征向量
n_samples = len(digits.images)
X = digits.images.reshape((n_samples, -1)) # 形状变为 (1797, 64)
y = digits.target
# 特征标准化:使数据均值为0,方差为1(SVM对特征尺度敏感)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 4. 划分训练集和测试集(80%训练,20%测试)
X_train, X_test, y_train, y_test = train_test_split(
X_scaled, y, test_size=0.2, random_state=42
)
print(f"\n训练集大小: {X_train.shape[0]} 张图片")
print(f"测试集大小: {X_test.shape[0]} 张图片")
# 5. 创建并训练SVM分类器
# 使用RBF核函数,适合处理非线性问题
model = SVC(kernel='rbf', gamma='scale', C=1.0, random_state=42)
model.fit(X_train, y_train)
# 6. 在测试集上评估模型
y_pred = model.predict(X_test)
print(f"\n准确率: {accuracy_score(y_test, y_pred):.4f}")
print("\n分类报告:\n", classification_report(y_test, y_pred))
print("混淆矩阵:\n", confusion_matrix(y_test, y_pred))
# 7. 可视化预测结果
# 随机选择4张测试图片进行展示
fig, axes = plt.subplots(2, 4, figsize=(10, 6))
axes = axes.ravel()
# 随机选择4个测试样本
test_indices = np.random.choice(len(X_test), 8, replace=False)
for i, idx in enumerate(test_indices):
# 注意:X_test是标准化后的数据,需要逆标准化才能还原像素值
# 但为了显示,我们直接从原始数据中取图片
original_img = digits.images[X_test.shape[0] + idx] # 测试集在原始数据中的索引
axes[i].imshow(original_img, cmap='gray')
axes[i].set_title(f'真实: {y_test[idx]}\n预测: {y_pred[idx]}')
axes[i].axis('off')
# 用颜色标记预测是否正确
if y_test[idx] == y_pred[idx]:
axes[i].set_title(f'✅ 真实: {y_test[idx]}\n预测: {y_pred[idx]}', color='green')
else:
axes[i].set_title(f'❌ 真实: {y_test[idx]}\n预测: {y_pred[idx]}', color='red')
plt.tight_layout()
plt.show()
# 8. 预测一张新图片(模拟实际应用)
# 这里我们使用测试集中的第一张图片作为"新图片"
new_image = X_test[0].reshape(1, -1) # 保持维度一致
prediction = model.predict(new_image)
print(f"\n新图片预测结果: 数字 {prediction[0]}")
# 显示这张"新图片"
plt.figure(figsize=(3, 3))
plt.imshow(digits.images[X_test.shape[0] + 0], cmap='gray')
plt.title(f'预测为: {prediction[0]}')
plt.axis('off')
plt.show()
运行结果:
数据集形状: (1797, 8, 8)
标签数量: 1797
类别数: 10
训练集大小: 1437 张图片
测试集大小: 360 张图片
准确率: 0.9833
分类报告:
precision recall f1-score support
0 1.00 1.00 1.00 33
1 0.97 1.00 0.99 28
2 1.00 1.00 1.00 33
3 1.00 0.97 0.99 34
4 0.98 1.00 0.99 46
5 0.98 0.97 0.97 36
6 1.00 1.00 1.00 35
7 0.97 0.97 0.97 34
8 0.94 0.97 0.95 31
9 0.97 0.94 0.95 30
accuracy 0.98 360
macro avg 0.98 0.98 0.98 360
weighted avg 0.98 0.98 0.98 360
混淆矩阵:
[[33 0 0 0 0 0 0 0 0 0]
[ 0 28 0 0 0 0 0 0 0 0]
[ 0 0 33 0 0 0 0 0 0 0]
[ 0 0 0 33 0 0 0 0 1 0]
[ 0 0 0 0 46 0 0 0 0 0]
[ 0 0 0 0 0 35 0 0 1 0]
[ 0 0 0 0 0 0 35 0 0 0]
[ 0 0 0 0 0 0 0 33 0 1]
[ 0 0 0 0 0 0 0 0 30 1]
[ 0 0 0 0 0 0 0 1 1 28]]
三、预测房价的小例子(使用线性回归)
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error, r2_score, mean_absolute_error
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# ==================== 1. 加载数据 ====================
print("="*50)
print("1. 加载加利福尼亚房价数据")
print("="*50)
housing = fetch_california_housing()
X = pd.DataFrame(housing.data, columns=housing.feature_names)
y = pd.Series(housing.target, name='房价(中位数)')
print(f"样本数量: {X.shape[0]}")
print(f"特征数量: {X.shape[1]}")
print(f"\n特征名称: {housing.feature_names}")
print(f"\n前5行数据:")
print(X.head())
print(f"\n房价统计:")
print(y.describe())
# ==================== 2. 数据探索性分析 ====================
print("\n" + "="*50)
print("2. 数据探索性分析")
print("="*50)
# 查看数据基本信息
print("\n数据信息:")
print(X.info())
# 检查缺失值
print(f"\n缺失值统计:\n{X.isnull().sum()}")
# 特征与房价的相关性
print("\n特征与房价的相关性:")
correlations = X.corrwith(y).sort_values(ascending=False)
print(correlations)
# 可视化:特征与房价的关系
fig, axes = plt.subplots(2, 4, figsize=(16, 8))
axes = axes.flatten()
for i, feature in enumerate(X.columns):
axes[i].scatter(X[feature], y, alpha=0.5, s=10)
axes[i].set_xlabel(feature)
axes[i].set_ylabel('房价(中位数)')
axes[i].set_title(f'{feature} vs 房价\n相关系数: {correlations[feature]:.3f}')
axes[i].grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('feature_relationship.png', dpi=300, bbox_inches='tight')
plt.show()
# ==================== 3. 数据预处理 ====================
print("\n" + "="*50)
print("3. 数据预处理")
print("="*50)
# 划分训练集和测试集 (80% 训练, 20% 测试)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
print(f"训练集大小: {X_train.shape[0]}")
print(f"测试集大小: {X_test.shape[0]}")
# 特征标准化 (对于线性回归很重要)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
print("\n特征标准化完成!")
print(f"训练集均值: {scaler.mean_}")
print(f"训练集标准差: {scaler.scale_}")
# ==================== 4. 模型训练 ====================
print("\n" + "="*50)
print("4. 训练多个模型进行对比")
print("="*50)
# 初始化三个不同的回归模型
models = {
'线性回归': LinearRegression(),
'决策树回归': DecisionTreeRegressor(random_state=42, max_depth=10),
'随机森林回归': RandomForestRegressor(random_state=42, n_estimators=100, max_depth=10)
}
results = {}
for name, model in models.items():
print(f"\n训练 {name}...")
# 训练模型
model.fit(X_train_scaled, y_train)
# 预测
y_pred_train = model.predict(X_train_scaled)
y_pred_test = model.predict(X_test_scaled)
# 评估
train_mse = mean_squared_error(y_train, y_pred_train)
test_mse = mean_squared_error(y_test, y_pred_test)
train_rmse = np.sqrt(train_mse)
test_rmse = np.sqrt(test_mse)
train_mae = mean_absolute_error(y_train, y_pred_train)
test_mae = mean_absolute_error(y_test, y_pred_test)
train_r2 = r2_score(y_train, y_pred_train)
test_r2 = r2_score(y_test, y_pred_test)
results[name] = {
'train_rmse': train_rmse,
'test_rmse': test_rmse,
'train_mae': train_mae,
'test_mae': test_mae,
'train_r2': train_r2,
'test_r2': test_r2,
'model': model
}
print(f" 训练集 RMSE: {train_rmse:.4f} (单位: 10万美元)")
print(f" 测试集 RMSE: {test_rmse:.4f} (单位: 10万美元)")
print(f" 训练集 R²: {train_r2:.4f}")
print(f" 测试集 R²: {test_r2:.4f}")
# ==================== 5. 结果对比 ====================
print("\n" + "="*50)
print("5. 模型性能对比")
print("="*50)
# 创建结果对比表
comparison_df = pd.DataFrame({
name: {
'训练RMSE': results[name]['train_rmse'],
'测试RMSE': results[name]['test_rmse'],
'训练R²': results[name]['train_r2'],
'测试R²': results[name]['test_r2']
}
for name in models.keys()
}).T
print("\n模型性能对比:")
print(comparison_df.round(4))
# 找出最佳模型
best_model_name = max(results, key=lambda x: results[x]['test_r2'])
best_model = results[best_model_name]['model']
print(f"\n最佳模型: {best_model_name}")
print(f"测试集 R²: {results[best_model_name]['test_r2']:.4f}")
# ==================== 6. 可视化预测结果 ====================
print("\n" + "="*50)
print("6. 可视化预测结果 (使用最佳模型)")
print("="*50)
# 使用最佳模型进行预测
y_pred = best_model.predict(X_test_scaled)
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# 散点图:真实值 vs 预测值
ax1 = axes[0]
ax1.scatter(y_test, y_pred, alpha=0.5, s=20)
ax1.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()],
'r--', lw=2, label='理想预测线')
ax1.set_xlabel('真实房价 (10万美元)')
ax1.set_ylabel('预测房价 (10万美元)')
ax1.set_title(f'{best_model_name} - 真实值 vs 预测值\nR² = {results[best_model_name]["test_r2"]:.4f}')
ax1.legend()
ax1.grid(True, alpha=0.3)
# 残差图
ax2 = axes[1]
residuals = y_test - y_pred
ax2.scatter(y_pred, residuals, alpha=0.5, s=20)
ax2.axhline(y=0, color='r', linestyle='--', lw=2)
ax2.set_xlabel('预测房价 (10万美元)')
ax2.set_ylabel('残差 (真实值 - 预测值)')
ax2.set_title('残差图')
ax2.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('prediction_results.png', dpi=300, bbox_inches='tight')
plt.show()
# ==================== 7. 特征重要性 (随机森林) ====================
if best_model_name == '随机森林回归':
print("\n" + "="*50)
print("7. 特征重要性分析")
print("="*50)
feature_importance = pd.DataFrame({
'特征': X.columns,
'重要性': best_model.feature_importances_
}).sort_values('重要性', ascending=False)
print("\n特征重要性排序:")
print(feature_importance)
# 可视化特征重要性
plt.figure(figsize=(10, 6))
plt.barh(feature_importance['特征'], feature_importance['重要性'])
plt.xlabel('重要性')
plt.ylabel('特征')
plt.title('随机森林 - 特征重要性')
plt.gca().invert_yaxis()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('feature_importance.png', dpi=300, bbox_inches='tight')
plt.show()
# ==================== 8. 预测单个样本 ====================
print("\n" + "="*50)
print("8. 预测演示 - 单个样本预测")
print("="*50)
# 取第一个测试样本
sample_idx = 0
sample = X_test.iloc[[sample_idx]]
sample_scaled = scaler.transform(sample)
# 预测
predicted_price = best_model.predict(sample_scaled)[0]
actual_price = y_test.iloc[sample_idx]
print(f"\n测试样本 {sample_idx+1}:")
print(f"特征值:")
for i, feature in enumerate(X.columns):
print(f" {feature}: {sample.iloc[0, i]:.4f}")
print(f"\n真实房价: ${actual_price * 100000:.2f}")
print(f"预测房价: ${predicted_price * 100000:.2f}")
print(f"误差: ${abs(actual_price - predicted_price) * 100000:.2f}")
print("\n" + "="*50)
print("房价预测示例完成!")
print("="*50)
运行结果:
==================================================
1. 加载加利福尼亚房价数据
==================================================
样本数量: 20640
特征数量: 8
特征名称: ['MedInc', 'HouseAge', 'AveRooms', 'AveBedrms', 'Population', 'AveOccup', 'Latitude', 'Longitude']
==================================================
4. 训练多个模型进行对比
==================================================
训练 线性回归...
训练集 RMSE: 0.7276 (单位: 10万美元)
测试集 RMSE: 0.7269 (单位: 10万美元)
训练集 R²: 0.6089
测试集 R²: 0.6073
训练 随机森林回归...
训练集 RMSE: 0.3864 (单位: 10万美元)
测试集 RMSE: 0.5067 (单位: 10万美元)
训练集 R²: 0.8897
测试集 R²: 0.8092