发布时间:2025-07-24
点击次数: 本文围绕CV领域MLP模型压缩中的剪枝技术展开,介绍剪枝因深度学习模型过参数化而生,可去除冗余参数。细粒度剪枝分训练基准模型、剪去低于阈值连接、微调恢复性能等步骤。还给出MLP剪枝实现代码,包括网络搭建、训练、剪枝函数等,展示剪枝前后效果,提及卷积剪枝思路。
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜


剪枝步骤
- 第一步:训练一个基准模型。
- 第二步:对权重值的幅度进行排序,去掉低于一个预设阈值的连接,得到剪枝后的网络。
- 第三步:对剪枝后网络进行微调以恢复损失的性能,然后继续进行第二步,依次交替,直到满足终止条件,比如精度下降在一定范围内。

简小派
简小派是一款AI原生求职工具,通过简历优化、岗位匹配、项目生成、模拟面试与智能投递,全链路提升求职成功率,帮助普通人更快拿到更好的 offer。
123
查看详情
np.percentile(a, q, axis=None, out=None, overwrite_input=False, interpolation='linear', keepdims=False)
a : array,用来算分位数的对象,可以是多维的数组
q : 介于0-100的float,用来计算是几分位的参数,如四分之一位就是25,如要算两个位置的数就(25,75)
axis : 坐标轴的方向,一维的就不用考虑了,多维的就用这个调整计算的维度方向,取值范围0/1
out : 输出数据的存放对象,参数要与预期输出有相同的形状和缓冲区长度
overwrite_input : bool,默认False,为True时及计算直接在数组内存计算,计算后原数组无法保存
interpolation : 取值范围{'linear', 'lower', 'higher', 'midpoint', 'nearest'}
默认liner,比如取中位数,但是中位数有两个数字6和7,选不同参数来调整输出
keepdims : bool,默认False,为真时取中位数的那个轴将保留在结果中
In [1]
# 作用:找到一组数的分位数值,如二分位数等(具体什么位置根据自己定义)# 方便我们之后设定剪枝的阈值import numpy as np a = np.array([[1,2,3,4,5,6,7,8,9]]) np.percentile(a, 50)
5.0
核心代码实现步骤
- 1 通过设定的阈值找到相应的权重,大于这个权重为true,小于为false,生成bool矩阵
- 2 将bool矩阵转为0-1矩阵,这就是我们所需的mask
- 3 mask乘上初始权重得到最终剪枝后的权重
# 导入所需包import paddleimport paddle.nn as nnimport paddle.nn.functional as Fimport paddle.utilsimport numpy as npimport mathfrom copy import deepcopyfrom matplotlib import pyplot as pltfrom paddle.io import Datasetfrom paddle.io import DataLoaderfrom paddle.vision import datasetsfrom paddle.vision import transforms
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/__init__.py:107: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working from collections import MutableMapping /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/rcsetup.py:20: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working from collections import Iterable, Mapping /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/colors.py:53: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working from collections import SizedIn [2]
# 搭建基础线性层class MaskedLinear(nn.Linear):
def __init__(self, in_features, out_features, bias=True):
super(MaskedLinear, self).__init__(in_features, out_features, bias)
self.mask_flag = False
self.mask = None
def set_mask(self, mask):
self.mask = mask
self.weight.set_value(self.weight * self.mask)
self.mask_flag = True
def get_mask(self):
print(self.mask_flag) return self.mask def forward(self, x):
if self.mask_flag:
weight = self.weight * self.mask return F.linear(x, weight, self.bias) else: return F.linear(x, self.weight, self.bias)
In [3]
# 搭建MLP网络class MLP(nn.Layer):
def __init__(self):
super(MLP, self).__init__()
self.linear1 = MaskedLinear(28 * 28 * 3, 200)
self.relu1 = nn.ReLU()
self.linear2 = MaskedLinear(200, 200)
self.relu2 = nn.ReLU()
self.linear3 = MaskedLinear(200, 10) def forward(self, x):
out = paddle.reshape(x, (x.shape[0], -1))
out = self.relu1(self.linear1(out))
out = self.relu2(self.linear2(out))
out = self.linear3(out) return out def set_masks(self, masks):
# Should be a less manual way to set masks
# Le*e it for the future
self.linear1.set_mask(masks[0])
self.linear2.set_mask(masks[1])
self.linear3.set_mask(masks[2])
In [4]
# 打印输出网络结构mlp_Net = MLP() paddle.summary(mlp_Net,(1, 3, 28, 28))
W0127 11:14:20.232509 135 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 10.1, Runtime API Version: 10.1 W0127 11:14:20.238121 135 device_context.cc:465] device: 0, cuDNN Version: 7.6.
---------------------------------------------------------------------------
Layer (type) Input Shape Output Shape Param #
===========================================================================
MaskedLinear-1 [[1, 2352]] [1, 200] 470,600
ReLU-1 [[1, 200]] [1, 200] 0
MaskedLinear-2 [[1, 200]] [1, 200] 40,200
ReLU-2 [[1, 200]] [1, 200] 0
MaskedLinear-3 [[1, 200]] [1, 10] 2,010
===========================================================================
Total params: 512,810
Trainable params: 512,810
Non-trainable params: 0
---------------------------------------------------------------------------
Input size (MB): 0.01
Forward/backward pass size (MB): 0.01
Params size (MB): 1.96
Estimated Total Size (MB): 1.97
---------------------------------------------------------------------------
{'total_params': 512810, 'trainable_params': 512810}
In [5]
# 图像转tensor操作,也可以加一些数据增强的方式,例如旋转、模糊等等# 数据增强的方式要加在Compose([ ])中def get_transforms(mode='train'):
if mode == 'train':
data_transforms = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=[0.4914, 0.4822, 0.4465], std=[0.2025, 0.1994, 0.2010])]) else:
data_transforms = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=[0.4914, 0.4822, 0.4465], std=[0.2025, 0.1994, 0.2010])]) return data_transforms# 获取官方MNIST数据集def get_data
set(name='MNIST', mode='train'):
if name == 'MNIST':
dataset = datasets.MNIST(mode=mode, transform=get_transforms(mode)) return dataset# 定义数据加载到模型形式def get_dataloader(dataset, batch_size=128, mode='train'):
dataloader = DataLoader(dataset, batch_size=batch_size, num_workers=2, shuffle=(mode == 'train')) return dataloader
In [6]
# 初始化函数,用于模型初始化class AverageMeter():
""" Meter for monitoring losses"""
def __init__(self):
self.*g = 0
self.sum = 0
self.cnt = 0
self.reset() def reset(self):
"""reset all values to zeros"""
self.*g = 0
self.sum = 0
self.cnt = 0
def update(self, val, n=1):
"""update *g by val and n, where val is the *g of n values"""
self.sum += val * n
self.cnt += n
self.*g = self.sum / self.cnt
In [7]
# mlp网络训练def mlp_train_one_epoch(model, dataloader, criterion, optimizer, epoch, total_epoch, report_freq=20):
print(f'----- Training Epoch [{epoch}/{total_epoch}]:')
loss_meter = AverageMeter()
acc_meter = AverageMeter()
model.train() for batch_idx, data in enumerate(dataloader):
image = data[0]
label = data[1]
out = model(image)
loss = criterion(out, label)
loss.backward()
optimizer.step()
optimizer.clear_grad()
pred = nn.functional.softmax(out, axis=1)
acc1 = paddle.metric.accuracy(pred, label)
batch_size = image.shape[0]
loss_meter.update(loss.cpu().numpy()[0], batch_size)
acc_meter.update(acc1.cpu().numpy()[0], batch_size) if batch_idx > 0 and batch_idx % report_freq == 0: print(f'----- Batch[{batch_idx}/{len(dataloader)}], Loss: {loss_meter.*g:.5}, Acc@1: {acc_meter.*g:.4}') print(f'----- Epoch[{epoch}/{total_epoch}], Loss: {loss_meter.*g:.5}, Acc@1: {acc_meter.*g:.4}')
In [8]
# mlp网络预测def mlp_validate(model, dataloader, criterion, report_freq=10):
print('----- Validation')
loss_meter = AverageMeter()
acc_meter = AverageMeter()
model.eval() for batch_idx, data in enumerate(dataloader):
image = data[0]
label = data[1]
out = model(image)
loss = criterion(out, label)
pred = paddle.nn.functional.softmax(out, axis=1)
acc1 = paddle.metric.accuracy(pred, label)
batch_size = image.shape[0]
loss_meter.update(loss.cpu().numpy()[0], batch_size)
acc_meter.update(acc1.cpu().numpy()[0], batch_size) if batch_idx > 0 and batch_idx % report_freq == 0: print(f'----- Batch [{batch_idx}/{len(dataloader)}], Loss: {loss_meter.*g:.5}, Acc@1: {acc_meter.*g:.4}') print(f'----- Validation Loss: {loss_meter.*g:.5}, Acc@1: {acc_meter.*g:.4}')
In [9]
def weight_prune(model, pruning_perc):
'''
Prune pruning_perc % weights layer-wise
'''
threshold_list = [] for p in model.parameters(): if len(p.shape) != 1: # bias
weight = p.abs().numpy().flatten() # 将权重参数拉伸为1维
threshold = np.percentile(weight, pruning_perc) # 根据阈值对权重参数进行筛选
threshold_list.append(threshold) # generate mask
masks = []
idx = 0
for p in model.parameters(): if len(p.shape) != 1:
pruned_inds = p.abs() > threshold_list[idx] # 返回bool矩阵
pruned_inds = paddle.cast(pruned_inds, 'float32') # paddle.cast将bool->float
masks.append(pruned_inds)
idx += 1
return masks
In [10]
# mlp网络主函数def mlp_main():
total_epoch = 1
batch_size = 256
model = MLP()
train_dataset = get_dataset(mode='train')
train_dataloader = get_dataloader(train_dataset, batch_size, mode='train')
val_dataset = get_dataset(mode='test')
val_dataloader = get_dataloader(val_dataset, batch_size, mode='test')
criterion = nn.CrossEntropyLoss()
scheduler = paddle.optimizer.lr.CosineAnnealingDecay(0.02, total_epoch)
optimizer = paddle.optimizer.Momentum(learning_rate=scheduler,
parameters=model.parameters(),
momentum=0.9,
weight_decay=5e-4)
eval_mode = False
if eval_mode:
state_dict = paddle.load('./mlp_ep2.pdparams')
model.set_state_dict(state_dict)
mlp_validate(model, val_dataloader, criterion) return
s*e_freq = 5
test_freq = 1
for epoch in range(1, total_epoch+1):
mlp_train_one_epoch(model, train_dataloader, criterion, optimizer, epoch, total_epoch)
scheduler.step() if epoch % test_freq == 0 or epoch == total_epoch:
mlp_validate(model, val_dataloader, criterion) if epoch % s*e_freq == 0 or epoch == total_epoch:
paddle.s*e(model.state_dict(), f'./mlp_ep{epoch}.pdparams')
paddle.s*e(optimizer.state_dict(), f'./mlp_ep{epoch}.pdopts') # 剪枝后的效果
print("\n=====Pruning 60%=======\n")
pruned_model = deepcopy(model)
mask = weight_prune(pruned_model, 60)
pruned_model.set_masks(mask)
mlp_validate(pruned_model, val_dataloader, criterion) return model,pruned_model
In [11]
# 返回值是剪枝前后网络模型mlp_model, mlp_pruned_model = mlp_main()In [12]
# 定义模型权重展示函数def plot_weights(model):
modules = [module for module in model.sublayers()]
num_sub_plot = 0
for i, layer in enumerate(modules): if hasattr(layer, 'weight'):
plt.subplot(131+num_sub_plot)
w = layer.weight
w_one_dim = w.cpu().numpy().flatten()
plt.hist(w_one_dim[w_one_dim!=0], bins=50)
num_sub_plot += 1
plt.show()
In [13]
# 剪枝前的权重plot_weights(mlp_model)
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/cbook/__init__.py:2349: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working if isinstance(obj, collections.Iterator): /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/cbook/__init__.py:2366: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working return list(data) if isinstance(data, collections.MappingView) else data
<Figure size 432x288 with 3 Axes>In [14]
# 剪枝后的权重plot_weights(mlp_pruned_model)
<Figure size 432x288 with 3 Axes>

