4.6 Scikit-learn 与深度学习框架的结合


文档摘要

4.6 Scikit-learn 与深度学习框架的结合 Scikit-learn 与深度学习框架的结合:代码实践与深度详解 4.6 Scikit-learn 与深度学习框架的结合 Scikit-learn,作为 Python 中最受欢迎的机器学习库之一,以其简洁的 API、丰富的算法和强大的工具集,在传统机器学习领域占据着举足轻重的地位。然而,随着深度学习在图像识别、自然语言处理等领域的巨大成功,越来越多的开发者开始探索如何将 Scikit-learn 的优势与深度学习框架的强大能力相结合,构建更高效、更灵活的机器学习解决方案。 4.6.

4.6 Scikit-learn 与深度学习框架的结合

Scikit-learn 与深度学习框架的结合:代码实践与深度详解

4.6 Scikit-learn 与深度学习框架的结合

Scikit-learn,作为 Python 中最受欢迎的机器学习库之一,以其简洁的 API、丰富的算法和强大的工具集,在传统机器学习领域占据着举足轻重的地位。然而,随着深度学习在图像识别、自然语言处理等领域的巨大成功,越来越多的开发者开始探索如何将 Scikit-learn 的优势与深度学习框架的强大能力相结合,构建更高效、更灵活的机器学习解决方案。

4.6.1 结合的必要性与优势

虽然深度学习框架自身也提供了丰富的机器学习工具,但 Scikit-learn 在某些方面仍然具有独特的优势,使其与深度学习框架的结合成为一种有价值的选择:

  • 数据预处理与特征工程的便利性: Scikit-learn 提供了大量的预处理工具 (如标准化、归一化、特征选择、降维等) 和特征工程方法,这些工具经过多年的发展和优化,稳定可靠,API 简洁易用。在深度学习模型训练前,利用 Scikit-learn 进行数据预处理和特征工程,可以有效提升模型性能,并简化开发流程。

  • 模型选择与评估的系统性: Scikit-learn 提供了完善的模型选择和评估工具,如交叉验证、网格搜索、各种评估指标等。这些工具可以帮助开发者系统地评估深度学习模型的性能,并进行超参数调优,从而找到最佳模型配置。

  • 传统机器学习算法的补充作用: 在某些场景下,传统机器学习算法 (如逻辑回归、支持向量机、随机森林等) 仍然具有深度学习模型无法比拟的优势,例如在小数据集、高维数据或需要可解释性的任务中。将 Scikit-learn 的传统机器学习算法与深度学习模型结合,可以构建更全面的模型体系,应对更复杂的任务。

  • Pipeline 的强大工作流: Scikit-learn 的 Pipeline 机制可以将多个数据预处理、特征工程和模型训练步骤串联起来,形成一个完整的工作流。将深度学习模型融入 Scikit-learn Pipeline 中,可以提高代码的可读性、可维护性和复用性,并简化实验流程。

4.6.2 Scikit-learn 与深度学习框架的结合方式

Scikit-learn 与深度学习框架的结合主要体现在以下几个方面:

  1. 使用 Scikit-learn 进行数据预处理,深度学习框架构建模型: 这是最常见的结合方式。利用 Scikit-learn 强大的数据预处理能力,对数据进行清洗、转换、特征工程等操作,然后将预处理后的数据输入到深度学习框架 (如 TensorFlow 或 PyTorch) 中构建的模型进行训练。

  2. 使用深度学习框架进行特征提取,Scikit-learn 构建传统机器学习模型: 深度学习模型 (尤其是卷积神经网络 CNN 和循环神经网络 RNN) 在特征提取方面表现出色。可以将预训练的深度学习模型作为特征提取器,提取数据的高级特征,然后将这些特征输入到 Scikit-learn 的传统机器学习模型 (如分类器、回归器) 中进行后续任务。

  3. 将深度学习模型封装为 Scikit-learn 兼容的 Estimator: 为了更好地将深度学习模型融入 Scikit-learn 的生态系统,可以将深度学习模型封装成 Scikit-learn 兼容的 Estimator (估计器)。这样就可以像使用 Scikit-learn 内置模型一样,使用交叉验证、网格搜索等工具对深度学习模型进行评估和调优,并将其集成到 Pipeline 中。

  4. 使用 Scikit-learn 的评估指标评估深度学习模型: Scikit-learn 提供了丰富的评估指标 (如准确率、精确率、召回率、F1-score、AUC-ROC 等),可以直接用于评估深度学习模型的性能,无需重复造轮子。

