如何在Python中保存训练好的模型

在Python中保存训练好的模型的方法是什么?

在实际的机器学习(ML)应用中,找到最佳算法/模型并不是你的全部责任。保存、存储和打包这些模型以备将来使用和部署是至关重要的。

这些实践有以下几个原因:

  • 备份:训练好的模型可以作为备份保存,以防原始数据被损坏或销毁。
  • 可重用性和可重现性:构建ML模型本质上是耗时的。为了节省成本和时间,确保每次运行模型时都能得到相同的结果是至关重要的。正确保存和存储模型可以解决这个问题。
  • 部署:在实际应用中部署训练好的模型时,需要将其打包以便于部署。这样其他系统和应用程序就可以在没有太多麻烦的情况下使用同一个模型。

再次强调,保存和存储ML模型可以方便共享、重用和重现性,而打包模型可以实现快速无痛部署。这三个操作相互配合,简化整个模型管理过程。

在本文中,您将学习不同的方法来保存、存储和打包训练好的机器学习模型,以及每种方法的优缺点。但在此之前,您必须了解这三个术语之间的区别。

保存 vs. 打包 vs. 存储 ML 模型

尽管所有这些术语看起来相似,但它们并不相同。

保存 vs. 存储 vs. 打包 ML 模型 | 来源:作者

保存模型是指将模型的参数、权重等保存到文件中的过程。通常,所有的ML和DL模型都提供了一些保存模型的方法(例如model.save())。但您必须知道,保存只是一个单独的操作,并且只提供一个模型二进制文件,因此您仍然需要编写代码使您的ML应用程序可以投入生产。

打包,另一方面,指的是将模型文件、依赖项、配置文件等必要组件捆绑或容器化为一个可部署的单一包的过程。打包的目标是使在生产环境中分发和部署ML模型变得更加容易。

一旦打包完成,模型可以在不同的环境中部署,使得模型可以在各种生产环境中使用,例如Web应用程序、移动应用程序等。Docker是一种可以实现这一目标的工具之一。

存储ML模型是指将训练好的模型文件保存在一个可以随时访问的集中式存储中的过程。在存储模型时,通常会选择某种存储方式,以便在需要时可以获取模型并使用。模型注册表是一类可以解决此问题的工具。

现在让我们看看如何保存我们的模型。

如何在Python中保存训练好的模型?

在本节中,您将了解保存机器学习(ML)和深度学习(DL)模型的不同方法。首先,让我们使用最著名的鸢尾花数据集创建一个简单的分类模型。

注意:本文的重点不是向您展示如何创建最佳的ML模型,而是解释如何有效地保存训练好的模型。

首先,您需要加载所需的依赖项和鸢尾花数据集,如下所示:

# 加载依赖项
import pandas as pd 

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler 
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import classification_report, confusion_matrix

# 加载数据集
url = "iris.data"

# 使用的列名
names = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width', 'Class']

# 从 URL 读取数据集
dataset = pd.read_csv(url, names=names) 

# 检查鸢尾花分类数据的前几行
dataset.head()

接下来,您需要将数据分割为训练集和测试集,并应用所需的预处理阶段,例如特征标准化。

# 将独立特征和因变量分开
X = dataset.iloc[:, :-1].values
y = dataset.iloc[:, 4].values 

# 将数据集随机分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, 
                                                    y, test_size=0.20) 
# 特征标准化
scaler = StandardScaler()
scaler.fit(X_train)

X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test) 

最后,你需要在训练数据上训练一个分类模型(可以随意选择),并在测试数据上评估其性能。

# 训练一个KNN分类器
model = KNeighborsClassifier(n_neighbors=5)
model.fit(X_train, y_train) 

# 对测试数据进行预测
y_predict = model.predict(X_test)

# 检查结果
print(confusion_matrix(y_test, y_predict))
print(classification_report(y_test, y_predict)) 

鸢尾花分类结果 | 来源:作者

现在你有一个想要保存以供将来使用的机器学习模型。保存机器学习模型的第一种方法是使用pickle文件。

使用pickle保存训练好的模型

pickle模块可用于序列化和反序列化Python对象。序列化是将Python对象层次结构转换为字节流的过程,而反序列化是将字节流(来自二进制文件或其他看起来由字节组成的对象)转换回对象层次结构的过程。

要将用作pickle文件的ML模型保存下来,你需要使用默认的Python安装中已经包含的pickle模块。

要保存iris分类器模型,你只需要选择一个文件名,并将模型存储到pickle文件中,如下所示:

import pickle

# 将iris分类器模型保存为pickle文件
model_pkl_file = "iris_classifier_model.pkl"  

with open(model_pkl_file, 'wb') as file:  
    pickle.dump(model, file)

如你所见,文件以“wb(写入二进制)”模式打开,以将模型保存为字节。同时,“dump()”方法将模型存储在给定的pickle文件中。

你也可以使用pickle模块的“load()”方法加载此模型。现在,你需要以“rb(读取二进制)”模式打开文件来加载保存的模型。

# 从pickle文件中加载模型
with open(model_pkl_file, 'rb') as file:  
    model = pickle.load(file)

# 评估模型
y_predict = model.predict(X_test)

# 检查结果
print(classification_report(y_test, y_predict)) 

加载后,你可以使用此模型进行预测。

