Chapter 6 有监督机器学习

6.1 数据处理

6.1.1 标准化 与 归一化

据的尺度或范围,以便更好地适用于机器学习算法或数据分析。它们有不同的方法和目标:

  1. 标准化(Standardization):
  • 标准化的目标是将数据的分布转换为均值为0、标准差为1的标准正态分布(也称为Z分布)。
  • 它通过减去均值(平均值)并除以标准差来缩放数据。这可以用以下公式表示:\(z = (x - \mu) / \sigma\),其中 \(z\) 是标准化后的值,\(x\) 是原始值,\(\mu\) 是均值,\(\sigma\) 是标准差。
  • 标准化对数据中存在离群值(异常值)的情况更具鲁棒性,因为它主要依赖于数据的分布统计量,而不受极端值的干扰。
  • 常见的标准化方法包括Z-Score标准化。
  1. 归一化(Normalization):
  • 归一化的目标是将数据缩放到特定的范围,通常在0到1之间。
  • 归一化可以通过以下公式实现:\(x_{\text{new}} = (x - x_{\text{min}}) / (x_{\text{max}} - x_{\text{min}})\),其中 \(x_{\text{new}}\) 是归一化后的值,\(x\) 是原始值,\(x_{\text{min}}\) 是最小值,\(x_{\text{max}}\) 是最大值。
  • 归一化对于需要将特征值放在相似尺度下的算法非常有用,例如神经网络和支持向量机(SVM)。
  • 常见的归一化方法包括最小-最大缩放和按范数(范数归一化)进行缩放。

总结来说,标准化和归一化都是数据预处理的技术,但它们的目标和方法有所不同。您应根据您的数据和机器学习模型的需求来选择使用哪种方法。标准化通常更适用于数据的分布不受特定范围限制的情况,而归一化通常更适用于需要将数据缩放到特定范围内的情况。

6.1.1.1 标准化 (Standardization)

标准化的目标是将数据转换为均值为0、标准差为1的标准正态分布(Z分布)。

使用 StandardScaler 类来进行标准化:

from sklearn.preprocessing import StandardScaler

# 创建一个示例数据集
data = [[1, 2], [2, 3], [3, 4], [4, 5]]

# 初始化标准化器
scaler = StandardScaler()

# 对数据进行标准化
scaled_data = scaler.fit_transform(data)

6.1.1.2 归一化(Normalization):

归一化的目标是将数据缩放到特定范围,通常在0到1之间。

使用 MinMaxScaler 类来进行归一化:

from sklearn.preprocessing import MinMaxScaler

# 创建一个示例数据集
data = [[1, 2], [2, 3], [3, 4], [4, 5]]

# 初始化归一化器
scaler = MinMaxScaler()

# 对数据进行归一化
normalized_data = scaler.fit_transform(data)

6.1.1.3 总结:

  1. 标准化通过 StandardScaler 完成,将数据转换为均值为0、标准差为1的标准正态分布。
  2. 归一化通过 MinMaxScaler 完成,将数据缩放到指定范围内,通常在0到1之间。
  3. 无论是标准化还是归一化,都可以按照以下步骤进行:
    • 导入所需的模块:from sklearn.preprocessing import StandardScaler 或 from sklearn.preprocessing import MinMaxScaler。
    • 创建一个数据集,其中每行代表一个样本,每列代表一个特征。
    • 初始化标准化器或归一化器:scaler = StandardScaler() 或 scaler = MinMaxScaler()。
    • 使用 fit_transform 方法来应用标准化或归一化,得到转换后的数据。

6.1.2 非线性转换

非线性转换通常用于将数据映射到一个新的特征空间,以改进数据的线性可分性或以适应非线性模型。 非线性转换通常包括将数据映射到高维特征空间,以便在该空间中进行线性操作。这些转换可用于解决非线性问题或改善数据的线性可分性。以下是一些常见的非线性转换技术和示例:

  1. 多项式特征扩展: 多项式特征扩展将原始特征的组合添加为新的特征,从而使模型能够捕捉非线性关系。
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression

data = [[1], [2], [3]]
target = [2, 3, 4]

poly = PolynomialFeatures(degree=2)
data_poly = poly.fit_transform(data)

