scikit-learn(简称sklearn)是Python最流行的机器学习库之一,它以简洁的API、丰富的算法实现和完善的文档著称,成为机器学习初学者和从业者的首选工具。无论是分类、回归、聚类还是降维,scikit-learn都能提供高效且易用的解决方案。本文将通过具体示例,从基础概念到实战应用,带你掌握scikit-learn的核心用法,快速入门机器学习。

一、scikit-learn简介与环境准备

1. 为什么选择scikit-learn?

  • 算法丰富:涵盖分类、回归、聚类、降维、模型选择等几乎所有经典机器学习算法

  • 接口统一:所有算法遵循一致的API设计(fit()训练、predict()预测),降低学习成本

  • 文档完善:拥有详细的官方文档和丰富的示例,便于学习和调试

  • 生态兼容:与NumPy、Pandas、Matplotlib无缝集成,形成完整的数据科学工作流

  • 轻量高效:专注于机器学习任务,不依赖复杂框架,易于部署

2. 环境搭建

scikit-learn依赖于NumPy和SciPy,建议使用Anaconda环境安装,或通过pip安装:

# 基础安装(包含核心依赖)
pip install scikit-learn

# 完整安装(包含示例数据集和可视化工具)
pip install scikit-learn numpy pandas matplotlib seaborn

验证安装是否成功:

import sklearn
print(f"scikit-learn版本:{sklearn.__version__}")  # 输出版本号即表示安装成功

二、核心概念与基本流程

机器学习的核心流程可以概括为:**数据准备→模型训练→评估优化→预测应用**。scikit-learn将这个流程标准化,让开发者可以专注于业务逻辑而非算法细节。

1. 数据表示

在scikit-learn中,数据通常表示为:

  • 特征矩阵(X):二维数组(形状为[n_samples, n_features]),每行是一个样本,每列是一个特征

  • 标签向量(y):一维数组(形状为[n_samples]),存储每个样本的目标值(分类任务为类别,回归任务为连续值)

2. 基本流程示例(以分类任务为例)

# 1. 导入必要的模块
from sklearn.datasets import load_iris  # 数据集
from sklearn.model_selection import train_test_split  # 划分训练集和测试集
from sklearn.preprocessing import StandardScaler  # 特征标准化
from sklearn.ensemble import RandomForestClassifier  # 模型
from sklearn.metrics import accuracy_score  # 评估指标

# 2. 加载数据
data = load_iris()
X, y = data.data, data.target  # 特征矩阵和标签向量

# 3. 数据预处理:划分训练集(80%)和测试集(20%)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42  # random_state确保结果可复现
)

# 4. 特征缩放(部分算法需要,如SVM、KNN)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)  # 训练集拟合并转换
X_test_scaled = scaler.transform(X_test)        # 测试集使用相同的缩放规则

# 5. 初始化并训练模型
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train_scaled, y_train)  # 传入训练数据和标签

# 6. 模型预测与评估
y_pred = model.predict(X_test_scaled)  # 预测测试集
accuracy = accuracy_score(y_test, y_pred)  # 计算准确率
print(f"模型准确率:{accuracy:.2f}")  # 输出:模型准确率:1.00(鸢尾花数据集较简单)

三、数据预处理:构建高质量特征

数据预处理是机器学习的关键步骤,直接影响模型效果。scikit-learn提供了丰富的预处理工具,涵盖数据清洗、特征转换、特征选择等。

1. 数据标准化与归一化

  • 标准化(Standardization):将特征转换为均值为0、标准差为1的分布(适用于正态分布特征)

  • 归一化(Normalization):将特征缩放到[0,1]区间(适用于均匀分布特征)

from sklearn.preprocessing import StandardScaler, MinMaxScaler
import numpy as np

# 示例数据
data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.float64)

# 标准化
scaler = StandardScaler()
data_standardized = scaler.fit_transform(data)
print("标准化后的数据:")
print(data_standardized)
print("均值:", data_standardized.mean(axis=0))  # 接近0
print("标准差:", data_standardized.std(axis=0))  # 接近1

# 归一化
minmax_scaler = MinMaxScaler()
data_normalized = minmax_scaler.fit_transform(data)
print("\n归一化后的数据:")
print(data_normalized)  # 所有值在[0,1]区间

2. 处理缺失值

from sklearn.impute import SimpleImputer
import numpy as np

# 含缺失值的数据(NaN表示缺失)
data = np.array([
    [1, 2, np.nan],
    [4, np.nan, 6],
    [7, 8, 9]
])