4.6.3 代码实践:Scikit-learn 与 TensorFlow 的结合

接下来,我们将通过具体的代码示例,演示 Scikit-learn 与 TensorFlow 的结合。

示例 1:使用 Scikit-learn StandardScaler 进行数据标准化,TensorFlow 构建神经网络模型

import numpy as np from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split from tensorflow import keras from tensorflow.keras import layers # 1. 生成模拟数据 X = np.random.rand(1000, 10) # 1000 个样本,10 个特征 y = np.random.randint(0, 2, 1000) # 二分类任务 # 2. 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 3. 使用 Scikit-learn StandardScaler 进行数据标准化 scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) # fit_transform 在训练集上拟合和转换 X_test_scaled = scaler.transform(X_test) # transform 在测试集上使用训练集拟合的 scaler 进行转换 # 4. 使用 TensorFlow Keras 构建神经网络模型 model = keras.Sequential([ layers.Dense(64, activation='relu', input_shape=(X_train_scaled.shape[1],)), # 输入层 layers.Dense(32, activation='relu'), # 隐藏层 layers.Dense(1, activation='sigmoid') # 输出层 (二分类) ]) # 5. 编译模型 model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) # 6. 训练模型 model.fit(X_train_scaled, y_train, epochs=10, batch_size=32, validation_split=0.1) # 7. 评估模型 loss, accuracy = model.evaluate(X_test_scaled, y_test) print(f"测试集 Loss: {loss:.4f}") print(f"测试集 Accuracy: {accuracy:.4f}")

代码详解:

  • 数据预处理: 我们首先使用 sklearn.preprocessing.StandardScaler 对训练集数据 X_train 进行标准化,并使用训练集上拟合的 scaler 对测试集数据 X_test 进行相同的转换。关键在于 fit_transformtransform 的区分。 fit_transform 用于训练集,学习数据的均值和标准差,并进行转换;transform 用于测试集或新数据,使用训练集学习到的均值和标准差进行转换,保证数据处理的一致性,避免信息泄露。

  • 模型构建: 使用 TensorFlow Keras 构建一个简单的多层感知机 (MLP) 模型,包括一个输入层、两个隐藏层和一个输出层 (sigmoid 激活函数用于二分类)。

  • 模型训练与评估: 使用 model.fit 训练模型,并使用 model.evaluate 在测试集上评估模型的性能。

示例 2:使用预训练的 TensorFlow Hub 模型进行特征提取,Scikit-learn LogisticRegression 进行分类

import numpy as np from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score import tensorflow as tf import tensorflow_hub as hub # 1. 生成模拟文本数据 (简化版) texts = [ "This is a positive review.", "This movie is terrible.", "I enjoyed this book very much.", "The food was awful.", "Excellent service and quality." ] labels = np.array([1, 0, 1, 0, 1]) # 1: positive, 0: negative # 2. 划分训练集和测试集 texts_train, texts_test, y_train, y_test = train_test_split(texts, labels, test_size=0.2, random_state=42) # 3. 加载预训练的 TensorFlow Hub 文本嵌入模型 (例如:Universal Sentence Encoder) embed = hub.load("https://tfhub.dev/google/universal-sentence-encoder/4") # 选择一个合适的文本嵌入模型 # 4. 使用预训练模型提取文本特征 X_train_features = embed(texts_train).numpy() X_test_features = embed(texts_test).numpy() # 5. 使用 Scikit-learn LogisticRegression 构建分类器 classifier = LogisticRegression(random_state=42) # 6. 训练分类器 classifier.fit(X_train_features, y_train) # 7. 预测与评估 y_pred = classifier.predict(X_test_features) accuracy = accuracy_score(y_test, y_pred) print(f"测试集 Accuracy: {accuracy:.4f}")

