原文:
www.kdnuggets.com/2020/12/pruning-machine-learning-models-tensorflow.html
评论
在上一篇文章中,我们回顾了一些关于剪枝神经网络的主要文献。我们了解到剪枝是一种模型优化技术,涉及到在权重张量中消除不必要的值。这将导致更小的模型,其准确性非常接近基线模型。
在这篇文章中,我们将通过一个示例来应用剪枝,并查看对最终模型大小和预测误差的影响。
1. 谷歌网络安全证书 - 快速进入网络安全职业。
2. 谷歌数据分析专业证书 - 提升你的数据分析技能
3. 谷歌 IT 支持专业证书 - 支持组织的 IT 工作
我们的第一步是处理几个导入:
-
Os
和Zipfile
将帮助我们评估模型的大小。 -
tensorflow_model_optimization
用于模型剪枝。 -
load_model
用于加载已保存的模型。 -
当然还包括
tensorflow
和keras
。
最后,我们初始化 TensorBoard,以便能够可视化模型:
import os
import zipfile
import tensorflow as tf
import tensorflow_model_optimization as tfmot
from tensorflow.keras.models import load_model
from tensorflow import keras
%load_ext tensorboard
在这个实验中,我们将使用 scikit-learn 生成一个回归数据集。然后,我们将数据集拆分为训练集和测试集:
from sklearn.datasets import make_friedman1
X, y = make_friedman1(n_samples=10000, n_features=10, random_state=0)from sklearn.model_selection import train_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()
让我们编译模型并训练它。
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=early_stop,verbose=0)
由于这是一个回归问题,我们监控的是平均绝对误差和均方误差。
这是绘制为图像的模型。输入是 10,因为我们生成的数据集有 10 个特征。
tf.keras.utils.plot_model(
model,
to_file=”model.png”,
show_shapes=True,
show_layer_names=True,
rankdir=”TB”,
expand_nested=True,
dpi=96,
)
现在让我们检查均方误差。我们可以继续到下一部分,看看剪枝整个模型时该误差如何变化。
from sklearn.metrics import mean_squared_errorpredictions = model.predict(X_test)print(‘Without Pruning MSE %.4f’ % mean_squared_error(y_test,predictions.reshape(3300,)))Without Pruning MSE 0.0201
让我们将上述均方误差与修剪整个模型后获得的均方误差进行比较。第一步是定义修剪参数。权重修剪是基于大小的。这意味着一些权重在训练过程中被转换为零。模型变得稀疏,从而使其更容易压缩。稀疏模型还使推理更快,因为零值可以被跳过。
期望的参数是修剪计划、块大小和块池化类型。
-
在这种情况下,我们设置了 50% 的 稀疏性,意味着 50% 的权重将被置零。
-
block_size
— 块的尺寸(高度、宽度)矩阵权重张量中的稀疏模式。
-
block_pooling_type
— 用于池化权重的函数块。必须是
AVG
或MAX
。
现在我们可以通过应用我们的修剪参数来修剪整个模型。
让我们查看模型摘要。将其与未修剪模型的摘要进行比较。从下面的图像中我们可以看到整个模型已经被修剪——稍后我们将通过修剪一个密集层后获得的摘要看到不同之处。
model_to_prune.summary()
在我们可以将模型拟合到训练和测试集之前,我们必须编译模型。
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(),
# Log sparsity and other metrics in Tensorboard.
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(‘Whole Model Pruned MSE %.4f’ % mean_squared_error(y_test,prune_predictions.reshape(3300,)))Whole Model Pruned MSE 0.1830
现在,让我们实现相同的模型——但这一次,我们只修剪密集层。注意在修剪计划中使用的 [PolynomialDecay](https://www.tensorflow.org/model_optimization/api_docs/python/tfmot/sparsity/keras/PolynomialDecay)
函数。
从摘要中,我们可以看到只有第一个密集层将被修剪。
model_layer_prunning.summary()
然后我们编译并拟合模型。
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(‘Layer Prunned MSE %.4f’ % mean_squared_error(y_test,layer_prune_predictions.reshape(3300,)))Layer Prunned MSE 0.1388
我们无法将此处获得的 MSE 与之前的进行比较,因为我们使用了不同的剪枝参数。如果你想比较它们,请确保剪枝参数相似。经过测试,layer_pruning_params
在这种特定情况下比 pruning_params
的误差更低。比较不同剪枝参数获得的 MSE 很有用,以便你可以选择不会降低模型性能的参数。
现在让我们比较有剪枝和无剪枝模型的大小。我们首先训练并保存模型权重以供后续使用。
我们将设置基础模型并加载保存的权重。然后我们剪枝整个模型。我们编译、训练模型,并在 Tensorboard 上可视化结果。
这是 TensorBoard 上剪枝总结的一个快照。
其他剪枝总结也可以在 Tensorboard 上查看。
现在让我们定义一个函数来计算模型的大小。
现在我们定义导出模型并计算其大小。
对于剪枝模型, tfmot.sparsity.keras.strip_pruning()
用于恢复原始模型的稀疏权重。注意被剪枝和未剪枝模型的大小差异。
model_for_export = tfmot.sparsity.keras.strip_pruning(model_for_pruning)
Size of gzipped pruned model without stripping: 6101.00 bytes
Size of gzipped pruned model with stripping: 5140.00 bytes
对两个模型进行预测,我们发现它们具有相同的均方误差。
Model for Prunning Error 0.0264
Model for Export Error 0.0264
你可以测试不同的剪枝计划如何影响模型的大小。显然,这里的观察结果并不普遍。你需要尝试不同的剪枝参数,了解它们如何影响你的模型大小、预测误差和/或准确性,具体取决于你的问题。
要进一步优化模型,你可以对其进行量化。如果你想深入了解这一点以及更多内容,请查看下面的资源和仓库。
Keras 中的剪枝示例 | TensorFlow 模型优化
欢迎来到基于幅度的权重剪枝的端到端示例。有关剪枝是什么以及如何...
适用于移动和嵌入式设备的 TensorFlow Lite
在这篇文章中,我们通过一个示例来应用剪枝,并查看对最终模型大小的影响...
8 位量化和 TensorFlow Lite:通过低精度加速移动推理
heartbeat.fritz.ai
简介:德里克·姆维提是一位数据科学家,对知识分享充满热情。他通过 Heartbeat、Towards Data Science、Datacamp、Neptune AI、KDnuggets 等博客积极参与数据科学社区。他的内容在互联网上的浏览量超过一百万次。德里克还是一名作者和在线讲师。他还与多个机构合作,实施数据科学解决方案并提升员工技能。德里克在多媒体大学学习了数学和计算机科学,还是 Meltwater 创业技术学校的校友。如果数据科学、机器学习和深度学习的世界引起了你的兴趣,你可能会想了解他的Python 数据科学与机器学习完整课程。
原文。经许可转载。
相关:
-
使用 TensorFlow Serving 将训练好的模型部署到生产环境
-
处理机器学习中的不平衡数据
-
如何将 PyTorch Lightning 模型部署到生产环境