# 用均值填充缺失值
imputer = SimpleImputer(strategy="mean")  # 可选:mean, median, most_frequent, constant
data_imputed = imputer.fit_transform(data)
print("填充缺失值后的数据:")
print(data_imputed)

3. 类别特征编码

机器学习模型通常需要数值输入,对于字符串类型的类别特征(如"红"、"蓝"),需进行编码:

from sklearn.preprocessing import LabelEncoder, OneHotEncoder
import numpy as np

# 示例类别特征
data = np.array(["红", "蓝", "绿", "红", "蓝"]).reshape(-1, 1)

# 标签编码(适用于有序类别,如"低"、"中"、"高")
label_encoder = LabelEncoder()
data_label_encoded = label_encoder.fit_transform(data.ravel())  # 转为0,1,2...
print("标签编码结果:", data_label_encoded)

# 独热编码(适用于无序类别,如颜色、国家)
onehot_encoder = OneHotEncoder(sparse_output=False)  # sparse_output=False返回稠密矩阵
data_onehot_encoded = onehot_encoder.fit_transform(data)
print("独热编码结果:")
print(data_onehot_encoded)
# 输出为:
# [[1. 0. 0.]
#  [0. 1. 0.]
#  [0. 0. 1.]
#  [1. 0. 0.]
#  [0. 1. 0.]]

四、常用机器学习算法示例

1. 分类算法(预测离散标签)

逻辑回归(二分类与多分类)
from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report

# 加载乳腺癌数据集(二分类任务)
data = load_breast_cancer()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 初始化并训练模型
model = LogisticRegression(max_iter=10000, random_state=42)  # 增加迭代次数确保收敛
model.fit(X_train, y_train)

# 预测与评估
y_pred = model.predict(X_test)
print(classification_report(y_test, y_pred, target_names=data.target_names))

随机森林(集成学习)
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# 加载葡萄酒数据集(多分类任务)
data = load_wine()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 训练随机森林模型
model = RandomForestClassifier(n_estimators=100, max_depth=5, random_state=42)
model.fit(X_train, y_train)

# 评估
y_pred = model.predict(X_test)
print(f"准确率:{accuracy_score(y_test, y_pred):.2f}")

# 查看特征重要性
importances = model.feature_importances_
for name, importance in zip(data.feature_names, importances):
    print(f"{name}: {importance:.3f}")

2. 回归算法(预测连续值)

线性回归
from sklearn.linear_model import LinearRegression
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score

# 加载糖尿病数据集(回归任务)
data = load_diabetes()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 训练线性回归模型
model = LinearRegression()
model.fit(X_train, y_train)

# 预测与评估
y_pred = model.predict(X_test)
print(f"均方误差(MSE):{mean_squared_error(y_test, y_pred):.2f}")
print(f"决定系数(R²):{r2_score(y_test, y_pred):.2f}")  # 越接近1越好

随机森林回归
from sklearn.ensemble import RandomForestRegressor
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error

# 加载加州房价数据集
data = fetch_california_housing()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 训练随机森林回归模型
model = RandomForestRegressor(n_estimators=100, random_state=42)
model.fit(X_train, y_train)

# 评估
y_pred = model.predict(X_test)
print(f"平均绝对误差(MAE):{mean_absolute_error(y_test, y_pred):.2f}")

3. 聚类算法(无监督学习)

K-Means聚类
from sklearn.cluster import KMeans
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt

# 加载鸢尾花数据集
data = load_iris()
X = data.data  # 不使用标签,进行无监督聚类

# 训练K-Means模型(假设分为3类)
kmeans = KMeans(n_clusters=3, random_state=42, n_init=10)  # n_init确保稳定结果
clusters = kmeans.fit_predict(X)

# 可视化聚类结果(使用前两个特征)
plt.scatter(X[:, 0], X[:, 1], c=clusters, cmap='viridis', label='聚类结果')
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], 
           s=300, c='red', marker='X', label='聚类中心')
plt.xlabel(data.feature_names[0])
plt.ylabel(data.feature_names[1])
plt.legend()
plt.show()

4. 降维算法(特征压缩)

PCA主成分分析
from sklearn.decomposition import PCA
from sklearn.datasets import load_digits
import matplotlib.pyplot as plt

# 加载手写数字数据集(64维特征)
data = load_digits()
X, y = data.data, data.target
print("原始特征维度:", X.shape[1])  # 输出:64

# 使用PCA降维到2维
pca = PCA(n_components=2)  # 保留2个主成分
X_pca = pca.fit_transform(X)
print("降维后特征维度:", X_pca.shape[1])  # 输出:2

# 可视化降维结果
plt.scatter(X_pca[:, 0], X_pca[:, 1], c=y, cmap='tab10', alpha=0.7)
plt.colorbar(label='数字类别')
plt.xlabel('主成分1')
plt.ylabel('主成分2')
plt.title('PCA降维可视化')
plt.show()

# 查看解释方差比
print(f"前2个主成分解释的方差比例:{pca.explained_variance_ratio_.sum():.2f}")

五、实战案例:客户流失预测系统

下面实现一个完整的客户流失预测系统,涵盖数据加载、探索、预处理、模型训练、调参和评估的全流程:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import (accuracy_score, precision_score, recall_score, 
                             f1_score, roc_auc_score, confusion_matrix, 
                             classification_report, roc_curve)

# 1. 数据加载与探索
# 加载数据集(示例使用Kaggle的Telco Customer Churn数据集)
# 实际使用时可从https://www.kaggle.com/datasets/blastchar/telco-customer-churn下载
# 这里使用模拟数据演示
data = pd.DataFrame({
    'gender': np.random.choice(['Male', 'Female'], size=1000),
    'SeniorCitizen': np.random.choice([0, 1], size=1000),
    'Partner': np.random.choice(['Yes', 'No'], size=1000),
    'tenure': np.random.randint(1, 73, size=1000),
    'MonthlyCharges': np.random.uniform(18, 120, size=1000),
    'Contract': np.random.choice(['Month-to-month', 'One year', 'Two year'], size=1000),
    'Churn': np.random.choice(['Yes', 'No'], size=1000)
})

# 查看数据基本信息
print("数据集形状:", data.shape)
print("\n前5行数据:")
print(data.head())

# 查看目标变量分布(是否流失)
churn_distribution = data['Churn'].value_counts(normalize=True)
print("\n客户流失比例:")
print(churn_distribution)

# 可视化: tenure与流失的关系
plt.figure(figsize=(10, 6))
sns.boxplot(x='Churn', y='tenure', data=data)
plt.title('客户 tenure 与流失的关系')
plt.show()

# 2. 数据预处理
# 划分特征与目标变量
X = data.drop('Churn', axis=1)
y = (data['Churn'] == 'Yes').astype(int)  # 将'Yes'/'No'转为1/0

# 区分数值特征和类别特征
numeric_features = ['tenure', 'MonthlyCharges', 'SeniorCitizen']
categorical_features = ['gender', 'Partner', 'Contract']

# 创建预处理管道:数值特征标准化,类别特征独热编码
preprocessor = ColumnTransformer(
    transformers=[
        ('num', StandardScaler(), numeric_features),
        ('cat', OneHotEncoder(drop='first'), categorical_features)  # drop='first'避免多重共线性
    ])

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=42, stratify=y  # stratify确保分层抽样,保持类别比例
)

# 3. 模型训练与超参数调优
# 创建包含预处理和模型的管道
pipeline = Pipeline([
    ('preprocessor', preprocessor),
    ('classifier', RandomForestClassifier(random_state=42))
])

# 定义超参数搜索空间
param_grid = {
    'classifier__n_estimators': [50, 100, 200],
    'classifier__max_depth': [None, 10, 20, 30],
    'classifier__min_samples_split': [2, 5, 10]
}

# 网格搜索交叉验证
grid_search = GridSearchCV(
    pipeline, param_grid, cv=5, scoring='f1', n_jobs=-1, verbose=1
)
grid_search.fit(X_train, y_train)

print(f"\n最佳超参数:{grid_search.best_params_}")
print(f"最佳交叉验证分数:{grid_search.best_score_:.4f}")

# 4. 模型评估
# 使用最佳模型预测
best_model = grid_search.best_estimator_
y_pred = best_model.predict(X_test)
y_pred_proba = best_model.predict_proba(X_test)[:, 1]  # 流失的概率

# 计算评估指标
print("\n测试集评估指标:")
print(f"准确率(Accuracy):{accuracy_score(y_test, y_pred):.4f}")
print(f"精确率(Precision):{precision_score(y_test, y_pred):.4f}")
print(f"召回率(Recall):{recall_score(y_test, y_pred):.4f}")
print(f"F1分数:{f1_score(y_test, y_pred):.4f}")
print(f"AUC:{roc_auc_score(y_test, y_pred_proba):.4f}")

# 混淆矩阵
cm = confusion_matrix(y_test, y_pred)
plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', 
            xticklabels=['未流失', '流失'], 
            yticklabels=['未流失', '流失'])
plt.xlabel('预测标签')
plt.ylabel('真实标签')
plt.title('混淆矩阵')
plt.show()