鸢尾花分类结果 | 来源:作者

使用Python pickle的优点

  • 1
    pickle是Python中的标准模块,使用起来非常方便,可以用于保存和恢复ML模型。
  • 2
    pickle文件可以处理大多数Python对象,包括自定义对象,使其成为保存模型的多功能方式。
  • 3
    对于小型模型,pickle方法非常快速高效。
  • 4
    当一个ML模型被反序列化时,它会恢复到之前的状态,包括任何变量或配置。这使得Python pickle文件成为保存ML模型的最佳选择之一。

使用Python pickle的缺点

  • 1
    如果解序列化不可信数据,pickle可能会造成安全威胁。解析对象可能会执行恶意代码,因此只能从可靠来源解析信息至关重要。
  • 2
    由于无法在不同的Python版本或操作系统之间传输pickle对象,因此其使用可能受到限制。
  • 3
    对于内存占用大的模型,使用pickle可能会创建巨大的文件,这可能会导致问题。
  • 4
    pickle可能会使跟踪模型随时间的变化变得困难,特别是如果模型经常更新,而为不同版本的模型创建多个pickle文件是不可行的。

腌菜最适合小型模型,并且还存在一些安全问题,这些原因足以寻找保存ML模型的其他替代方法。接下来,让我们讨论Joblib 来保存和加载ML模型。

注意:在接下来的章节中,您将看到相同的鸢尾花分类器模型使用不同的技术进行保存。

使用Joblib保存训练好的模型

Joblib是一组工具(通常是Scipy生态系统的一部分),提供了轻量级的Python管道。它主要关注磁盘缓存、记忆化和并行计算,并用于保存和加载Python对象。Joblib专门针对NumPy数组进行了优化,使其对具有许多参数的ML模型快速可靠。

要使用Joblib保存大型模型,您需要使用预安装在Python中的Python Joblib模块。

import joblib 

# 使用joblib保存模型
filename = 'joblib_model.sav'
joblib.dump(model, filename)

要保存模型,您需要为文件名定义以‘.sav’或‘.pkl’扩展名的文件名,并调用Joblib的dump()方法。

与pickle类似,Joblib提供了load()方法来加载保存的ML模型。

# 使用joblib加载模型
loaded_model = joblib.load(filename)

# 评估模型
y_predict = model.predict(X_test)

# 检查结果
print(classification_report(y_test, y_predict)) 

使用Joblib加载模型后,您可以自由地将其用于数据进行预测。

鸢尾花分类结果 | 来源:作者

使用Joblib保存ML模型的优点

  • 1
    Joblib的快速和有效性是其关键组成部分,特别适用于具有大量内存需求的模型。
  • 2
    Joblib可以通过并行计算来并行化序列化和反序列化过程,从而提高多核机器上的性能。
  • 3
    对于需要大量内存的模型,Joblib采用内存映射文件格式来减少内存使用。
  • 4
    Joblib提供了各种安全功能,例如白名单安全函数,可以在反序列化过程中使用,以帮助防止不受信任的数据。

使用Joblib保存ML模型的缺点

  • 1
    Joblib针对NumPy数组进行了优化,可能在其他对象类型上效果不佳。
  • 2
    与Pickle相比,Joblib的灵活性较低,可用于配置序列化过程的选项较少。
  • 3
    与Pickle相比,Joblib知名度较低,这可能使得更难找到有关它的帮助和文档。

尽管Joblib解决了pickle面临的主要问题,但它本身也存在一些问题。接下来,您将看到如何使用JSON手动保存和恢复模型。

使用JSON保存训练好的模型

当您想完全控制ML模型的保存和恢复过程时,可以使用JSON。与其他两种方法不同,此方法不会直接将ML模型转储到文件中;相反,您需要显式定义模型的不同参数来保存它们。

要使用此方法,您需要使用Python的json模块,该模块也随默认Python安装一起提供。使用JSON方法需要额外的工作来编写ML模型包含的所有参数。要使用JSON保存模型,让我们创建一个像这样的函数:

import json 

# 创建保存为JSON的函数
def save_json(model, filepath, X_train, y_train): 
    saved_model = {}
    saved_model["algorithm"] = model.get_params()['algorithm'],
    saved_model["max_iter"] = model.get_params()['leaf_size'],
    saved_model["solver"] = model.get_params()['metric'],
    saved_model["metric_params"] = model.get_params()['metric_params'],
    saved_model["n_jobs"] = model.get_params()['n_jobs'],
    saved_model["n_neighbors"] = model.get_params()['n_neighbors'],
    saved_model["p"] = model.get_params()['p'],
    saved_model["weights"] = model.get_params()['weights'],
    saved_model["X_train"] = X_train.tolist() if X_train is not None else "None",
    saved_model["y_train"] = y_train.tolist() if y_train is not None else "None"
    
    json_txt = json.dumps(saved_model, indent=4)
    with open(filepath, "w") as file: 
        file.write(json_txt)

# 将鸢尾花分类模型保存为json文件
file_path = 'json_model.json'
save_json(model, file_path, X_train, y_train)

您可以看到,您需要定义每个模型参数以及将其存储在JSON中的数据。不同的模型有不同的方法来检查参数的详细信息。例如,KNeighboursClassifier的get_params()方法会返回模型中所有超参数的列表。您需要将所有这些超参数和数据值保存在一个字典中,然后将其转储到一个以‘.json’扩展名结尾的文件中。