# 找出特定元素的位置# 筛选出True值对应位置的数据np.random.seed(7) #相同的种子可确保随机数按序生成时是相同的,结果可重现b = np.random.randint(40, 100, size=(6,6)) # 生成40到100,6x6个随机数print('b={}\nb中小于70的元素为\n\n{}'.format(b,b<70))
ind = np.where(b>60,b,0) # 返回的是一个tuple 类型print("np.where(b>60,b,0)=\n{}".format(ind))b=[[87 44 65 94 43 59] [63 79 68 97 54 63] [48 65 86 82 66 48] [79 78 44 88 47 84] [40 51 95 98 46 59] [84 45 96 64 95 93]] b中小于70的元素为 [[False True True False True True] [ True False True False True True] [ True True False False True True] [False False True False True False] [ True True False False True True] [False True False True False False]] np.where(b>60,b,0)= [[87 0 65 94 0 0] [63 79 68 97 0 63] [ 0 65 86 82 66 0] [79 78 0 88 0 84] [ 0 0 95 98 0 0] [84 0 96 64 95 93]]
以上就是模型压缩之剪枝(MLP)的详细内容,更多请关注其它相关文章!
# ai
# cos
# 排列
# python
# 济源官网seo关键词排名厂家
# 外贸seo视频
# 富阳百度网站优化
# 石家庄seo竞价知识
# 营销和宣传推广哪个好
# 湖北seo优化收费
# 温州抖音营销推广报名
# 如何选择优化网站模板
# 江西专业网络推广网站
# 寒假营销推广策划书
# 的是
# 如下图
# 官网
# 第二步
# 被称为
# 所需
# 随机数
# 一言
# 中文网
# 多维
# type
# fig
# latte
# liner
# red
相关栏目:
【
行业新闻62819 】
【
科技资讯67470 】
相关推荐:
复旦发布「新闻推荐生态系统模拟器」SimuLine:单机支持万名读者、千名创作者、100+轮次推荐
张勇对话多位诺奖得主 人工智能将无处不在
此「错」并非真的错:从四篇经典论文入手,理解Transformer架构图「错」在何处
无人机自主巡检为高海拔输电线路运维添“新彩”
独家视角:首次展示有人与无人协同打击的7000米高空察打一体无人机
13万个注释神经元,5300万个突触,普林斯顿大学等发布首个完整「成年果蝇」大脑连接组
周鸿祎参加中美青年科技创新峰会,分享人工智能创新机遇
AI大模型紫东太初已被注册商标 中科院已注册紫东太初大模型商标
英伟达CEO宣称生成式AI已迎来“划时代时刻”
日媒:AI高效解析纳斯卡地画
码刻 | 48小时Hackathon,源码见证新生代AI创新的发生
微软在 Build 大会上宣布的新 Microsoft Store AI Hub 现已开始推出
对话式论文阅读工具PaperMate上线,综述细节AI告诉你
人工智能“Aria”现身 Opera浏览器100版本更新:新功能“标签岛”
元宇宙技术带你穿梭“大运河”,江苏书展上的数字阅读馆吸睛小读者
中国气象局预测:到 2030 年,中国人工智能气象应用将达到国际领先水平
陈根:AI工具为游戏软件实时3D内容助力
边喷火边跳踢踏舞,机器狗最新技能爆火全网!网友直呼真·热狗
对Hugging Face开源模型精准投毒!LLM切脑后变身PoisonGPT,用虚假事实洗脑60亿人
生成式AI与云结合,机遇与挑战并存
马斯克“揭秘”人工智能真面目
脑虎科技:奔跑在“脑机接口”最前沿 跨界融合取得阶段性成果
万兴播爆桌面端上线,支持AI数字人搜索、视频编辑等功能
RoboNeo操作教程
参议院司法听证会:AI 不易管控,有可能被恶意分子利用来研发生化武器
研究发现AI聊天机器人ChatGPT不会讲笑话,只会重复25个老梗
Xbox游戏工作室负责人:VR/AR领域的用户规模还不足够
即时 AI再次升级 30秒生成自带动效的网页 生成速度提升100%
工业机器人及非标自动化设备集成服务提供商
贫穷让我预训练
AI大模型产品集体奔赴高考考场,教育赛道的讯飞星火能赢吗?
联想举办2025创新开放日,展出260余项算力及AI产品技术
美图秀秀“AI 扩图”功能上线,可根据图像生成更大画幅
衡水市冀州中学机器人社团在世界机器人大赛中斩获佳绩
昇腾AI & 讯飞星火:深度联手,共话国产大模型“大未来”
Win11 的画图应用将包含 Windows Copilot 的 AI 工具整合
【搞事】时隔4年 谷歌更新安卓logo 机器人头更饱满了
“黑科技”亮相大湾区轨交论坛 智慧交通迈向“强AI”
联想创投携手12家被投企业MWC展示元宇宙、机器人等技术
定义人工智能的十个关键术语
海南科技职业大学第25届中国机器人及人工智能大赛海南赛区荣获一等奖等114项
【|直播|预告】人工智能高峰论坛将于7月2日13:30准时开播!
智能机器人与话剧的完美结合:宇树四足机器人B1助力《骆驼祥子》重现经典
鉴智机器人发布基于地平线征程5的标准视觉感知产品
网友自制 AI 版《流浪地球 3》预告片,登上 CCTV6
微幼科技推出全自动晨检机器人,助力幼儿园校园健康检测
直击上影节 | 光线传媒董事长王长田谈新技术:未来VR放映效果可能媲美影院
360发布AI数字人广场,可同孙悟空、爱因斯坦等古今中外角色对话
华为联合合作伙伴 共同发布昇腾AI大模型训推一体化解决方案
陈根:AI冥想教练为用户提供个性化指导