model = LinearRegression()
model.fit(data_poly, target)
## LinearRegression()
  1. 核方法: 核方法通过将数据映射到高维空间中的非线性特征来增强模型的能力。常见的核函数包括多项式核和径向基函数(RBF)核。
from sklearn.svm import SVR
from sklearn.datasets import make_regression

data, target = make_regression(n_samples=100, n_features=1, noise=0.1)

model = SVR(kernel='poly', degree=3)  # 多项式核
model.fit(data, target)
## SVR(kernel='poly')
  1. 非线性特征变换: 非线性特征变换可以应用于特定特征,例如对数变换、指数变换、正切变换等。
import numpy as np

data = np.array([1, 2, 3, 4])
transformed_data = np.log(data)  # 对数变换
  1. 流形学习: 流形学习方法(如t-SNE)通过学习数据的低维表示来捕捉非线性结构。
from sklearn.manifold import TSNE
from sklearn.datasets import load_iris

data = load_iris().data
tsne = TSNE(n_components=2)
transformed_data = tsne.fit_transform(data)
## /Users/milin/.virtualenvs/sklearn2023/lib/python3.7/site-packages/sklearn/manifold/_t_sne.py:783: FutureWarning: The default initialization in TSNE will change from 'random' to 'pca' in 1.2.
##   FutureWarning,
## /Users/milin/.virtualenvs/sklearn2023/lib/python3.7/site-packages/sklearn/manifold/_t_sne.py:793: FutureWarning: The default learning rate in TSNE will change from 200.0 to 'auto' in 1.2.
##   FutureWarning,

6.1.3 对分类变量进行编码

  1. 标签编码(Label Encoding): 标签编码用于将分类变量的标签(类别)映射到整数。这对于某些算法(如决策树和随机森林)很有用,因为它们需要数值输入。
from sklearn.preprocessing import LabelEncoder

labels = ["cat", "dog", "fish", "dog", "cat"]
encoder = LabelEncoder()
encoded_labels = encoder.fit_transform(labels)

结果是 [0, 1, 2, 1, 0],其中每个标签都被映射为一个整数。

  1. 独热编码(One-Hot Encoding): 独热编码用于将分类变量的每个类别转化为二进制特征。每个类别都用一个二进制位表示,其中一个为1,其余为0。
from sklearn.preprocessing import OneHotEncoder
import pandas as pd

data = pd.DataFrame({"color": ["red", "green", "blue"]})
encoder = OneHotEncoder()
encoded_data = encoder.fit_transform(data[["color"]]).toarray()

结果是一个二进制矩阵,例如 [[0, 1, 0], [0, 0, 1], [1, 0, 0]],其中每一列代表一个类别。

  1. Pandas 的 get_dummies 方法: 如果您使用 Pandas,可以使用 get_dummies 方法来进行独热编码。
import pandas as pd

data = pd.DataFrame({"color": ["red", "green", "blue"]})
encoded_data = pd.get_dummies(data, columns=["color"])

这将创建一个包含二进制特征的新DataFrame。

  1. 自定义编码: 有时候,您可能需要自定义编码方法,以将类别映射为数值或其他形式。这可以通过编写自定义函数来实现。
data = ["low", "medium", "high", "low"]
encoding_dict = {"low": 1, "medium": 2, "high": 3}
encoded_data = [encoding_dict[val] for val in data]

6.1.4 离散化 (Discretization)

  1. 等宽离散化(Equal Width Discretization): 这种方法将数据范围均匀地分成若干个箱子(区间),每个箱子的宽度相等。
from sklearn.preprocessing import KBinsDiscretizer

data = [[1], [2], [3], [4], [5]]
discretizer = KBinsDiscretizer(n_bins=3, encode='ordinal', strategy='uniform')
discretized_data = discretizer.fit_transform(data)
  1. 等频离散化(Equal Frequency Discretization): 这种方法将数据划分成若干个区间,使每个区间内的数据点数量相等。
from sklearn.preprocessing import KBinsDiscretizer

data = [[1], [2], [3], [4], [5]]
discretizer = KBinsDiscretizer(n_bins=3, encode='ordinal', strategy='quantile')
discretized_data = discretizer.fit_transform(data)
  1. 自定义边界离散化: 您还可以自定义边界值,将数据划分成特定的区间。
import numpy as np