要读取此JSON文件,您只需要打开它并按以下方式访问参数:

# 创建json加载函数
def load_json(filepath):
    with open(filepath, "r") as file:
        saved_model = json.load(file)

    return saved_model

# 加载模型配置
saved_model = load_json('json_model.json')
saved_model

在上面的代码中,创建了一个名为load_json()的函数,它以读模式打开JSON文件,并将所有参数和数据作为字典返回。

不幸的是,您不能直接使用JSON保存的模型,您需要自己读取这些参数和数据来重新训练模型。

使用JSON保存ML模型的优点

  • 1. 需要在不同系统之间交换的模型可以使用JSON进行,JSON是一种可由各种编程语言和平台读取的便携式格式。
  • 2. JSON是一种基于文本的格式,易于阅读和理解,适用于需要人工检查或编辑的模型。
  • 3. 与Pickle或Joblib相比,JSON是一种创建较小文件的轻量级格式,对于必须通过互联网传输的模型非常重要。
  • 4. 与pickle不同,在反序列化过程中执行代码的JSON是一种安全格式,可以最小化安全威胁。

使用JSON保存ML模型的缺点

  • 1. 因为JSON只支持少量数据类型,所以它可能与使用特殊数据类型的复杂机器学习模型不兼容。
  • 2. 特别是对于大型模型,JSON序列化和反序列化可能比其他格式更慢。
  • 3. 与其他格式相比,JSON提供的灵活性较小,可能需要更多的工作来定制序列化过程。
  • 4. JSON是一种丢失格式,可能无法保留原始模型中的所有信息,这对于需要精确复制的模型可能是一个问题。

为了确保安全性和JSON/pickle的优势,您可以将模型保存到专用数据库中。接下来,您将看到如何在数据库中保存ML模型。

使用TensorFlow Keras保存深度学习模型

TensorFlow是一个用于训练基于DL的模型的流行框架,Keras是TensorFlow的一个封装器。使用具有多个层和一组标记数据的神经网络设计来训练深度学习模型。这些模型有两个主要组件:权重和网络架构,您需要将它们保存起来以便将来使用。通常有两种方法可以保存深度学习模型:

  1. 将模型架构保存在JSON或YAML文件中,将权重保存在HDF5文件中。
  2. 将模型和架构都保存在HDF5、protobuf或tflite文件中。

您可以参考任一种方法来执行此操作,但广泛使用的方法是将模型权重和架构一起保存在HDF5文件中。

要在TensorFlow Keras中保存深度学习模型,可以使用Keras Model对象的save()方法。此方法将整个模型,包括模型架构、优化器和权重,保存在可以后续加载以进行预测的格式中。

下面是一个示例代码片段,演示如何保存TensorFlow Keras基于DL的模型:

# 导入TensorFlow依赖项
from tensorflow.keras.models import Sequential, model_from_json
from tensorflow.keras.layers import Dense

# 定义模型架构
model = Sequential()
model.add(Dense(12, input_dim=4, activation='relu'))
model.add(Dense(8, activation='relu'))
model.add(Dense(1, activation='sigmoid'))

# 编译模型
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

# 训练模型
model.fit(X_train, y_train, epochs=150, batch_size=10, verbose=0)

# 保存模型和其架构
model.save('model.h5')

这就是它,您只需要定义模型的架构,使用适当的设置训练模型,最后使用save()方法保存它。

使用Keras加载保存的模型就像在Python中读取文件一样简单。您只需要调用load_model()方法,并提供模型文件路径,您的模型将被加载。

# 定义依赖
from tensorflow.keras.models import load_model

# 加载模型
model = load_model('model.h5')

# 检查模型信息
model.summary()

您现在可以加载模型并使用它了。

加载的Tensorflow模型 | 来源: 作者

使用TensorFlow Keras保存模型的优点

  • 1. 使用save()和load_model()函数在TensorFlow Keras中保存和加载模型非常简单。这使得保存和共享模型变得容易,并且可以将其部署到生产环境中。
  • 2. 使用Keras保存模型时,整个模型架构、优化器和权重将保存在一个文件中。不需要单独加载架构和权重,可以简单地加载模型并生成预测。
  • 3. TensorFlow Keras支持多种文件格式来保存模型,包括HDF5格式(.h5)、TensorFlow SavedModel格式(.pb)和TensorFlow Lite格式(.tflite)。这样可以根据需要选择最适合的格式。

使用TensorFlow Keras保存模型的缺点

  • 1. 当保存Keras模型时,生成的文件可能会非常大,特别是如果有大量的层或参数。这可能会在带宽或存储空间有限的情况下使共享或部署模型变得困难。
  • 2. 使用一个版本的TensorFlow Keras保存的模型可能无法与另一个版本一起工作。如果尝试加载使用不同版本的Keras或TensorFlow保存的模型,可能会导致问题。
  • 3. 虽然保存Keras模型很简单,但您只能使用Keras提供的用于存储模型的功能。如果您需要在保存或加载模型的方式上需要更多灵活性,可能需要使用其他框架或策略。

还有一个广泛使用的名为PyTorch的框架可用于训练基于深度学习的模型。让我们看看如何使用Python保存基于PyTorch的深度学习模型。

