在TensorFlow中使用模型剪枝将机器学习模型变得更小

本文涉及的产品
交互式建模 PAI-DSW,每月250计算时 3个月
模型训练 PAI-DLC,100CU*H 3个月
模型在线服务 PAI-EAS,A10/V100等 500元 1个月
简介: 在TensorFlow中使用模型剪枝将机器学习模型变得更小

学习如何通过剪枝来使你的模型变得更小

640.png

剪枝是一种模型优化技术,这种技术可以消除权重张量中不必要的值。这将会得到更小的模型,并且模型精度非常接近标准模型。

在本文中,我们将通过一个例子来观察剪枝技术对最终模型大小和预测误差的影响。

导入常见问题


我们的第一步导入一些工具、包:

  • Os和Zi    pfile可以帮助我们评估模型的大小。
  • tensorflow_model_optimization用来修剪模型。
  • load_model用于加载保存的模型。
  • 当然还有tensorflow和keras。


最后,初始化TensorBoard,这样就可以将模型可视化:

importosimportzipfileimporttensorflowastfimporttensorflow_model_optimizationastfmotfromtensorflow.keras.modelsimportload_modelfromtensorflowimportkeras%load_exttensorboard

数据集生成


在这个实验中,我们将使用scikit-learn生成一个回归数据集。之后,我们将数据集分解为训练集和测试集:

fromsklearn.datasetsimportmake_friedman1X, y=make_friedman1(n_samples=10000, n_features=10, random_state=0)
fromsklearn.model_selectionimporttrain_test_splitX_train, X_test, y_train, y_test=train_test_split(X, y, test_size=0.33, random_state=42)

没有应用剪枝技术的模型


我们将创建一个简单的神经网络来预测目标变量y,然后检查均值平方误差。在此之后,我们将把它与修剪过的整个模型进行比较,然后只与修剪过的Dense层进行比较。


接下来,在30个训练轮次之后,一旦模型停止改进,我们就使用回调来停止训练它。

early_stop = keras.callbacks.EarlyStopping(monitor=’val_loss’, patience=30)

我们打印出模型概述,以便与运用剪枝技术的模型概述进行比较。

model=setup_model()
model.summary()

640.png

让我们编译模型并训练它。

tf.keras.utils.plot_model(
model,
to_file=”model.png”,
show_shapes=True,
show_layer_names=True,
rankdir=”TB”,
expand_nested=True,
dpi=96,
)

640.png

现在检查一下均方误差。我们可以继续到下一节,看看当我们修剪整个模型时,这个误差是如何变化的。

fromsklearn.metricsimportmean_squared_errorpredictions=model.predict(X_test)
print(‘WithoutPruningMSE%.4f%mean_squared_error(y_test,predictions.reshape(3300,)))
WithoutPruningMSE0.0201

当把模型部署到资源受限的边缘设备(如手机)时,剪枝等优化模型技术尤其重要。

采用等稀疏修剪对整个模型进行剪枝

我们将上面的MSE与修剪整个模型得到的MSE进行比较。第一步是定义剪枝参数。权重剪枝是基于数量级的。这意味着在训练过程中一些权重被转换为零。模型变得稀疏,这样就更容易压缩。由于可以跳过零,稀疏模型还可以加快推理速度。


预期的参数是剪枝计划、块大小和块池类型。

  • 在本例中,我们设置了50%的稀疏度,这意味着50%的权重将归零。
  • block_size —— 矩阵权重张量中块稀疏模式的维度(高度,权值)。
  • block_pooling_type —— 用于对块中的权重进行池化的函数。必须是AVG或MAX。

 

fromtensorflow_model_optimization.sparsity.kerasimportConstantSparsitypruning_params= {
'pruning_schedule': ConstantSparsity(0.5, 0),
'block_size': (1, 1),
'block_pooling_type': 'AVG'}

现在,我们可以应用我们的剪枝参数来修剪整个模型。

fromtensorflow_model_optimization.sparsity.kerasimportprune_low_magnitudemodel_to_prune=prune_low_magnitude(
keras.Sequential([
tf.keras.layers.Dense(128, activation='relu', input_shape=(X_train.shape[1],)),
tf.keras.layers.Dense(1, activation='relu')
]), **pruning_params)

我们检查模型概述。将其与未剪枝模型的模型进行比较。从下图中我们可以看到整个模型已经被剪枝 —— 我们将很快看到剪枝一个稠密层后模型概述的区别。

model_to_prune.summary()

640.png

在TF中,我们必须先编译模型,然后才能将其用于训练集和测试集。

model_to_prune.compile(optimizer=’adam’,
loss=tf.keras.losses.mean_squared_error,
metrics=[‘mae’, ‘mse’])

由于我们正在使用剪枝技术,所以除了早期停止回调函数之外,我们还必须定义两个剪枝回调函数。我们定义一个记录模型的文件夹,然后创建一个带有回调函数的列表。

tfmot.sparsity.keras.UpdatePruningStep()

使用优化器步骤更新剪枝包装器。如果未能指定剪枝包装器,将会导致错误。

tfmot.sparsity.keras.PruningSummaries()

将剪枝概述添加到Tensorboard。

log_dir=.models’callbacks= [
tfmot.sparsity.keras.UpdatePruningStep(),
#LogsparsityandothermetricsinTensorboard.
tfmot.sparsity.keras.PruningSummaries(log_dir=log_dir),
keras.callbacks.EarlyStopping(monitor=’val_loss’, patience=10)
]

有了这些,我们现在就可以将模型与训练集相匹配了。

model_to_prune.fit(X_train,y_train,epochs=100,validation_split=0.2,callbacks=callbacks,verbose=0)

在检查这个模型的均方误差时,我们注意到它比未剪枝模型的均方误差略高。

prune_predictions=model_to_prune.predict(X_test)
print(‘WholeModelPrunedMSE%.4f%mean_squared_error(y_test,prune_predictions.reshape(3300,)))
WholeModelPrunedMSE0.1830

用多项式剪枝计划对稠密层进行剪枝

现在让我们实现相同的模型,但这一次,我们将只剪枝稠密层。请注意在剪枝计划中使用多项式衰退函数。

fromtensorflow_model_optimization.sparsity.kerasimportPolynomialDecaylayer_pruning_params= {
'pruning_schedule': PolynomialDecay(initial_sparsity=0.2,
final_sparsity=0.8, begin_step=1000, end_step=2000),
'block_size': (2, 3),
'block_pooling_type': 'MAX'}
model_layer_prunning=keras.Sequential([
prune_low_magnitude(tf.keras.layers.Dense(128, activation='relu',input_shape=(X_train.shape[1],)),
**layer_pruning_params),
tf.keras.layers.Dense(1, activation='relu')
  ])


从概述中我们可以看到只有第一个稠密层将被剪枝。

model_layer_prunning.summary()

640.png

然后我们编译并拟合模型。

model_layer_prunning.compile(optimizer=’adam’,
loss=tf.keras.losses.mean_squared_error,
metrics=[‘mae’, ‘mse’])
model_layer_prunning.fit(X_train,y_train,epochs=300,validation_split=0.1,callbacks=callbacks,verbose=0)

现在,让我们检查均方误差。

layer_prune_predictions=model_layer_prunning.predict(X_test)
print(‘LayerPrunnedMSE%.4f%mean_squared_error(y_test,layer_prune_predictions.reshape(3300,)))
LayerPrunnedMSE0.1388

由于我们使用了不同的剪枝参数,所以我们无法将这里获得的MSE与之前的MSE进行比较。如果您想比较它们,那么请确保剪枝参数是相同的。在测试时,对于这个特定情况,layer_pruning_params给出的错误比pruning_params要低。比较从不同的剪枝参数获得的MSE是有用的,这样你就可以选择一个不会使模型性能变差的MSE。

比较模型大小