代码详解:

  • 特征提取: 我们使用 TensorFlow Hub 加载预训练的 Universal Sentence Encoder 模型,该模型可以将文本转换为固定长度的向量表示 (文本嵌入)。embed(texts_train).numpy() 将训练集文本输入到预训练模型中,得到文本特征矩阵 X_train_features

  • 模型构建与训练: 使用 Scikit-learn LogisticRegression 构建逻辑回归分类器,并使用提取的文本特征 X_train_features 和对应的标签 y_train 进行训练。

  • 预测与评估: 使用训练好的逻辑回归模型对测试集文本特征 X_test_features 进行预测,并使用 sklearn.metrics.accuracy_score 评估模型的准确率。

示例 3:将 TensorFlow Keras 模型封装为 Scikit-learn 兼容的 KerasClassifier,并使用 GridSearchCV 进行超参数调优

import numpy as np from sklearn.model_selection import GridSearchCV, train_test_split from tensorflow import keras from tensorflow.keras import layers from scikeras.wrappers import KerasClassifier # 导入 Scikit-learn 兼容的 KerasClassifier # 1. 生成模拟数据 (同示例 1) X = np.random.rand(1000, 10) y = np.random.randint(0, 2, 1000) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 2. 定义一个函数,用于创建 Keras 模型 (GridSearchCV 需要) def create_model(optimizer='adam', units=64): model = keras.Sequential([ layers.Dense(units, activation='relu', input_shape=(X_train.shape[1],)), layers.Dense(32, activation='relu'), layers.Dense(1, activation='sigmoid') ]) model.compile(optimizer=optimizer, loss='binary_crossentropy', metrics=['accuracy']) return model # 3. 将 Keras 模型封装为 KerasClassifier keras_clf = KerasClassifier(model=create_model, verbose=0) # verbose=0 关闭训练过程输出 # 4. 定义超参数网格 param_grid = { 'optimizer': ['adam', 'sgd'], 'units': [32, 64, 128], 'epochs': [5, 10], 'batch_size': [16, 32] } # 5. 使用 GridSearchCV 进行超参数调优 grid = GridSearchCV(estimator=keras_clf, param_grid=param_grid, cv=3) # 3 折交叉验证 grid_result = grid.fit(X_train, y_train) # 6. 输出最佳参数和最佳性能 print(f"最佳参数组合: {grid_result.best_params_}") print(f"最佳交叉验证得分: {grid_result.best_score_:.4f}") # 7. 使用最佳模型在测试集上评估 best_model = grid_result.best_estimator_ loss, accuracy = best_model.model.evaluate(X_test, y_test) # 注意访问内部的 Keras 模型 print(f"测试集 Loss: {loss:.4f}") print(f"测试集 Accuracy: {accuracy:.4f}")

代码详解:

  • KerasClassifier 封装: 我们使用 scikeras.wrappers.KerasClassifiercreate_model 函数创建的 Keras 模型封装成 Scikit-learn 兼容的分类器 keras_clf需要安装 scikeras 库 (pip install scikeras)。

  • GridSearchCV 超参数调优: 使用 Scikit-learn GridSearchCVkeras_clf 进行超参数调优。param_grid 定义了需要搜索的超参数及其取值范围。cv=3 表示使用 3 折交叉验证。

  • 最佳模型评估: grid_result.best_estimator_ 获取 GridSearchCV 找到的最佳模型,然后使用 best_model.model.evaluate 在测试集上评估其性能。注意需要通过 best_model.model 访问内部的 Keras 模型进行评估。

4.6.4 代码实践:Scikit-learn 与 PyTorch 的结合

Scikit-learn 与 PyTorch 的结合方式与 TensorFlow 类似,主要区别在于深度学习框架的 API 和库的选择。

示例 4:使用 Scikit-learn MinMaxScaler 进行数据归一化,PyTorch 构建神经网络模型