使用PyTorch保存深度学习模型

PyTorch是由Facebook开发的一个高度使用的深度学习框架之一。它提供了动态计算图,使您能够实时修改模型,非常适合研究和实验。它使用‘.pt’和‘.pth’文件格式来保存模型架构和权重。

要保存PyTorch中的深度学习模型,可以使用PyTorch的torch.nn.Module对象的save()方法。该方法将整个模型,包括模型架构和权重,保存为可以在以后加载并进行预测的格式。

下面是一个示例代码片段,展示如何保存PyTorch模型:

# 导入依赖
import torch
import torch.nn as nn
import numpy as np

# 将数据numpy数组转换为张量
X_train = torch.FloatTensor(X_train)
X_test = torch.FloatTensor(X_test)
y_train = torch.LongTensor(y_train)
y_test = torch.LongTensor(y_test)

# 定义模型架构
class NeuralNetworkClassificationModel(nn.Module):
    def __init__(self,input_dim,output_dim):
        super(NeuralNetworkClassificationModel,self).__init__()
        self.input_layer    = nn.Linear(input_dim,128)
        self.hidden_layer1  = nn.Linear(128,64)
        self.output_layer   = nn.Linear(64,output_dim)
        self.relu = nn.ReLU()
    
    
    def forward(self,x):
        out =  self.relu(self.input_layer(x))
        out =  self.relu(self.hidden_layer1(out))
        out =  self.output_layer(out)
        return out

# 定义输入和输出维度
input_dim  = 4 
output_dim = 3
model = NeuralNetworkClassificationModel(input_dim,output_dim)

# 创建优化器和损失函数对象
learning_rate = 0.01
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(),lr=learning_rate)

# 定义训练步骤
def train_network(model,optimizer,criterion,X_train,y_train,X_test,y_test,num_epochs,train_losses,test_losses):
    for epoch in range(num_epochs):
        # 清除上一步的梯度
        optimizer.zero_grad()
        
        # 前向传播
        output_train = model(X_train)

        # 计算损失
        loss_train = criterion(output_train, y_train)

        # 反向传播:计算梯度
        loss_train.backward()

        # 更新权重
        optimizer.step()
        
        output_test = model(X_test)
        loss_test = criterion(output_test,y_test)

        train_losses[epoch] = loss_train.item()
        test_losses[epoch] = loss_test.item()

        if (epoch + 1) % 50 == 0:
            print(f"Epoch { epoch+1 }/{ num_epochs }, Train Loss: { loss_train.item():.4f }, Test Loss: {loss_test.item():.4f}")

# 训练模型
num_epochs = 1000
train_losses = np.zeros(num_epochs)
test_losses  = np.zeros(num_epochs)
train_network(model,optimizer,criterion,X_train,y_train,X_test,y_test,num_epochs,train_losses,test_losses)

# 保存模型
torch.save(model, 'model_pytorch.pt')

与Tensorflow不同,Pytorch允许您对模型训练有更多的控制,如上面的代码所示。在训练完模型后,您可以使用save() 方法保存权重和模型结构。

使用Pytorch加载保存的模型需要使用load() 方法。

# 加载模型
model = torch.load('model_pytorch.pt')
# 检查模型摘要
model.eval()

Pytorch加载的模型 | 来源:作者

使用Pytorch保存模型的优点

  • 1
    PyTorch使用的计算图是动态的,这意味着它是在程序运行时构建的。这样可以在训练或推理过程中更灵活地修改模型。
  • 2
    对于具有可变长度输入或输出的动态模型,例如自然语言处理(NLP)和计算机视觉中常见的模型,PyTorch提供了改进的支持。
  • 3
    由于PyTorch是用Python编写的,并且与NumPy和pandas等其他Python库配合良好,因此在训练之前和之后对数据进行操作非常简单。

使用Pytorch保存模型的缺点

  • 1
    尽管PyTorch提供了易于使用的API,但对于深度学习或Python编程的新手来说,可能会有一个陡峭的学习曲线。
  • 2
    由于PyTorch本质上是一个用于研究的框架,可能没有像TensorFlow或Keras等其他深度学习框架那样用于生产部署的工具。

除此之外,您还可以使用模型注册平台来保存基于深度学习的模型,尤其是那些体积较大的模型。这样可以轻松部署和维护模型,而无需开发人员额外的努力。

您可以在这里找到本文中使用的数据集和代码。

如何打包机器学习模型?

机器学习模型通常针对训练数据集和特定的环境进行了优化。但是,当将模型部署在不同环境中(例如生产环境)时,可能会面临各种挑战。

这些挑战包括但不限于硬件、软件和数据输入的差异。将模型打包可以更容易地解决这些问题,因为它允许将模型导出或序列化为标准格式,可以在各种环境中加载和使用。

目前有各种打包选项可供选择。通过将模型打包为PMML(Predictive Model Markup Language)、ONNX、TensorFlow SavedModel格式等标准格式,可以更轻松地共享和协作使用模型,而不必担心不同团队使用的不同库和工具。现在,让我们来看一些使用Python中不同框架打包机器学习模型的示例。

注意:对于本节,您将看到相同的鸢尾花分类示例。

使用PMML打包模型

使用Python中的PMML库,您可以将机器学习模型导出为PMML格式,然后将其部署为Web服务、批处理系统或数据集成平台。这样可以更轻松地共享和协作使用机器学习模型,以及在各种生产环境中部署它们。

要使用PMML打包机器学习模型,您可以使用不同的模块,如sklearn2pmml、jpmml-sklearn、jpmml-tensorflow等。

注意:要使用PMML,您必须在系统上安装Java Runtime。

下面是一个示例代码片段,它允许您使用PMML打包训练过的鸢尾花分类器模型。

from sklearn2pmml import PMMLPipeline, sklearn2pmml
# 使用PMML打包鸢尾花分类器模型
sklearn2pmml(PMMLPipeline([("estimator",
                        	model)]),
         	"iris_model.pmml",
         	with_repr=True)

在上面的代码中,您只需通过传递您的模型对象来创建一个PMML pipeline对象。然后,您需要使用sklearn2pmml() 方法保存PMML对象。就是这样,现在您可以在不同的环境中使用这个“iris_model.pmml” 文件。

使用PMML的优点

  • 1
    由于PMML是一个与平台无关的格式,所以PMML模型可以与许多数据处理平台集成,并在各种生产环境中使用。
  • 2
    PMML可以减少供应商锁定,因为它允许用户从不同的机器学习平台导出和导入模型。
  • 3
    PMML模型可以很容易地部署到生产环境中,因为它们可以与各种数据处理平台和系统集成。

使用PMML的缺点

  • 1
    由于有限的支持,一些机器学习模型和算法可能无法以PMML格式导出。
  • 2
    PMML是一种基于XML的格式,可能冗长且不灵活,这可能使得在导出为PMML格式后难以修改或更新模型。
  • 3
    创建PMML模型可能会很困难,特别是对于具有多个特征和交互的复杂模型。

使用ONNX打包模型

ONNX(Open Neural Network Exchange)是由Microsoft和Facebook开发的一种表示机器学习模型的开放格式。它可以在不同的深度学习框架和工具之间实现互操作性。

ONNX模型可以高效地部署在各种平台上,包括移动设备、边缘设备和云端。它支持多种运行时,包括Caffe2、TensorFlow、PyTorch和MXNet,这使得您可以轻松地在不同设备和平台上部署您的模型。

要使用ONNX保存模型,您需要在系统中下载onnx和onnxruntime包。

以下是如何将现有的ML模型转换为ONNX格式的示例。

# 加载依赖项
import onnxmltools
import onnxruntime

# 将KNeighborsClassifier模型转换为ONNX格式
onnx_model = onnxmltools.convert_sklearn(model)

# 将ONNX模型保存到文件中
onnx_file = "iris_knn.onnx"
onnxmltools.utils.save_model(onnx_model, onnx_file)

您只需要导入所需的模块,并使用convert_sklearn()方法将sklearn模型转换为ONNX模型。转换完成后,使用save_model()方法,您可以将ONNX模型存储在带有“.onnx”扩展名的文件中。尽管这里展示了一个ML模型的示例,但ONNX主要用于DL模型。

您还可以使用ONNX Runtime模块加载此模型。

# 将ONNX模型加载到ONNX Runtime中
sess = onnxruntime.InferenceSession(onnx_file)

# 在一些测试数据上评估模型
input_data = {"X": X_test[:10].astype('float32')}
output = sess.run(None, input_data)

您需要使用InferenceSession()方法创建会话来从文件加载ONNX模型,然后使用sess.run()方法从模型中进行预测。

使用ONNX的优点

  • 1
    只需很少的努力,ONNX模型就可以轻松地部署到许多平台上,包括移动设备和云端。由于ONNX支持各种运行时,因此在各种硬件和软件平台上部署模型非常简单。
  • 2
    ONNX模型经过优化,可以运行速度更快,资源消耗更少,优于其他格式的模型。

使用ONNX的缺点

  • 1
    ONNX主要设计用于深度学习模型,可能不适用于其他类型的机器学习模型。
  • 2
    ONNX模型可能与不同深度学习框架的所有版本不兼容,这可能需要额外的努力来确保兼容性。

使用Tensorflow SavedModel打包模型

Tensorflow的SavedModel格式允许您轻松保存和加载深度学习模型,并确保与其他Tensorflow工具和平台的兼容性。此外,它提供了一种简化和高效的方式来在生产环境中部署我们的模型。

SavedModel支持广泛的部署场景,包括使用Tensorflow Serving提供模型服务,使用Tensorflow Lite将模型部署到移动设备,以及将模型导出到其他ML库(如ONNX)。

它提供了一种简单而流畅的方式来保存和加载Tensorflow模型。API易于使用和文档完善,格式设计高效且可扩展。

注意:您可以使用上面部分训练的相同TensorFlow模型。

要将模型保存为SavedModel格式,您可以使用以下代码:

import tensorflow as tf

# 使用SavedModel格式保存模型
tf.saved_model.save(model, "my_model")

您还可以使用load()方法加载模型。

# 加载模型
loaded_model = tf.saved_model.load("my_model")

使用Tensorflow SavedModel的优点

  • 1
    SavedModel是独立于平台且兼容版本的,使得在不同平台和TensorFlow版本上共享和部署模型变得容易。
  • 2
    SavedModel支持多种部署场景,包括将模型导出到其他ML库(如ONNX),使用TensorFlow Serving提供模型服务以及使用TensorFlow Lite将模型分发到移动设备。
  • 3
    SavedModel针对训练和推断进行了优化,支持分布式训练,并能够利用GPU和TPU加速训练。