data = [1, 2, 3, 4, 5]
custom_bins = [0, 2, 4, 6]
discretized_data = np.digitize(data, custom_bins)

6.1.4.1 示例总结:

  1. 使用 KBinsDiscretizer 类进行等宽离散化或等频离散化。
  2. 设置 n_bins 参数来指定要分成的箱子数量。
  3. 使用 encode 参数来指定编码方式,‘ordinal’ 表示输出为箱子的序数,‘onehot’ 表示输出为独热编码。
  4. 使用 strategy 参数来选择离散化策略,‘uniform’ 表示等宽离散化,‘quantile’ 表示等频离散化。
  5. 您还可以使用NumPy的 digitize 函数来进行自定义离散化,需要提供自定义边界值。
  6. 离散化可用于处理连续特征,使其适用于某些机器学习算法,或用于创建分组、分箱分析等。根据您的数据和需求,选择适当的离散化方法非常重要。

6.1.5 生成多项式特征

生成多项式特征是一种将原始特征的多项式组合作为新特征添加到数据集中的方法,这有助于模型捕捉非线性关系。使用 PolynomialFeatures 类来生成多项式特征。

from sklearn.preprocessing import PolynomialFeatures

data = [[2, 3]]
poly = PolynomialFeatures(degree=2)  # 生成2次多项式特征
poly_features = poly.fit_transform(data)

示例总结:

  • 使用 PolynomialFeatures 类来生成多项式特征。
  • 设置 degree 参数来指定要生成的多项式的最高次数。
  • fit_transform 方法将原始特征数据转化为多项式特征。

示例中,原始数据 [[2, 3]] 被转化为 [[1, 2, 3, 4, 6, 9]],其中包括了原始特征的各项幂和它们的组合。

生成多项式特征对于捕捉特征之间的非线性关系非常有用,尤其在线性模型无法很好地拟合数据时。注意,随着多项式次数的增加,特征的数量也会迅速增加,这可能会导致维度灾难。因此,选择适当的多项式次数很重要,以充分捕捉非线性关系而不至于使数据维度过高。

6.2 线性模型

6.2.1 线性回归(Linear Regression):

线性回归是一种用于回归问题的线性模型,试图拟合输入特征和输出之间的线性关系。

import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score

# 生成示例数据
np.random.seed(0)
X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)

# 划分数据集为训练集和测试集
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)

# 进行预测
## LinearRegression()
y_pred = model.predict(X_test)

# 评估模型性能
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)

print("均方误差 (MSE):", mse)
## 均方误差 (MSE): 0.9177532469714291
print("R^2 分数:", r2)
## R^2 分数: 0.6521157503858556

这个示例包括以下步骤:

  1. 生成一个简单的线性关系的示例数据。
  2. 使用train_test_split将数据集划分为训练集和测试集。
  3. 创建一个LinearRegression线性回归模型。
  4. 使用训练数据拟合模型。
  5. 使用测试数据进行预测。
  6. 使用均方误差(MSE)和R²分数评估模型性能。

这是一个典型的Sklearn线性回归模型示例,用于拟合线性关系并评估模型的性能。您可以根据需要修改数据和模型,以适应不同的问题。

6.2.2 岭回归(Ridge Regression):

岭回归是一种线性回归的改进方法,通过引入L2正则化来防止过拟合。

from sklearn.linear_model import Ridge

# 创建一个岭回归模型
model = Ridge(alpha=1.0)

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

# 进行预测
## Ridge()
y_pred = model.predict(X_test)

6.2.3 Lasso 回归:

Lasso回归也是一种线性回归的改进方法,通过引入L1正则化来选择重要的特征并进行系数稀疏化。

from sklearn.linear_model import Lasso

# 创建一个Lasso回归模型
model = Lasso(alpha=1.0)

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

# 进行预测
## Lasso()
y_pred = model.predict(X_test)

6.2.4 逻辑回归(Logistic Regression):

逻辑回归是一种用于分类问题的线性模型,它使用Logistic函数来估计概率。

import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix

# 加载鸢尾花数据集
data = load_iris()
X = data.data
y = data.target

# 划分数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建逻辑回归模型
model = LogisticRegression(max_iter=1000)

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

# 进行预测
## LogisticRegression(max_iter=1000)
y_pred = model.predict(X_test)

# 评估模型性能
accuracy = accuracy_score(y_test, y_pred)
confusion = confusion_matrix(y_test, y_pred)
report = classification_report(y_test, y_pred)

print("准确率:", accuracy)
## 准确率: 1.0
print("混淆矩阵:\n", confusion)
## 混淆矩阵:
##  [[10  0  0]
##  [ 0  9  0]
##  [ 0  0 11]]
print("分类报告:\n", report)
## 分类报告:
##                precision    recall  f1-score   support
## 
##            0       1.00      1.00      1.00        10
##            1       1.00      1.00      1.00         9
##            2       1.00      1.00      1.00        11
## 
##     accuracy                           1.00        30
##    macro avg       1.00      1.00      1.00        30
## weighted avg       1.00      1.00      1.00        30

这个示例包括以下步骤:

  1. 加载鸢尾花数据集,它是一个常用的分类示例数据集。
  2. 使用 train_test_split 将数据集划分为训练集和测试集。
  3. 创建一个逻辑回归模型,可以通过设置 max_iter 参数来增加迭代次数以确保模型收敛。
  4. 使用训练数据拟合模型。
  5. 使用测试数据进行预测。
  6. 使用准确率、混淆矩阵和分类报告来评估模型性能。

6.3 支持向量机

支持向量机(Support Vector Machine,SVM)是一种强大的监督学习算法,用于二元分类和回归问题。它的核心思想是在特征空间中找到一个最优的超平面,以最大程度地分离不同类别的数据点。以下是SVM的原理总结、一个完整的Sklearn示例以及如何使用网格搜索调整参数的示例:

6.3.1 SVM 原理总结:

SVM的目标是找到一个最优的超平面,以最大化两个类别之间的间隔(支持向量之间的距离)。这个间隔被称为“间隔最大化”,它使SVM在面对未知数据时具有很好的泛化能力。SVM还可以使用不同的核函数来处理非线性分类问题,如多项式核和径向基函数(RBF)核。

from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score

# 加载鸢尾花数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target

# 划分数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建SVM模型
model = SVC(kernel='linear', C=1.0)

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

# 进行预测
## SVC(kernel='linear')
y_pred = model.predict(X_test)

# 评估模型性能
accuracy = accuracy_score(y_test, y_pred)
print("准确率:", accuracy)
## 准确率: 1.0

6.3.2 使用网格搜索调整参数:

你可以使用Sklearn的GridSearchCV来执行网格搜索以找到最佳的超参数组合。在这个示例中,我们将调整SVM的内核类型和正则化参数C:

from sklearn.model_selection import GridSearchCV

# 定义参数网格
param_grid = {'C': [0.1, 1, 10],
              'kernel': ['linear', 'poly', 'rbf']}

# 创建SVM模型
model = SVC()

# 创建GridSearchCV对象
grid_search = GridSearchCV(estimator=model, param_grid=param_grid, cv=5, scoring='accuracy')

# 在训练数据上进行网格搜索
grid_search.fit(X_train, y_train)

# 打印最佳参数和最佳分数
## GridSearchCV(cv=5, estimator=SVC(),
##              param_grid={'C': [0.1, 1, 10],
##                          'kernel': ['linear', 'poly', 'rbf']},
##              scoring='accuracy')
print("最佳参数:", grid_search.best_params_)
## 最佳参数: {'C': 1, 'kernel': 'linear'}
print("最佳分数:", grid_search.best_score_)

# 使用最佳参数的模型进行预测
## 最佳分数: 0.9583333333333334
best_model = grid_search.best_estimator_
y_pred = best_model.predict(X_test)

# 评估最佳模型性能
accuracy = accuracy_score(y_test, y_pred)
print("最佳模型准确率:", accuracy)
## 最佳模型准确率: 1.0

6.4 KNN

K近邻(K-Nearest Neighbors,KNN)是一种基本的监督学习算法,用于分类和回归问题。它的核心思想是基于特征空间中数据点的距离来进行预测。以下是KNN的原理总结、一个完整的Sklearn示例以及如何使用网格搜索调整参数的示例:

6.4.1 KNN 原理总结:

KNN算法的基本原理是根据数据点之间的距离,将一个未标记的数据点分为与其最近的K个已标记数据点所属的类别。KNN的工作流程如下:

  1. 选择K值:选择一个整数K,表示要考虑的最近邻居数量。
  2. 计算距离:计算未标记数据点与所有已标记数据点之间的距离。
  3. 选择K个最近邻:选择K个距离最近的已标记数据点。
  4. 多数投票:将这K个最近邻中的多数类别作为未标记数据点的预测类别。
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score

# 加载鸢尾花数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target

# 划分数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建KNN分类器
model = KNeighborsClassifier(n_neighbors=3)

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

# 进行预测
## KNeighborsClassifier(n_neighbors=3)
y_pred = model.predict(X_test)

# 评估模型性能
accuracy = accuracy_score(y_test, y_pred)
print("准确率:", accuracy)
## 准确率: 1.0

6.4.2 使用网格搜索调整参数:

你可以使用Sklearn的GridSearchCV来执行网格搜索以找到最佳的K值:

from sklearn.model_selection import GridSearchCV

# 定义参数网格
param_grid = {'n_neighbors': [3, 5, 7, 9]}

# 创建KNN分类器
model = KNeighborsClassifier()

# 创建GridSearchCV对象
grid_search = GridSearchCV(estimator=model, param_grid=param_grid, cv=5, scoring='accuracy')

# 在训练数据上进行网格搜索
grid_search.fit(X_train, y_train)

# 打印最佳参数和最佳分数
## GridSearchCV(cv=5, estimator=KNeighborsClassifier(),
##              param_grid={'n_neighbors': [3, 5, 7, 9]}, scoring='accuracy')
print("最佳K值:", grid_search.best_params_['n_neighbors'])
## 最佳K值: 3
print("最佳分数:", grid_search.best_score_)

# 使用最佳参数的模型进行预测
## 最佳分数: 0.9583333333333334
best_model = grid_search.best_estimator_
y_pred = best_model.predict(X_test)

# 评估最佳模型性能
accuracy = accuracy_score(y_test, y_pred)
print("最佳模型准确率:", accuracy)
## 最佳模型准确率: 1.0

6.5 决策树

决策树(Decision Tree)是一种用于分类和回归问题的监督学习算法。它基于树状结构进行决策,通过在每个内部节点选择一个特征来分裂数据,最终将数据划分为不同的类别或值

6.5.1 决策树原理:

决策树的基本原理是通过递归地将数据划分为不同的子集,直到满足某个停止条件(如达到最大深度或叶子节点中的样本数小于某个阈值)。在每个节点上,决策树选择一个特征,以最大程度地分隔不同类别的数据点。这个过程不断重复,直到构建出一棵树。

6.5.2 Sklearn 决策树示例:

下面是一个完整的Sklearn示例,使用决策树进行鸢尾花分类:

from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score

# 加载鸢尾花数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target

# 划分数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建决策树分类器
model = DecisionTreeClassifier()

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

# 进行预测
## DecisionTreeClassifier()
y_pred = model.predict(X_test)

# 评估模型性能
accuracy = accuracy_score(y_test, y_pred)
print("准确率:", accuracy)
## 准确率: 1.0

6.5.3 使用网格搜索调整参数:

你可以使用Sklearn的GridSearchCV来执行网格搜索以找到最佳的参数组合,例如最大深度:

from sklearn.model_selection import GridSearchCV

# 定义参数网格
param_grid = {'max_depth': [None, 5, 10, 15, 20]}

# 创建决策树分类器
model = DecisionTreeClassifier()

# 创建GridSearchCV对象
grid_search = GridSearchCV(estimator=model, param_grid=param_grid, cv=5, scoring='accuracy')

# 在训练数据上进行网格搜索
grid_search.fit(X_train, y_train)

# 打印最佳参数和最佳分数
## GridSearchCV(cv=5, estimator=DecisionTreeClassifier(),
##              param_grid={'max_depth': [None, 5, 10, 15, 20]},
##              scoring='accuracy')
print("最佳最大深度:", grid_search.best_params_['max_depth'])
## 最佳最大深度: None
print("最佳分数:", grid_search.best_score_)

# 使用最佳参数的模型进行预测
## 最佳分数: 0.95
best_model = grid_search.best_estimator_
y_pred = best_model.predict(X_test)

# 评估最佳模型性能
accuracy = accuracy_score(y_test, y_pred)
print("最佳模型准确率:", accuracy)
## 最佳模型准确率: 1.0

6.6 随机森林

集成学习(Ensemble Learning)是一种机器学习技术,它结合多个基本模型以获得更好的性能。其中一个最流行的集成学习方法是随机森林(Random Forest),它是基于决策树的一种集成方法。

6.6.1 基本原理

集成学习的基本原理是将多个弱学习器组合成一个强学习器。这可以通过多种方式实现,其中一种方法是投票法(Voting)、平均法(Averaging)和Bagging等。随机森林是一种Bagging方法,它使用多个决策树组成一个森林,每个决策树在数据的不同子集上训练,然后通过投票来做出最终的预测。

6.6.2 Sklearn 随机森林示例:

下面是一个完整的Sklearn示例,使用随机森林进行鸢尾花分类:

from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score

# 加载鸢尾花数据集
iris = datasets.load_iris()
X = iris.data
y = iris.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, random_state=42)

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

# 进行预测
## RandomForestClassifier(random_state=42)
y_pred = model.predict(X_test)

# 评估模型性能
accuracy = accuracy_score(y_test, y_pred)
print("准确率:", accuracy)
## 准确率: 1.0

6.6.3 使用网格搜索调整参数:

你可以使用Sklearn的GridSearchCV来执行网格搜索以找到最佳的参数组合,例如最大深度和树的数量:

from sklearn.model_selection import GridSearchCV

# 定义参数网格
param_grid = {
    'n_estimators': [50, 100, 200],
    'max_depth': [None, 10, 20, 30]
}

# 创建随机森林分类器
model = RandomForestClassifier(random_state=42)

# 创建GridSearchCV对象
grid_search = GridSearchCV(estimator=model, param_grid=param_grid, cv=5, scoring='accuracy')

# 在训练数据上进行网格搜索
grid_search.fit(X_train, y_train)

# 打印最佳参数和最佳分数
## GridSearchCV(cv=5, estimator=RandomForestClassifier(random_state=42),
##              param_grid={'max_depth': [None, 10, 20, 30],
##                          'n_estimators': [50, 100, 200]},
##              scoring='accuracy')
print("最佳树的数量:", grid_search.best_params_['n_estimators'])
## 最佳树的数量: 200
print("最佳最大深度:", grid_search.best_params_['max_depth'])
## 最佳最大深度: None
print("最佳分数:", grid_search.best_score_)

# 使用最佳参数的模型进行预测
## 最佳分数: 0.95
best_model = grid_search.best_estimator_
y_pred = best_model.predict(X_test)

# 评估最佳模型性能
accuracy = accuracy_score(y_test, y_pred)
print("最佳模型准确率:", accuracy)
## 最佳模型准确率: 1.0

6.7 Xgboost

XGBoost(eXtreme Gradient Boosting)是一种梯度提升机(Gradient Boosting Machine)的变体,它在梯度提升算法的基础上引入了正则化和改进的分裂策略,以提高性能和鲁棒性。以下是XGBoost的原理总结、一个完整的Sklearn示例以及如何使用网格搜索调整参数的示例:

6.7.1 XGBoost 原理总结:

XGBoost的主要特点包括:

  1. 梯度提升:XGBoost基于梯度提升算法,用于提升多个弱学习器的性能。每次迭代都会训练一个弱学习器,然后将其添加到集成模型中,以纠正之前迭代中的错误。

  2. 正则化:XGBoost引入了L1和L2正则化,以防止过拟合。正则化项会在损失函数中加入,控制叶子节点的权重。

  3. 改进的分裂策略:XGBoost采用了一种高效的分裂策略,通过遍历特征的分割点来确定最佳分裂,以降低计算复杂度。

  4. 并行化处理:XGBoost支持并行处理,可以有效地处理大规模数据集。

6.7.2 Sklearn XGBoost 示例:

下面是一个完整的Sklearn示例,使用XGBoost进行乳腺癌分类:

import xgboost as xgb
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# 加载乳腺癌数据集
data = load_breast_cancer()
X = data.data
y = data.target

# 划分数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建XGBoost分类器
model = xgb.XGBClassifier()

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

