机器学习 第二课 Sklearn 入门
概述
机器学习 (Machine Learning) 是一个近年来频繁出现在科技新闻, 研究报告, 行业分析和实际应用中的热门领域. 机器学习 (Machine Learning) 正以前所未有的速度影响着我们的生活. 从智能音响的语音识别, 手机摄像头的人脸解锁, 到金融领域的评估, 医疗健康的预测分析. 机器学习的应用早已渗透到生活的方方面面. 对于我们这些初学着来说, Scikit-Learn 是最好的选择.
Scikit-Learn, 简称 Sklearn, 是 Python 的一个开源机器学习库, 自从诞生以来, 已经逐渐成为机器学习领域的标准库. Sklearn 提供了丰富的算法选择, 从基础的线性回归 (Linear Regression), 分类, 到高级的集成方法和模型优化, 几乎涵盖了机器学习的各个方面. 但更为重要的是, Scikit-Learn 的设计哲学为使用者提供了简答, 高效, 可靠的工具, 帮助我们来完成自己的任务.
今天小白我带大家来全面了解一下 Scikit-Learn 的基础, 从安装配置开始, 探讨其核心组件, 估计器, 模型训练与评估, 再到实际应用案例, 我们将逐步探索这个强大的库. 希望在文章的结尾, 读者可以具备食用 Scikit-Learn 解决实际问题的能力.
机器学习与 Python 的完美结合
我们先来探讨一个问题: 为什么要选择 Python 作为机器学习的编程语言? 这个问题的答案可以从多个角度来看. 首先, Python 是一种通用的高级编程语言, 语法简洁明了, 适合初学着学习. 此外, Python 有着丰富的开源库和框架, 涵盖了从数据分析, 可视化到深度学习的各个方面, 这使得 Python 在数据科学和机器学习领域占据了显著的优势.
其次, Python 的社区活跃, 有着大量的在线资源, 教程和案例, 这为我们提供了宝贵的学习资料. 不仅如此, Python 的跨平台特性使得开发者可以在不同的操作系统上轻松的部署和运行自己的程序.
那么, 为何选择 Scikit-Learn 作为 Python 中的机器学习库? 与其他库相比, Scikit-Learn 有着明确的优势. 首先, 它的 API 设计统一, 清晰, 无论是数据预处理, 模型训练还是评估, 用户都可以用几行简短的代码完成. 此外 Scikit-Learn 的文档齐全, 为我们提供了大量的实例和指导, 大大降低了学习的难度. 最后, Scikit-Learn 是一个纯 Python 实现的库, 意味着我们无语安装大量复杂的以来或担心其他库的兼容性问题.
Scikit-Learn 的核心组件与结构
安装与配置
Scikit-Learn 依赖于 Numpy 和 SciPy, 两个为 Python 提供科学计算功能的库. 因此, 在安装 Scikit-Learn, 去报已经安装了这两个库.
安装 Scikit-Learn:
pip install scikit-learn
conda:
conda install scikit-learn
验证安装
查看是否安装成功:
import sklearn
print(sklearn.__version__)
数据表示与预处理
在 Scikit-Learn 中, 数据同城为 Numpy 数组或特征矩阵. 其中样本是矩阵的行, 特征是矩阵的列.
特征矩阵和目标向量
特征矩阵:
- 通常表示为 “X”, 形状为 “[n_samples, n_features”
目标向量 - 当处理监督学习问题时, 我们还会有一个不妙 (或标签) 数组, 通常表示为 ‘y’
数据处理
Scikit-Learn 提供了多种实用工具, 帮助我们对数据进行预处理:
- 缩放: 如 “StandardScaler”, 帮助我们对数据进行标准化
- 编码: 如 “OneHotEncoder”, 将分类特征转换为数字
- 填充: 使用 “SimpleImputer”, 处理缺失数据
估计器
Scikit-Learn 的估计器 (Estimator) 为不同的机器学习应用提供了一致的界面.
核心概念如下:
- 估计器 (Estimator): 所有算法的实现都是估计器, 例如, 线性回归是一个估计器, k 近邻也是一个估计器
- 转换器 (Transformer): 可以对数据进行某种转化的估计器
- 预测期 (Predictor): 可以根据输入数据进行预测的估计器
基本步骤包括:
- 选择一个模型, 导入相应的估计器类
- 选择模型参数, 实例化类, 设置超参数值
- 整理数据, 通过特征矩阵和目标向量组织
- 调用估计器的
fit()
方法训练模型 - 使用
predict()
方法进行预测
例子:
"""
@Module Name: Scikit-Learn 估计器.py
@Author: CSDN@我是小白呀
@Date: October 15, 2023
Description:
Scikit-Learn 估计器
"""
from sklearn.linear_model import LinearRegression
# 创建数据
X = [[1], [2], [3]]
y = [2, 4, 6]
# 实例化模型
model = LinearRegression()
# 训练模型
model.fit(X, y)
# 预测
predict = model.predict([[4]])
print("预测结果:", predict)
输出结果:
预测结果: [8.]
模型的选择
在机器学习中, 模型的选择是最关键的步骤之一. 一个恰当的模型可以大大提高预测的准确性, 而不合适的模型可能导致预测结果严重偏离我们想要的结果.
所以, 在选择模型之前, 我们要先明确我们要解决的问题, 机器学习的问题主要分为两大类, 分类问题 (Classification) 和回归问题 (Regression).
思考问题的本质
在选择模型之前, 我们先要明确问题的本质. 有些问题可能乍看是分类问题, 但实际上使用回归模型更为合适. 例如: 预测学生期末考试及格率可以视为一个分类问题 (及格 / 不及格), 但其实我们使用回归模型来预测分数能得到更好的效果.
研究数据的分布
数据分布 (Data Distribution) 和特征 (Feature) 对模型的选择也至关重要, 不同的模型对不同的数据表现也不一样. 举个例子, 对于分布不平衡的分类数据 (某些类数据量远大于别的类), 我们需要通上采样 (Up-Sampling) 或下采样 (Sub-Sampling) 来处理不平衡的数据类型.
判断任务的复杂性
问题的复杂性也是一个需要考虑的重要因素. 简单的线性模型, 如线性回归或逻辑回归, 可能适用于线性可分的问题. 但对于更复杂, 非线性的问题, 可能需要使用决策树 (Decision Tree), 随机森林 (Random Forest) 等复杂模型.
线性 (Linear) vs 非线性 (Non-Linear):
- 线性 (Linear):
- 线性关系是指两个或多个变量 (Variable) 之间的关系为线性关系
- 线性关系在数学中可以以 y = w x + b y=wx + b y=wx+b 其中 w 为权重 (Weight), b 为偏差 (Bias)
- 在线性系统中, 输入和输出的关系是成比例的
- 非线性 (Non-Linear):
- 非线性是指变量之间的关系为非线性, 比如曲线
- 非线性方程包括, 多项式, 指数, 对数
- 在非线性系统, 输入和输出之间的关系是复杂的
分类问题
分类问题 (Classification) 指的是预测的输出变量为类别, 例如判断一个电影的类型, 物体是猫还是狗.
分类问题的机器学习模型有:
- 线性模型: 逻辑回归 (Logistic Regression)
- 非线性模型: k-近邻 (KNN), 决策树 (Decision Tree), 支持向量机 (SVM)
回归问题
回归问题 (Regression) 是指预测的输出变量是连续的值, 例如票房预测, 房价预测等等.
回归问题的机器学习模型有:
- 线性模型: 线性回归 (Linear Regression)
- 非线性模型: 决策树回归 (Decision Tree Regressor), 随机森林 (Random Forest)
监督学习
监督学习 (Supervised Learning) 是机器学习的一个核心分支, 目标是从带标签 (Label) 的数据中学习一个模型, 并预测未知数据的标签.
分类算法
逻辑回归 (Logistic Regression): 尽管名称中有 “回归”, 但是逻辑回归模型是一个分类模型, 主要用于二分类 (Binary Classification) 问题. 逻辑回归通过 Sigmoid 函数, 输出一个概率值, 从而为输入样本分类.
例子:
from sklearn.linear_model import LogisticRegression
clf = LogisticRegression()
clf.fit(X_train, y_train)
决策树 (Decision Tree): 图像话的算法, 易于理解和解释, 可以用于分类和回归任务.
例子:
from sklearn.tree import DecisionTreeClassifier
tree = DecisionTreeClassifier()
tree.fit(X_train, y_train)
回归算法
线性回归 (Linear Regression): 在数据中找到最佳拟合直线. 预测一个连续的输出.
例子:
from sklearn.linear_model import LinearRegression
reg = LinearRegression()
reg.fit(X_train, y_train)
支持向量回归 (SVR, Support Vector Regression): 使用支持向量机来执行回归.
例子:
from sklearn.svm import SVR
svr = SVR()
svr.fit(X_train, y_train)
无监督学习
无监督学习 (Unsupervised Learning) 与监督学习不同, 无监督学习是从未标签的数据中寻找模式.
K-均值 (K-Means): 将数据划分为 k 个集群.
例子:
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=3)
kmeans.fit(X)
主成分分析 (PCA): 减少数据的维数, 同时尝试保留尽可能多的信息.
例子:
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)
网络搜索 (Grid Search): 系统地遍历各种参数组合, 通过交叉验证确定最小效果参数.
例子:
from sklearn.model_selection import GridSearchCV
param_grid = {'C': [0.1, 1, 10], 'gamma': [1, 0.1, 0.01]}
grid = GridSearchCV(SVR(), param_grid, refit=True)
grid.fit(X_train, y_train)
随机搜索 (Randomized Search): 与 Grid Search 类似, 但不尝试所有参数, 二手随机抽样给定数量的参数组合.
模型的评估
在机器学习的过程中, 选择合适的模型至关重要. 同样, 评估模型的性能才能了解模型是否达到了我们的预期, 以避免欠拟合和过拟合问题.
训练集和验证集
为了评估模型的效果, 我们需要有一个基准. 所以我们需要分割训练集和测试集. 训练集用于训练模型 (Train), 留出一部分数据用于测试模型, 也就是验证集 (Valid), 而不是将所有的数据训练模型.
分类模型评估
混淆矩阵 (Confusion Matrix): 表现模型的真实值与预测值之间的关系, 包括真正例, 负正例, 假整例, 和假负例.
例子:
from sklearn.metrics import confusion_matrix
y_pred = clf.predict(X_test)
matrix = confusion_matrix(y_test, y_pred)
print(matrix)
准确率 (Accuracy), 召回率 (Recall), F1 (F1-score): 评估分类器的不同方面, 包括其准确性, 覆盖范围和平衡性.
例子:
from sklearn.metrics import classification_report
report = classification_report(y_test, y_pred)
print(report)
回归模型评估
均方误差 (MSE, Mean Square Error): 衡量模型预测的准确性.
例子:
from sklearn.metrics import mean_squared_error
mse = mean_squared_error(y_test, y_pred)
print(mse)
R^2 分数 (R-squared Score): 衡量模型解释变量的能力, 值越接近 1 越好.
例子:
from sklearn.metrics import r2_score
r2 = r2_score(y_test, y_pred)
print(r2)
交叉验证 (Cross-Validation) 将数据分为多个子集, 然后对每个子集进行多次的训练 / 测试分割. 例如, 常见的 k-折叠 (k-Fold) 交叉验证方法会将数据分为 k 个子集. 在每次的验证中, 其中一个子集被用作验证集, 其他的子集则被用作训练集. 这样我们就能得到 k 个不同的模型性能评估, 这些评估的平均值可以提供更准确的模型性能评估.
例子:
"""
@Module Name: 模型的评估.py
@Author: CSDN@我是小白呀
@Date: October 16, 2023
Description:
模型的评估
"""
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split, cross_val_score, KFold
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, recall_score, f1_score
# 加载 iris 数据集
data = load_iris()
X = data.data
y = data.target
# 实例化随机森林
clf = RandomForestClassifier(n_estimators=50, random_state=42)
# 分割训练集 & 验证集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 使用 KFold 进行5折交叉验证
kf = KFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(clf, X, y, cv=kf)
print("交叉验证平均得分:", scores.mean())
# 训练模型
clf.fit(X_train, y_train)
# 评估指标
y_pred = clf.predict(X_test)
print("精度:", accuracy_score(y_test, y_pred))
print("召回率:", recall_score(y_test, y_pred, average='macro')) # 多分类问题使用宏平均
print("F1分数:", f1_score(y_test, y_pred, average='macro')) # 多分类问题使用宏平均
输出结果:
交叉验证平均得分: 0.9600000000000002
精度: 1.0
召回率: 1.0
F1分数: 1.0
特征工程
特征工程 (Feature Engineering) 是机器学习中的关键步骤. 我们通过创建和选择合适的特征, 模型的性能可以得到大幅提升.
特征选择
特征选择 (Feature Selection) 是选择与目标变量相关的特征的过程, 同时剔除不相关或冗余的特征.
特征选择的好处有:
- 减少模型的复杂性
- 降低过拟合的风险
- 提高模型训练速度
举个例子:
假设我们有一个预测房价的数据集, 其中包含了很多特征,如房间数, 地理位置, 建筑年份, 是否靠近地铁站等. 但是, 其中可能还包含了一些不太相关的特征, 如房东的姓名, 是否有游泳池等. 通过特征选择, 我们可以只选择与房价最相关的特征来训练模型.
代码:
"""
@Module Name: 特征选择.py
@Author: CSDN@我是小白呀
@Date: October 16, 2023
Description:
通过波士顿房价数据集, 说明特征选择
"""
import numpy as np
import pandas as pd
from sklearn.datasets import load_boston
from sklearn.feature_selection import SelectKBest, f_regression
# 使用 Boston 房价数据集作为示例
data = load_boston()
df = pd.DataFrame(data.data, columns=data.feature_names)
df['PRICE'] = data.target
# 假设我们增加了一些不相关的特征
df['LANDLORD_NAME'] = np.random.choice(['Alice', 'Bob', 'Charlie'], df.shape[0])
df['HAS_POOL'] = np.random.choice([0, 1], df.shape[0])
# 将分类特征转化为数字
df['LANDLORD_NAME'] = df['LANDLORD_NAME'].astype('category').cat.codes
# 分割数据
X = df.drop('PRICE', axis=1)
y = df['PRICE']
# 使用 SelectKBest 进行特征选择
# 为了确定与房价最相关的特征, 我们可以使用f _regression 作为评分函数
selector = SelectKBest(score_func=f_regression, k=2)
X_new = selector.fit_transform(X, y)
# 打印被选中的特征
selected_features = pd.DataFrame(selector.inverse_transform(X_new),
columns=X.columns)
selected_columns = selected_features.columns[selected_features.var() != 0]
print('选择的特征:', selected_columns)
输出结果:
选择的特征: Index(['RM', 'LSTAT'], dtype='object')
特征提取
特征提取 (Feature Extraction) 是将原始数据转换为一组代表性的, 较少的特征. 与特征选择不同, 特征提取创建成新的特征. 主要成分分析 (PCA) 是一种常用特征提取方法.
例子:
"""
@Module Name: 特征提取.py
@Author: CSDN@我是小白呀
@Date: October 16, 2023
Description:
人脸识别数据集, 说明特征提取
"""
from sklearn.datasets import fetch_lfw_people
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
# 加载人脸数据集
lfw_people = fetch_lfw_people(min_faces_per_person=70, resize=0.4)
X = lfw_people.data
n_samples, n_features = X.shape
# 原始图像的维度
h, w = lfw_people.images.shape[1:3]
# PCA 转换, 提取 150 个主要成分
n_components = 150
pca = PCA(n_components=n_components, whiten=True).fit(X)
X_pca = pca.transform(X)
# 可视化主要成分的效果
def plot_gallery(images, titles, h, w, n_row=5, n_col=5):
plt.figure(figsize=(1.8 * n_col, 2.4 * n_row))
plt.subplots_adjust(bottom=0, left=.01, right=.99, top=.90, hspace=.35)
for i in range(n_row * n_col):
plt.subplot(n_row, n_col, i + 1)
plt.imshow(images[i].reshape((h, w)), cmap=plt.cm.gray)
plt.title(titles[i], size=12)
plt.xticks(())
plt.yticks(())
eigenfaces = pca.components_.reshape((n_components, h, w))
eigenface_titles = ["eigenface %d" % i for i in range(eigenfaces.shape[0])]
plot_gallery(eigenfaces, eigenface_titles, h, w)
# 绘图
plt.show()
输出结果: