趋近智
保存训练好的模型是部署的必要步骤,使用Python的pickle和joblib库进行序列化可以实现这一过程。一个实际的例子将演示模型持久化的主要流程:训练一个非常简单的机器学习模型,将其保存到文件中,然后重新加载它来做预测。
首先,确保您已安装所需的库。我们主要使用scikit-learn来构建模型和生成数据,以及joblib,它通常被推荐用于scikit-learn对象。尽管pickle是内置的,但joblib在处理包含大型NumPy数组的对象时通常能提供更高的效率。
如果尚未安装,您可以使用pip添加它们:
pip install scikit-learn joblib
让我们首先创建并训练一个基础的分类模型。我们将使用scikit-learn生成一些合成数据并训练一个LogisticRegression模型。
# 导入所需库
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
import numpy as np # 稍后将需要numpy用于样本数据
# 生成合成分类数据
X, y = make_classification(n_samples=100, n_features=10, n_informative=5, n_redundant=5, random_state=42)
# 将数据分成训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 初始化并训练逻辑回归模型
model = LogisticRegression(solver='liblinear', random_state=42)
print("正在训练模型...")
model.fit(X_train, y_train)
print("模型训练完成。")
# 可选:评估已训练的模型(保存前)
y_pred_train = model.predict(X_train)
train_accuracy = accuracy_score(y_train, y_pred_train)
print(f"训练数据上的准确率: {train_accuracy:.4f}")
y_pred_test = model.predict(X_test)
test_accuracy = accuracy_score(y_test, y_pred_test)
print(f"测试数据上的准确率: {test_accuracy:.4f}")
此时,model对象仅存在于您的计算机内存中。如果脚本运行结束,训练好的参数将丢失。
pickle是Python用于对象序列化的标准库。它几乎可以保存任何Python对象。
为了保存模型,我们以二进制写入模式('wb')打开一个文件,并使用pickle.dump()。
import pickle
# 定义保存模型的文件名
pickle_filename = 'logistic_regression_model.pkl'
print(f"正在使用pickle将模型保存到 {pickle_filename}...")
# 以二进制写入模式 ('wb') 打开文件
with open(pickle_filename, 'wb') as file:
# 使用pickle.dump序列化模型对象并写入文件
pickle.dump(model, file)
print("模型已成功使用pickle保存。")
您现在应该在您的目录中看到一个名为logistic_regression_model.pkl的文件。该文件包含您已训练的LogisticRegression模型的序列化表示。
现在,假设我们在另一个脚本中或已重新启动了环境。我们可以使用pickle.load()将保存的模型重新加载到内存中。我们需要以二进制读取模式('rb')打开文件。
import pickle
import numpy as np # 确保numpy已导入,如果样本数据需要的话
from sklearn.metrics import accuracy_score # 用于验证预测结果
# 定义模型保存的文件名
pickle_filename = 'logistic_regression_model.pkl'
print(f"正在使用pickle从 {pickle_filename} 加载模型...")
# 以二进制读取模式 ('rb') 打开文件
with open(pickle_filename, 'rb') as file:
# 使用pickle.load从文件反序列化对象
loaded_model_pickle = pickle.load(file)
print("模型已成功使用pickle加载。")
# 让我们验证加载的模型是否有效
# 创建一些样本数据(例如,第一个测试样本)
sample_data = X_test[0].reshape(1, -1) # 重塑以进行单次预测
expected_prediction = y_test[0]
# 使用加载的模型进行预测
prediction = loaded_model_pickle.predict(sample_data)
print(f"使用加载的pickle模型对样本数据进行预测: {prediction[0]}")
print(f"预期预测结果: {expected_prediction}")
# 可选:再次验证测试集上的准确率
y_pred_loaded = loaded_model_pickle.predict(X_test)
loaded_accuracy = accuracy_score(y_test, y_pred_loaded)
print(f"使用加载的pickle模型在测试数据上的准确率: {loaded_accuracy:.4f}")
如您所见,加载的模型与原始模型表现完全一致,产生相同的预测结果和准确率。
joblib对于保存scikit-learn模型特别有用,因为它在处理包含大型NumPy数组的对象时通常效率更高,而这种对象在机器学习中很常见。其语法与pickle非常相似。
import joblib
# 定义保存模型的文件名
joblib_filename = 'logistic_regression_model.joblib'
print(f"正在使用joblib将模型保存到 {joblib_filename}...")
# 使用joblib.dump序列化并保存模型
# joblib高效处理文件的打开/关闭
joblib.dump(model, joblib_filename)
print("模型已成功使用joblib保存。")
这会创建一个名为logistic_regression_model.joblib的文件。
使用joblib.load()加载用joblib保存的模型同样简单。
import joblib
import numpy as np # 确保numpy已导入,如果样本数据需要的话
from sklearn.metrics import accuracy_score # 用于验证预测结果
# 定义模型保存的文件名
joblib_filename = 'logistic_regression_model.joblib'
print(f"正在使用joblib从 {joblib_filename} 加载模型...")
# 使用joblib.load反序列化模型
loaded_model_joblib = joblib.load(joblib_filename)
print("模型已成功使用joblib加载。")
# 验证加载的模型
sample_data = X_test[0].reshape(1, -1)
expected_prediction = y_test[0]
prediction = loaded_model_joblib.predict(sample_data)
print(f"使用加载的joblib模型对样本数据进行预测: {prediction[0]}")
print(f"预期预测结果: {expected_prediction}")
# 可选:验证测试集上的准确率
y_pred_loaded_joblib = loaded_model_joblib.predict(X_test)
loaded_accuracy_joblib = accuracy_score(y_test, y_pred_loaded_joblib)
print(f"使用加载的joblib模型在测试数据上的准确率: {loaded_accuracy_joblib:.4f}")
同样,使用joblib加载的模型与原始模型表现完全一致。
通常,您的模型依赖于在训练期间应用的特定数据预处理步骤,例如缩放或编码。在进行预测之前,这些步骤也必须应用于任何新数据。因此,您需要将拟合好的预处理器对象与模型一起保存。
让我们扩展这个例子,使用scikit-learn中的StandardScaler。
# 导入所需库
from sklearn.preprocessing import StandardScaler
import joblib
# 假设X_train是您的原始训练数据
print("正在拟合StandardScaler...")
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train) # 拟合并转换训练数据
print("Scaler已拟合。")
# 现在,在缩放后的数据上训练模型
model_scaled = LogisticRegression(solver='liblinear', random_state=42)
print("正在缩放后的数据上训练模型...")
model_scaled.fit(X_train_scaled, y_train)
print("模型训练完成。")
# --- 同时保存scaler和模型 ---
scaler_filename = 'standard_scaler.joblib'
model_scaled_filename = 'scaled_logistic_regression_model.joblib'
print(f"正在将scaler保存到 {scaler_filename}...")
joblib.dump(scaler, scaler_filename)
print("Scaler已保存。")
print(f"正在将缩放数据上训练的模型保存到 {model_scaled_filename}...")
joblib.dump(model_scaled, model_scaled_filename)
print("缩放模型已保存。")
# --- 同时加载以进行预测 ---
print("\n正在加载scaler和缩放模型以进行预测...")
loaded_scaler = joblib.load(scaler_filename)
loaded_scaled_model = joblib.load(model_scaled_filename)
print("Scaler和缩放模型已加载。")
# --- 联合使用它们 ---
# 获取原始测试数据(例如,X_test)
# 重要:在新数据上使用transform(),而不是fit_transform()
X_test_scaled = loaded_scaler.transform(X_test)
# 使用加载的模型对缩放后的测试数据进行预测
y_pred_loaded_scaled = loaded_scaled_model.predict(X_test_scaled)
loaded_scaled_accuracy = accuracy_score(y_test, y_pred_loaded_scaled)
print(f"\n使用加载的scaler和模型在测试数据上的准确率: {loaded_scaled_accuracy:.4f}")
在这个例子中,我们使用joblib将scaler和model_scaled保存为单独的文件。稍后进行预测时,我们首先加载这两个对象,然后使用加载的scaler对新数据进行transform处理,再将其提供给加载的model_scaled。未能应用完全相同的缩放将导致不正确的预测。
您也可以将相关对象(如模型及其scaler)一起保存到一个字典或列表中,并序列化这一个对象,尽管管理单独的文件通常更清晰。
在本次实践练习中,您学习了如何:
scikit-learn模型。pickle和joblib将训练好的模型保存到文件。保存和加载模型是准备机器学习工作以进行部署或共享的基本步骤。通过序列化您的模型及其必要组件,您可以确保它们可以在原始训练环境之外可靠地使用。
这部分内容有帮助吗?
© 2026 ApX Machine Learning用心打造