# 进行预测
## XGBClassifier(base_score=0.5, booster='gbtree', callbacks=None,
##               colsample_bylevel=1, colsample_bynode=1, colsample_bytree=1,
##               early_stopping_rounds=None, enable_categorical=False,
##               eval_metric=None, gamma=0, gpu_id=-1, grow_policy='depthwise',
##               importance_type=None, interaction_constraints='',
##               learning_rate=0.300000012, max_bin=256, max_cat_to_onehot=4,
##               max_delta_step=0, max_depth=6, max_leaves=0, min_child_weight=1,
##               missing=nan, monotone_constraints='()', n_estimators=100,
##               n_jobs=0, num_parallel_tree=1, predictor='auto', random_state=0,
##               reg_alpha=0, reg_lambda=1, ...)
y_pred = model.predict(X_test)

# 评估模型性能
accuracy = accuracy_score(y_test, y_pred)
print("准确率:", accuracy)
## 准确率: 0.956140350877193

6.7.3 使用网格搜索调整参数:

你可以使用Sklearn的GridSearchCV来执行网格搜索以找到最佳的参数组合,例如最大深度和学习率:

from sklearn.model_selection import GridSearchCV

# 定义参数网格
param_grid = {
    'max_depth': [3, 4, 5],
    'learning_rate': [0.01, 0.1, 0.2],
    'n_estimators': [50, 100, 200]
}

# 创建XGBoost分类器
model = xgb.XGBClassifier()

# 创建GridSearchCV对象
grid_search = GridSearchCV(estimator=model, param_grid=param_grid, cv=5, scoring='accuracy')

# 在训练数据上进行网格搜索
grid_search.fit(X_train, y_train)

# 打印最佳参数和最佳分数
## GridSearchCV(cv=5,
##              estimator=XGBClassifier(base_score=None, booster=None,
##                                      callbacks=None, colsample_bylevel=None,
##                                      colsample_bynode=None,
##                                      colsample_bytree=None,
##                                      early_stopping_rounds=None,
##                                      enable_categorical=False, eval_metric=None,
##                                      gamma=None, gpu_id=None, grow_policy=None,
##                                      importance_type=None,
##                                      interaction_constraints=None,
##                                      learning_rate=None, max_bin=None,
##                                      max_ca...t=None,
##                                      max_delta_step=None, max_depth=None,
##                                      max_leaves=None, min_child_weight=None,
##                                      missing=nan, monotone_constraints=None,
##                                      n_estimators=100, n_jobs=None,
##                                      num_parallel_tree=None, predictor=None,
##                                      random_state=None, reg_alpha=None,
##                                      reg_lambda=None, ...),
##              param_grid={'learning_rate': [0.01, 0.1, 0.2],
##                          'max_depth': [3, 4, 5],
##                          'n_estimators': [50, 100, 200]},
##              scoring='accuracy')
print("最佳最大深度:", grid_search.best_params_['max_depth'])
## 最佳最大深度: 3
print("最佳学习率:", grid_search.best_params_['learning_rate'])
## 最佳学习率: 0.1
print("最佳树的数量:", grid_search.best_params_['n_estimators'])
## 最佳树的数量: 200
print("最佳分数:", grid_search.best_score_)

# 使用最佳参数的模型进行预测
## 最佳分数: 0.9714285714285715
best_model = grid_search.best_estimator_
y_pred = best_model.predict(X_test)

# 评估最佳模型性能
accuracy = accuracy_score(y_test, y_pred)
print("最佳模型准确率:", accuracy)
## 最佳模型准确率: 0.9649122807017544

6.8 特征选择

特征选择是机器学习中的一个重要步骤,它涉及确定哪些特征对于建立准确的模型是最重要的,以减少维度和提高模型的性能。Sklearn提供了多种特征选择方法,包括过滤式(Filter)、包裹式(Wrapper)和嵌入式(Embedded)方法。以下是特征选择的原理总结和一个Sklearn案例示例:

6.8.1 特征选择原理总结:

  1. 过滤式特征选择(Filter):过滤式方法独立于任何具体的机器学习算法。它使用某种特征评估标准(如方差、相关性、互信息等)来对特征进行排序或选择。最常见的过滤式方法包括方差选择和互信息选择。

  2. 包裹式特征选择(Wrapper):包裹式方法根据一个具体的机器学习模型(如决策树、SVM等)的性能来评估特征的重要性。它使用递归特征消除(RFE)、正向选择(Forward Selection)或反向选择(Backward Elimination)等技术。

  3. 嵌入式特征选择(Embedded):嵌入式方法将特征选择嵌入到机器学习模型的训练过程中。最常见的嵌入式方法是L1正则化,它将特征的权重稀疏化,从而实现特征选择。

6.8.2 Sklearn 特征选择示例:

以下是一个Sklearn案例示例,使用乳腺癌数据集和特征选择方法来选择重要的特征:

from sklearn.datasets import load_breast_cancer
from sklearn.feature_selection import SelectKBest, f_classif
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score

# 加载乳腺癌数据集
data = load_breast_cancer()
X = data.data
y = data.target

# 划分数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 使用SelectKBest和f_classif方法选择最重要的特征
selector = SelectKBest(score_func=f_classif, k=10)
X_train_selected = selector.fit_transform(X_train, y_train)
X_test_selected = selector.transform(X_test)

# 创建支持向量机分类器
model = SVC()

# 训练模型
model.fit(X_train_selected, y_train)

# 进行预测
## SVC()
y_pred = model.predict(X_test_selected)

# 评估模型性能
accuracy = accuracy_score(y_test, y_pred)
print("准确率:", accuracy)
## 准确率: 0.9473684210526315

在上述示例中,我们使用了SelectKBest和f_classif方法来选择最重要的10个特征,并将其用于支持向量机分类器的训练和预测。这是一个过滤式特征选择方法的示例。你还可以尝试包裹式和嵌入式方法,具体取决于你的特定问题和需求。特征选择有助于提高模型的性能,减少计算成本并降低维度。

6.9 模型评估与交叉验证

在机器学习中,模型评估和交叉验证是至关重要的步骤,用于评估模型的性能、泛化能力和稳定性。Scikit-learn(Sklearn)提供了丰富的工具和方法来执行模型评估和交叉验证。

6.9.1 模型评估与交叉验证总结:

  1. 模型评估指标:在机器学习中,有多种模型评估指标,包括准确率、精确度、召回率、F1分数、ROC曲线和AUC等。不同的问题和任务可能需要使用不同的评估指标。

  2. 训练集和测试集划分:通常,数据集会分为训练集和测试集。模型在训练集上进行训练,然后在测试集上进行评估,以评估模型的性能。

  3. 交叉验证:交叉验证是一种更严格的评估方法,它将数据集分成多个部分,进行多次训练和测试。常见的交叉验证方法包括k折交叉验证和留一交叉验证。

  4. Sklearn工具:Sklearn提供了用于模型评估和交叉验证的工具,包括train_test_split函数、cross_val_score函数和GridSearchCV用于参数调优。

6.9.2 Sklearn 模型评估与交叉验证示例:

以下是一个Sklearn案例示例,使用乳腺癌数据集进行模型评估和交叉验证:

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score

# 加载乳腺癌数据集
data = load_breast_cancer()
X = data.data
y = data.target

# 划分数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建支持向量机分类器
model = SVC()

# 在训练集上进行交叉验证
cv_scores = cross_val_score(model, X_train, y_train, cv=5, scoring='accuracy')

# 计算交叉验证准确率的均值和标准差
cv_mean = cv_scores.mean()
cv_std = cv_scores.std()

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

# 在测试集上进行预测
## SVC()
y_pred = model.predict(X_test)

# 计算测试集准确率
test_accuracy = accuracy_score(y_test, y_pred)

print("交叉验证准确率均值:", cv_mean)
## 交叉验证准确率均值: 0.9032967032967033
print("交叉验证准确率标准差:", cv_std)
## 交叉验证准确率标准差: 0.037038020980994985
print("测试集准确率:", test_accuracy)
## 测试集准确率: 0.9473684210526315

在上述示例中,我们使用cross_val_score函数执行了5折交叉验证,计算了交叉验证准确率的均值和标准差。然后,我们使用相同的模型在测试集上进行了评估,计算了测试集的准确率。这个示例演示了如何使用Sklearn来进行模型评估和交叉验证。不同的评估指标和交叉验证策略可以根据具体问题进行选择。