使用Tensorflow SavedModel的缺点

  • 1
    SavedModel文件可能很大,特别是对于复杂模型,这可能使得存储和传输变得困难。
  • 2
    鉴于SavedModel专属于TensorFlow,它与其他ML库和工具的兼容性可能受到限制。
  • 3
    保存的模型是一个二进制文件,可能很难检查,这使得更难理解模型的架构和操作细节。

现在您已经看到了多种打包ML和DL模型的方式,您还必须知道有各种可用的工具来提供基础设施来打包、部署和提供这些模型。其中两个流行的工具是BentoML和MLFlow。

BentoML

BentoML是一个灵活的框架,用于构建和部署生产就绪的机器学习服务。它允许数据科学家将经过训练的模型、其依赖项以及用于提供模型所需的基础设施代码打包到一个可重用的包(称为“Bento”)中。

BentoML支持各种机器学习框架和部署平台,并提供统一的API来管理模型的生命周期。一旦将模型打包为Bento,就可以将其部署到各种服务平台,如AWS Lambda、Kubernetes或Docker。BentoML还提供了一个API服务器,可用于通过REST API提供模型服务。您可以在这里了解更多信息。

MLFlow

MLFlow是一个用于管理端到端机器学习生命周期的开源平台。它提供了一套全面的工具,用于跟踪实验、打包代码和依赖项以及部署模型。

MLFlow允许数据科学家将其模型打包为标准格式,可以部署到各种平台,如AWS SageMaker、Azure ML和Google Cloud AI Platform。该平台还提供了一个模型注册表,用于管理模型版本并跟踪其性能。此外,MLFlow还提供了一个用于提供模型的REST API,可以轻松集成到Web应用程序或其他服务中。

如何存储ML模型?

现在我们已经了解了如何保存模型,让我们看看如何存储它们以便快速简便地检索。

将ML模型存储在数据库中

您还可以将ML模型保存在关系型数据库(如PostgreSQL、MySQL、Oracle SQL等)或NoSQL数据库(如MongoDB、Cassandra等)中。选择数据库完全取决于诸如存储和操作结构化数据的类型和数量、性能和可扩展性要求以及应用程序的具体需求等因素。

在处理提供对存储和操作结构化数据的支持的ML模型时,PostgreSQL是一个常用选择。将ML模型存储在PostgreSQL中可以轻松跟踪模型的不同版本并在集中位置进行管理。

此外,它还允许轻松共享模型,适用于团队或组织之间的共享。然而,重要的是要注意,将大型模型存储在数据库中可能会增加数据库大小和查询时间,因此在将模型存储在PostgreSQL中时,需要考虑数据库的存储容量和性能。

要将ML模型保存在像PostgreSQL这样的数据库中,首先需要将训练好的模型转换为序列化格式,例如字节流(pickle对象)或JSON。

import pickle

# 序列化模型
model_bytes = pickle.dumps(model)

然后打开与数据库的连接并创建用于存储序列化模型的表或集合。为此,您需要使用Python的psycopg2 库,该库允许您连接到PostgreSQL数据库。您可以通过Python包安装程序来下载此库。

$ pip install psycopg2-binary

然后,您需要建立与数据库的连接来存储ML模型,如下所示:

import psycopg2

# 建立与数据库的连接
conn = psycopg2.connect(
  database="数据库名", user="用户名", password='您的密码', host='127.0.0.1', port= '5432'
)

要在数据库上执行任何操作,您需要创建一个游标对象,该对象将帮助您在Python程序中执行查询。

# 创建游标
cur = conn.cursor()

借助这个游标,您现在可以执行CREATE TABLE查询以创建新表。

cur.execute("CREATE TABLE models (id INT PRIMARY KEY NOT NULL, name CHAR(50), model BYTEA)")

注意:确保模型对象类型为BYTEA。

最后,您可以使用INSERT INTO命令将模型和其他元数据信息存储到数据库中。

# 将序列化的模型插入数据库
cur.execute("INSERT INTO models (id, name, model) VALUES (%s, %s, %s)", (1, '鸢尾花分类器', model_bytes))
conn.commit()

# 关闭数据库连接
cur.close()
conn.close()

完成所有操作后,关闭游标和与数据库的连接。

最后,要从数据库中读取模型,可以使用SELECT命令,并根据名称或ID筛选模型。

import psycopg2
import pickle

# 连接数据库
conn = psycopg2.connect(
  database="数据库名", user="用户名", password='您的密码', host='127.0.0.1', port= '5432'
)

# 从数据库中检索序列化模型
cur = conn.cursor()
cur.execute("SELECT model FROM models WHERE name = %s", ('鸢尾花分类器',))
model_bytes = cur.fetchone()[0]

# 反序列化模型
model = pickle.loads(model_bytes)

# 关闭数据库连接
cur.close()
conn.close()

从数据库加载模型后,可以使用它进行预测,如下所示:

# 测试加载的模型
y_predict = model.predict(X_test)

# 检查结果
print(classification_report(y_test, y_predict)) 

这就是全部内容,您已经将模型存储并从数据库加载。