# ROC曲线
fpr, tpr, _ = roc_curve(y_test, y_pred_proba)
plt.figure(figsize=(8, 6))
plt.plot(fpr, tpr, label=f'ROC曲线 (AUC = {roc_auc_score(y_test, y_pred_proba):.4f})')
plt.plot([0, 1], [0, 1], 'k--')  # 随机猜测的基准线
plt.xlabel('假正例率(FPR)')
plt.ylabel('真正例率(TPR)')
plt.title('ROC曲线')
plt.legend()
plt.show()

# 5. 特征重要性分析
# 提取特征名称(处理后的)
cat_features = list(best_model.named_steps['preprocessor']
                   .named_transformers_['cat']
                   .get_feature_names_out(categorical_features))
all_features = numeric_features + cat_features

# 获取特征重要性
importances = best_model.named_steps['classifier'].feature_importances_
feature_importance = pd.DataFrame({
    '特征': all_features,
    '重要性': importances
}).sort_values(by='重要性', ascending=False)

print("\n特征重要性排序:")
print(feature_importance)

# 可视化特征重要性
plt.figure(figsize=(10, 6))
sns.barplot(x='重要性', y='特征', data=feature_importance)
plt.title('特征重要性')
plt.show()
    

六、模型选择与调优技巧

1. 交叉验证(避免过拟合)

from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris

data = load_iris()
X, y = data.data, data.target
model = LogisticRegression(max_iter=1000)

# 5折交叉验证
cv_scores = cross_val_score(model, X, y, cv=5, scoring='accuracy')
print(f"各折准确率:{cv_scores}")
print(f"平均准确率:{cv_scores.mean():.2f} ± {cv_scores.std():.2f}")

2. 超参数调优(网格搜索与随机搜索)

from sklearn.model_selection import RandomizedSearchCV
from sklearn.svm import SVC
from scipy.stats import randint, uniform

# 定义参数分布(随机搜索比网格搜索更高效)
param_dist = {
    'C': uniform(loc=0, scale=10),  # 正则化参数
    'kernel': ['linear', 'rbf', 'poly'],
    'gamma': uniform(loc=0, scale=1)  # 核系数
}

model = SVC()
# 随机搜索(在参数空间中随机采样)
random_search = RandomizedSearchCV(
    model, param_dist, n_iter=20, cv=5, scoring='accuracy', random_state=42
)
random_search.fit(X_train, y_train)

print(f"最佳参数:{random_search.best_params_}")
print(f"最佳分数:{random_search.best_score_:.2f}")

3. 模型保存与加载

训练好的模型可以保存到磁盘,便于后续部署:

from sklearn.ensemble import RandomForestClassifier
import joblib  # scikit-learn推荐的模型保存工具

# 训练模型
model = RandomForestClassifier()
model.fit(X_train, y_train)

# 保存模型
joblib.dump(model, 'churn_model.pkl')

# 加载模型(部署时使用)
loaded_model = joblib.load('churn_model.pkl')
# 使用加载的模型预测
y_pred = loaded_model.predict(X_test)

七、常用数据集与扩展学习

1. scikit-learn内置数据集

scikit-learn提供了多个小型数据集,方便快速测试算法:

  • load_iris():鸢尾花分类数据集

  • load_breast_cancer():乳腺癌诊断数据集

  • load_diabetes():糖尿病回归数据集

  • load_digits():手写数字识别数据集

  • fetch_california_housing():加州房价数据集

2. 扩展资源

  • 官方文档:https://scikit-learn.org/stable/user_guide.html(权威教程)

  • 示例库:https://scikit-learn.org/stable/auto_examples/index.html(丰富的代码示例)

  • 进阶书籍:《Introduction to Machine Learning with Python》(scikit-learn作者编写)

八、总结

scikit-learn以其简洁的API和丰富的功能,成为机器学习入门和快速原型开发的理想工具。本文从数据预处理、核心算法到实战案例,展示了scikit-learn在分类、回归、聚类和降维等任务中的应用。通过统一的fit()/predict()接口,开发者可以轻松切换不同算法,快速对比效果。

在实际应用中,需注意:

  1. 数据质量是关键,预处理步骤往往比算法选择更重要

  2. 避免过拟合,通过交叉验证和正则化提高模型泛化能力

  3. 结合业务理解选择合适的评估指标(如召回率对欺诈检测更重要)

scikit-learn适合处理中小规模数据集和经典机器学习任务。对于大规模数据或深度学习场景,可结合PySpark MLlib或TensorFlow/PyTorch使用。掌握scikit-learn,将为你的机器学习之旅打下坚实基础,无论是学术研究还是工业应用,都能显著提升开发效率。

Logo

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

更多推荐