import numpy as np from sklearn.preprocessing import MinMaxScaler from sklearn.model_selection import train_test_split import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import Dataset, DataLoader # 1. 生成模拟数据 (同示例 1) X = np.random.rand(1000, 10) y = np.random.randint(0, 2, 1000) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 2. 使用 Scikit-learn MinMaxScaler 进行数据归一化 scaler = MinMaxScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test) # 3. 将数据转换为 PyTorch Tensor X_train_tensor = torch.tensor(X_train_scaled, dtype=torch.float32) X_test_tensor = torch.tensor(X_test_scaled, dtype=torch.float32) y_train_tensor = torch.tensor(y_train, dtype=torch.float32).unsqueeze(1) # 转换为列向量 y_test_tensor = torch.tensor(y_test, dtype=torch.float32).unsqueeze(1) # 4. 定义 PyTorch Dataset class CustomDataset(Dataset): def __init__(self, features, labels): self.features = features self.labels = labels def __len__(self): return len(self.features) def __getitem__(self, idx): return self.features[idx], self.labels[idx] train_dataset = CustomDataset(X_train_tensor, y_train_tensor) test_dataset = CustomDataset(X_test_tensor, y_test_tensor) # 5. 定义 PyTorch DataLoader train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True) test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False) # 6. 定义 PyTorch 神经网络模型 class Net(nn.Module): def __init__(self, input_size): super(Net, self).__init__() self.fc1 = nn.Linear(input_size, 64) self.relu = nn.ReLU() self.fc2 = nn.Linear(64, 32) self.fc3 = nn.Linear(32, 1) self.sigmoid = nn.Sigmoid() def forward(self, x): out = self.fc1(x) out = self.relu(out) out = self.fc2(out) out = self.relu(out) out = self.fc3(out) out = self.sigmoid(out) return out model = Net(input_size=X_train_tensor.shape[1]) # 7. 定义损失函数和优化器 criterion = nn.BCELoss() # 二分类交叉熵损失 optimizer = optim.Adam(model.parameters()) # 8. 训练模型 epochs = 10 for epoch in range(epochs): for inputs, labels in train_loader: optimizer.zero_grad() # 梯度清零 outputs = model(inputs) loss = criterion(outputs, labels) loss.backward() # 反向传播 optimizer.step() # 更新权重 # 9. 评估模型 model.eval() # 设置为评估模式 correct = 0 total = 0 with torch.no_grad(): # 关闭梯度计算 for inputs, labels in test_loader: outputs = model(inputs) predicted = (outputs > 0.5).float() # 阈值 0.5 进行二分类 total += labels.size(0) correct += (predicted == labels).sum().item() accuracy = correct / total print(f"测试集 Accuracy: {accuracy:.4f}")

代码详解:

  • 数据预处理: 使用 sklearn.preprocessing.MinMaxScaler 进行数据归一化,与 TensorFlow 示例类似。

  • 数据转换为 Tensor 和 Dataset/DataLoader: PyTorch 使用 Tensor 作为数据载体,并使用 Dataset 和 DataLoader 管理数据加载和批处理。我们将 Scikit-learn 预处理后的 NumPy 数组转换为 PyTorch Tensor,并创建自定义 Dataset 和 DataLoader。

  • 模型构建: 使用 PyTorch nn.Module 定义神经网络模型,结构与 TensorFlow 示例类似。

  • 模型训练与评估: 使用 PyTorch 的训练循环,包括前向传播、计算损失、反向传播、更新权重等步骤。评估模型时,需要将模型设置为评估模式 model.eval(),并关闭梯度计算 torch.no_grad()

示例 5:将 PyTorch 模型封装为 Scikit-learn 兼容的 Estimator (使用 skorch 库)