将ML模型存储在数据库中的优点:

  • 1. 将ML模型存储在数据库中提供了一个集中的存储位置,可以轻松地被多个应用程序和用户访问。
  • 2. 由于大多数组织已经有了数据库,因此将ML模型集成到现有基础设施中变得更容易。
  • 3. 数据库针对数据检索进行了优化,这意味着检索ML模型更快、更高效。
  • 4. 数据库旨在提供强大的安全功能,如身份验证、授权和加密。这确保存储的ML模型是安全的。

将ML模型存储在数据库中的缺点:

  • 1. 数据库设计用于存储结构化数据,对于存储ML模型等非结构化数据来说并不是最佳选择。因此,在模型大小、文件格式和其他方面,数据库可能存在限制。
  • 2. 将ML模型存储在数据库中可能会更加复杂,需要数据库管理和机器学习方面的专业知识。
  • 3. 如果ML模型很大,在数据库中存储它们可能会导致可扩展性问题。此外,检索大型模型可能会影响数据库的性能。

虽然pickle、joblib和JSON是保存机器学习模型的常见方法,但在版本控制、共享和管理机器学习模型方面存在局限性。在这种情况下,机器学习模型注册表可以解决所有这些问题。

接下来,您将看到如何将ML模型保存在模型注册表中,以帮助您实现可重现性和可重用性。

将ML模型存储在模型注册表中

  • 模型注册表是一个中央存储库,可以存储、版本控制和管理机器学习模型。
  • 它通常包括模型版本控制、元数据控制、比较模型运行等功能。
  • 在任何ML或DL项目中工作时,您可以随时从模型注册表中保存和检索模型及其元数据。
  • 最重要的是,模型注册表可以实现团队成员之间的高度协作。

查看本文以了解有关模型注册表的更多信息。

模型注册表有各种选择,例如neptune.ai、Mlflow、Kubeflow等。尽管所有这些平台都有一些独特的功能,但选择一个可以提供广泛功能集的注册表是明智的。

在此示例中,我将使用Neptune。它具有用于组织、存储和管理机器学习模型的模型注册表功能。对于需要管理其训练模型的数据科学家和ML工程师来说,它是一个很好的选择,因为它提供了协作功能、用户友好的界面和模型版本控制能力。

您可以在此处设置免费帐户,或在此处了解更多有关该工具的信息。

向Neptune注册表注册模型

一旦您创建了免费帐户,您可以单击“新项目”按钮开始一个新项目。

在Neptune中创建新项目 | 来源:作者

项目创建完成后,您将看到一个页面,其中包含用于保存模型的不同配置。使用Neptune,您可以使用Scikit-Learn、Keras、Tensorflow、Pytorch等不同的框架。

要将模型存储在Neptune模型注册表中,您需要安装该库:

$ pip install neptune

注意:确保您已使用pickle或joblib模块将训练好的模型转储到文件中,以便将其存储在模型注册表中。

安装依赖项后,您需要将其导入到程序中,并通过提供名称、唯一键(大写)和Neptune凭据来初始化Neptune模型。您可以在Neptune项目的模型元数据选项卡中找到所有这些信息。

import neptune

# 初始化模型
model = neptune.init_model(
name="预测模型",
key="IRMOD", # 对于您的项目应该是不同的
project="用户名/项目名称",
api_token="您的API密钥", # 您的凭据
)

在上面的代码中,导入了Neptune依赖项,并使用Neptune凭据初始化了一个模型(您要将其存储并跟踪使用Neptune的模型注册表)。然后,您需要将分类模型元数据分配给Neptune模型对象。

# 将分类模型元数据分配给模型对象
model_info = {"size_limit": 7.09, "size_units": "KB"}
model["model"] = model_info

最后,您可以使用upload()方法将模型上传到Neptune模型注册表中:

# 将模型上传到注册表
model["model/signature"].upload("iris_classifier_model.pkl")

此外,您还可以使用neptune提供的track_files()方法跟踪数据集版本。

# 跟踪数据集版本
model["data/train_and_test"].track_files("iris.data")

# 结束会话
model.stop()

就是这样,您的模型和数据集现在已保存到注册表中。此外,不要忘记使用stop()方法关闭会话。

在Neptune中检查存储的模型 | 来源:作者

给模型版本化

当你在一个真实世界的机器学习项目中工作时,你会尝试很多模型和参数组合。如果你不记录这些数据,你可能不会知道你尝试过的所有事情,可能会有重新工作的可能性。

这就是 Neptune 模型注册表帮助你的地方,你可以用几行代码注册不同版本的模型。首先,你需要初始化一个ModelVersion对象,如下所示:

# 初始化 ModelVersion
import neptune
model_version = neptune.init_model_version(
model="IR-IRMOD", # 你的项目需要不同的模型名称
project="username/projectname",
api_token="your-api-key", # 你的凭证
)

然后,你可以选择性地将模型和其他元数据详细信息保存在你要在 Neptune 注册表中注册的每个模型版本中。

# 模型参数
parameters = {
"algorithm": clf_model.get_params()['algorithm'],
"max_iter": clf_model.get_params()['leaf_size'],
"solver": clf_model.get_params()['metric'],
"metric_params": clf_model.get_params()['metric_params'],
"n_jobs": clf_model.get_params()['n_jobs'],
"n_neighbors": clf_model.get_params()['n_neighbors'],
"p": clf_model.get_params()['p'],
"weights": clf_model.get_params()['weights'],
}