现在让我们比较一下有剪枝和没有剪枝模型的大小。我们从训练和保存模型权重开始,以便以后使用。

deftrain_save_weights():
model=setup_model()
model.compile(optimizer='adam',
loss=tf.keras.losses.mean_squared_error,
metrics=['mae', 'mse'])
model.fit(X_train,y_train,epochs=300,validation_split=0.2,callbacks=callbacks,verbose=0)
model.save_weights('.models/friedman_model_weights.h5')
train_save_weights()

我们将建立我们的基础模型,并加载保存的权重。然后我们对整个模型进行剪枝。我们编译、拟合模型,并在Tensorboard上将结果可视化。

base_model=setup_model()
base_model.load_weights('.models/friedman_model_weights.h5') #optionalbutrecommendedformodelaccuracymodel_for_pruning=tfmot.sparsity.keras.prune_low_magnitude(base_model)
model_for_pruning.compile(
loss=tf.keras.losses.mean_squared_error,
optimizer='adam',
metrics=['mae', 'mse']
)
model_for_pruning.fit(
X_train,
y_train,
callbacks=callbacks,
epochs=300,
validation_split=0.2,
verbose=0)
%tensorboard--logdir={log_dir}

以下是TensorBoard的剪枝概述的快照。

640.png

在TensorBoard上也可以看到其它剪枝模型概述

640.png

现在让我们定义一个计算模型大小函数

defget_gzipped_model_size(model,mode_name,zip_name):
#Returnssizeofgzippedmodel, inbytes.
model.save(mode_name, include_optimizer=False)
withzipfile.ZipFile(zip_name, 'w', compression=zipfile.ZIP_DEFLATED) asf:
f.write(mode_name)
returnos.path.getsize(zip_name)

现在我们定义导出模型,然后计算大小。

对于剪枝过的模型,tfmot.sparsity.keras.strip_pruning()用来恢复带有稀疏权重的原始模型。请注意剥离模型和未剥离模型在尺寸上的差异。

model_for_export=tfmot.sparsity.keras.strip_pruning(model_for_pruning)
print("Size of gzipped pruned model without stripping: %.2f bytes"% (get_gzipped_model_size(model_for_pruning,'.models/model_for_pruning.h5','.models/model_for_pruning.zip')))
print("Size of gzipped pruned model with stripping: %.2f bytes"% (get_gzipped_model_size(model_for_export,'.models/model_for_export.h5','.models/model_for_export.zip')))
Sizeofgzippedprunedmodelwithoutstripping: 6101.00bytesSizeofgzippedprunedmodelwithstripping: 5140.00bytes

对这两个模型进行预测,我们发现它们具有相同的均方误差。

model_for_prunning_predictions=model_for_pruning.predict(X_test)
print('Model for Prunning Error %.4f'%mean_squared_error(y_test,model_for_prunning_predictions.reshape(3300,)))
model_for_export_predictions=model_for_export.predict(X_test)
print('Model for Export Error %.4f'%mean_squared_error(y_test,model_for_export_predictions.reshape(3300,)))
ModelforPrunningError0.0264ModelforExportError0.0264

最终想法

您可以继续测试不同的剪枝计划如何影响模型的大小。显然这里的观察结果不具有普遍性。也可以尝试不同的剪枝参数,并了解它们如何影响您的模型大小、预测误差/精度,这将取决于您要解决的问题。

为了进一步优化模型,您可以将其量化。如果您想了解更多,请查看下面的回购和参考资料。

相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
目录
相关文章
|
2天前
|
机器学习/深度学习 人工智能 算法
机器学习算法的优化与改进:提升模型性能的策略与方法
机器学习算法的优化与改进:提升模型性能的策略与方法
28 13
机器学习算法的优化与改进:提升模型性能的策略与方法
|
2月前
|
人工智能 JSON 算法
Qwen2.5-Coder 系列模型在 PAI-QuickStart 的训练、评测、压缩及部署实践
阿里云的人工智能平台 PAI,作为一站式、 AI Native 的大模型与 AIGC 工程平台,为开发者和企业客户提供了 Qwen2.5-Coder 系列模型的全链路最佳实践。本文以Qwen2.5-Coder-32B为例,详细介绍在 PAI-QuickStart 完成 Qwen2.5-Coder 的训练、评测和快速部署。
Qwen2.5-Coder 系列模型在 PAI-QuickStart 的训练、评测、压缩及部署实践
|
23天前
|
编解码 机器人 测试技术
技术实践 | 使用 PAI+LLaMA Factory 微调 Qwen2-VL 模型快速搭建专业领域知识问答机器人
Qwen2-VL是一款具备高级图像和视频理解能力的多模态模型,支持多种语言,适用于多模态应用开发。通过PAI和LLaMA Factory框架,用户可以轻松微调Qwen2-VL模型,快速构建文旅领域的知识问答机器人。本教程详细介绍了从模型部署、微调到对话测试的全过程,帮助开发者高效实现定制化多模态应用。
|
1月前
|
机器学习/深度学习 人工智能 算法
人工智能浪潮下的编程实践:构建你的第一个机器学习模型
在人工智能的巨浪中,每个人都有机会成为弄潮儿。本文将带你一探究竟,从零基础开始,用最易懂的语言和步骤,教你如何构建属于自己的第一个机器学习模型。不需要复杂的数学公式,也不必担心编程难题,只需跟随我们的步伐,一起探索这个充满魔力的AI世界。
49 12
|
2月前
|
机器学习/深度学习 Python
机器学习中评估模型性能的重要工具——混淆矩阵和ROC曲线。混淆矩阵通过真正例、假正例等指标展示模型预测情况
本文介绍了机器学习中评估模型性能的重要工具——混淆矩阵和ROC曲线。混淆矩阵通过真正例、假正例等指标展示模型预测情况,而ROC曲线则通过假正率和真正率评估二分类模型性能。文章还提供了Python中的具体实现示例,展示了如何计算和使用这两种工具来评估模型。
65 8
|
2月前
|
机器学习/深度学习 Python
机器学习中模型选择和优化的关键技术——交叉验证与网格搜索
本文深入探讨了机器学习中模型选择和优化的关键技术——交叉验证与网格搜索。介绍了K折交叉验证、留一交叉验证等方法,以及网格搜索的原理和步骤,展示了如何结合两者在Python中实现模型参数的优化,并强调了使用时需注意的计算成本、过拟合风险等问题。
65 6
|
2月前
|
机器学习/深度学习 数据采集 数据可视化
TensorFlow,一款由谷歌开发的开源深度学习框架,详细讲解了使用 TensorFlow 构建深度学习模型的步骤
本文介绍了 TensorFlow,一款由谷歌开发的开源深度学习框架,详细讲解了使用 TensorFlow 构建深度学习模型的步骤,包括数据准备、模型定义、损失函数与优化器选择、模型训练与评估、模型保存与部署,并展示了构建全连接神经网络的具体示例。此外,还探讨了 TensorFlow 的高级特性,如自动微分、模型可视化和分布式训练,以及其在未来的发展前景。
113 5
|
2月前
|
机器学习/深度学习 人工智能 TensorFlow
基于TensorFlow的深度学习模型训练与优化实战
基于TensorFlow的深度学习模型训练与优化实战
106 0
|
8月前
|
机器学习/深度学习 存储 搜索推荐
利用机器学习算法改善电商推荐系统的效率
电商行业日益竞争激烈,提升用户体验成为关键。本文将探讨如何利用机器学习算法优化电商推荐系统,通过分析用户行为数据和商品信息,实现个性化推荐,从而提高推荐效率和准确性。
259 14
|
8月前
|
机器学习/深度学习 算法 搜索推荐
Machine Learning机器学习之决策树算法 Decision Tree(附Python代码)
Machine Learning机器学习之决策树算法 Decision Tree(附Python代码)

热门文章

最新文章

相关产品

  • 人工智能平台 PAI