import numpy as np from sklearn.model_selection import GridSearchCV, train_test_split from sklearn.metrics import accuracy_score import torch import torch.nn as nn import torch.optim as optim from skorch import NeuralNetClassifier # 导入 skorch 的 NeuralNetClassifier # 1. 生成模拟数据 (同示例 1) X = np.random.rand(1000, 10) y = np.random.randint(0, 2, 1000) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) X_train = X_train.astype(np.float32) # skorch 需要 float32 类型 X_test = X_test.astype(np.float32) # 2. 定义 PyTorch 模型 (与示例 4 相同) class Net(nn.Module): def __init__(self, input_size): super(Net, self).__init__() self.fc1 = nn.Linear(input_size, 64) self.relu = nn.ReLU() self.fc2 = nn.Linear(64, 32) self.fc3 = nn.Linear(32, 1) self.sigmoid = nn.Sigmoid() def forward(self, x): out = self.fc1(x) out = self.relu(out) out = self.fc2(out) out = self.relu(out) out = self.fc3(out) out = self.sigmoid(out) return out # 3. 使用 skorch NeuralNetClassifier 封装 PyTorch 模型 class SkorchNet(NeuralNetClassifier): # 创建一个继承自 NeuralNetClassifier 的类 def __init__(self, input_size, **kwargs): super(SkorchNet, self).__init__(module=Net, module__input_size=input_size, **kwargs) # 传递 input_size 参数 skorch_clf = SkorchNet(input_size=X_train.shape[1], optimizer=optim.Adam, criterion=nn.BCELoss, max_epochs=10, batch_size=32, verbose=0) # verbose=0 关闭训练输出 # 4. 训练模型 skorch_clf.fit(X_train, y_train) # 5. 预测与评估 y_pred_proba = skorch_clf.predict_proba(X_test)[:, 1] # 获取正类概率 y_pred = (y_pred_proba > 0.5).astype(int) accuracy = accuracy_score(y_test, y_pred) print(f"测试集 Accuracy: {accuracy:.4f}") # 6. 使用 GridSearchCV 进行超参数调优 (可选) param_grid = { 'module__input_size': [X_train.shape[1]], # 必须传递 input_size 'optimizer__lr': [0.001, 0.01], # 注意 optimizer 参数的命名方式 'max_epochs': [5, 10], 'batch_size': [16, 32] } grid = GridSearchCV(estimator=skorch_clf, param_grid=param_grid, cv=3) grid_result = grid.fit(X_train, y_train) print(f"GridSearchCV 最佳参数: {grid_result.best_params_}") print(f"GridSearchCV 最佳得分: {grid_result.best_score_:.4f}")

代码详解:

  • skorch NeuralNetClassifier 封装: 我们使用 skorch.NeuralNetClassifier 将 PyTorch 模型 Net 封装成 Scikit-learn 兼容的分类器 skorch_clf需要安装 skorch 库 (pip install skorch)。 Skorch 库简化了 PyTorch 模型与 Scikit-learn 的集成。

  • 模型训练、预测与评估: 封装后的 skorch_clf 可以像 Scikit-learn 内置模型一样使用 fitpredictpredict_proba 等方法进行训练、预测和评估。

  • GridSearchCV 超参数调优: 同样可以使用 GridSearchCVskorch_clf 进行超参数调优,与 TensorFlow 示例类似。注意 skorch 中超参数的命名方式,例如 optimizer 的学习率参数需要写成 optimizer__lr

4.6.5 高级应用与展望

除了上述基本结合方式,Scikit-learn 与深度学习框架的结合还有更高级的应用场景:

  • Pipeline 集成深度学习模型: 将预处理步骤 (Scikit-learn)、特征提取步骤 (深度学习模型) 和最终分类/回归模型 (Scikit-learn 或深度学习模型) 串联成一个 Pipeline,构建端到端的工作流。

  • 集成学习与模型融合: 将 Scikit-learn 的传统机器学习模型与深度学习模型进行集成,例如使用 Stacking 或 VotingEnsemble 方法,结合不同模型的优势,提高整体性能和鲁棒性。

  • 迁移学习与微调: 利用预训练的深度学习模型作为特征提取器或初始化模型参数,结合 Scikit-learn 的模型选择和评估工具,进行迁移学习和微调,加速模型开发,并提升小数据集上的性能。

展望:

Scikit-learn 与深度学习框架的结合是未来机器学习发展的重要趋势。随着深度学习技术的不断成熟和普及,以及 Scikit-learn 生态系统的持续完善,两者之间的融合将会更加深入和紧密。我们可以期待更多更强大的工具和方法出现,进一步简化深度学习模型的开发、部署和应用,并推动机器学习技术在更广泛领域的应用。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U