# 记录模型参数和其他元数据
model_version["model/binary"].upload("iris_classifier_model.pkl")
model_version["model/parameters"] = parameters
model_version["data/dataset"].track_files("iris.data")
model_version["validation/acc"] = 0.93

# 停止会话
model_version.stop()

完成后,你可以使用stop()方法停止会话。

在 Neptune 应用程序中查看模型版本 | 来源:neptune.ai

从注册表查询模型和元数据

最后,当需要时,你需要访问这个保存的模型和元数据。你可以加载你保存到注册表中的任何特定模型版本。为此,你需要通过提供模型版本 id 来初始化一个ModelVersion对象。

import neptune
import pickle

# 指定模型版本 id
version_id = 'IR-IRMOD-1' # 你的项目需要不同的模型版本 id

# 初始化运行
model_version = neptune.init_model_version(
with_id=version_id,
project="username/project-name",
api_token="your-api-key", # 你的凭证
)

完成后,你可以访问你注册的不同模型对象,比如模型、元数据、数据集等详细信息。首先,让我们从注册表中下载模型并将其保存到本地,以便在测试数据上测试其性能。

# 从注册表保存模型到本地
if model_version.exists("model/binary"):
model_version["model/binary"].download(f"model/{version_id}_model.pkl")

# 从保存的 pickle 文件中加载模型
with open(f"model/{version_id}_model.pkl", 'rb') as file: 
clf_model_2 = pickle.load(file)

# 评估模型
y_predict = clf_model_2.predict(X_test)

你还可以查看你在 Neptune 中保存的模型元数据信息。

检查 Neptune 中保存的模型元数据信息 | 来源:作者

要将这些元数据下载到本地,你可以使用以下代码:

# 检查元数据
model_version["model/parameters"].fetch()

就是这样,现在你知道如何将特定模型存储和加载到 Neptune 模型注册表中。

你可以在这里阅读有关 Neptune 模型注册表的更多信息。

使用模型注册表存储模型的优点

  • 1. 集中管理、存储和版本控制机器学习模型的位置。
  • 2. 模型注册表通常包含有关模型的元数据,例如版本、性能指标等,使得跟踪变化和理解模型的历史变得更简单。
  • 3. 模型注册表允许团队成员合作并轻松共享他们的工作。
  • 4. 一些模型注册表提供自动化部署选项,可以简化将模型部署到生产环境的过程。
  • 5. 模型注册表通常提供访问控制、加密和身份验证等安全功能,确保模型安全且只能被授权用户访问。

使用模型注册表存储模型的缺点

  • 1. 某些模型注册表需要付费订阅,增加了机器学习项目的成本。
  • 2. 模型注册表通常有一定的学习曲线,需要时间来熟悉其功能和特性。
  • 3. 使用模型注册表可能需要与其他工具和系统进行集成,可能会引入额外的依赖。

现在您已经了解了保存机器学习模型的不同方法(模型注册表是最优选项),现在是时候了解一些保存深度学习(DL)模型的方法了。

最佳实践

在本节中,您将了解保存机器学习和深度学习模型的一些最佳实践。

  • 确保库版本一致:在保存和加载模型时使用不同的库版本可能会导致兼容性问题,因为库的更新可能会引入一些结构性变化。您必须确保加载机器学习模型时使用的库版本与保存模型时使用的库版本相同。
  • 确保Python版本一致:在您的机器学习流水线开发的所有阶段都使用相同的Python版本是一个好习惯。有时Python版本的更改可能会导致执行问题,例如,Tensorflow V1仅支持Python 3.7,如果您尝试在稍后的版本中使用它,您将遇到错误。
  • 同时保存模型架构和权重:对于基于DL的模型,如果仅保存模型权重而不保存模型架构,则无法重构模型。保存模型架构和经过训练的权重可以确保完全重构并在以后使用该模型。
  • 记录模型:应对模型的目标、输入、输出和预期性能进行记录。这可以帮助其他人了解模型的能力和约束。
  • 使用模型注册表:使用像neptune.ai这样的模型注册表来跟踪模型、版本和元数据,并与团队成员进行协作。
  • 保持保存的模型安全:通过加密或将其存储在安全位置来保护保存的模型,特别是如果它包含敏感数据。

结论

总之,保存机器学习模型是开发过程中的重要步骤,因为它允许您重复使用和与他人共享模型。有几种保存机器学习模型的方法,每种方法都有其优点和缺点。一些流行的方法包括使用pickle、Joblib、JSON、TensorFlow save和PyTorch save。

选择适合特定用例的文件格式,并遵循保存和记录模型的最佳实践,例如版本控制、确保语言和库版本以及测试保存的模型,这些都是很重要的。通过遵循本文讨论的实践,您可以确保正确保存机器学习模型,便于重复使用和部署,并可以有效地与他人共享。

参考资料

  1. https://machinelearningmastery.com/save-load-machine-learning-models-python-scikit-learn/
  2. https://www.tensorflow.org/tutorials/keras/save_and_load
  3. https://pytorch.org/tutorials/beginner/saving_loading_models.html
  4. https://www.kaggle.com/code/prmohanty/python-how-to-save-and-load-ml-models