英伟达结构化剪枝工具Nvidia Apex Automatic Sparsity [ASP](1)——使用方法
英伟达结构化剪枝工具Nvidia Apex Automatic Sparsity [ASP](1)——使用方法
Apex是Nvdia维护的pytorch工具库,包括混合精度训练和分布式训练,Apex的目的是为了让用户能够更早的使用上这些“新鲜出炉”的训练工具。ASP(Automatic Sparsity)是Nvidia Apex模块中用于模型稀疏剪枝的算法,
项目地址:NVIDIA/apex: A PyTorch Extension: Tools for easy mixed precision and distributed training in Pytorch (github.com)
本文主要介绍的是ASP中的一个用于模型剪枝的模块:ASP(Automatic sparsity),该模块仅仅向python模型训练文件中添加两行代码来实现模型的2:4稀疏剪枝,同时还可以通过开启通道置换算法将绝对值较大的参数进行保留,以求对模型精度的影响最小化。
项目地址:项目
论文链接:论文
Installation
从github clone源码安装需要checkout到23.05的tag
git clone https://github.com/NVIDIA/apex.git
cd apex
git checkout 23.05
pip install -v --disable-pip-version-check --no-cache-dir --global-option="--cpp_ext" --global-option="--cuda_ext" --global-option="--permutation_search" ./
Usage
使用ASP对模型进行稀疏化只需要两步:
# 1. 导入sparsity模块
from apex.contrib.sparsity import ASP
# 2. 使用ASP来模型和优化器进行稀疏化
ASP.prune_trained_model(model, optimizer)
prune_trained_model
函数会计算出稀疏mask并将其施加在模型的权重上。
整体而言,通常需要在对模型稀疏化后重新进行训练,整个过程可以表示为:
ASP.prune_trained_model(model, optimizer)x, y = DataLoader(args)
for epoch in range(epochs):y_pred = model(x)loss = loss_function(y_pred, y)loss.backward()optimizer.step()torch.save(...)
非标准用法:
ASP还可以用来为模型生成稀疏的随机化参数,从而进行更加复杂高级的实验,如果在两个step之间重新计算权重的稀疏矩阵,可以通过在训练的step之间调用ASP.recompute_sparse_masks
函数来为模型重新生成稀疏mask。
Channel Permutation
该项目还可以通过开启通道置换算法,来为结构化稀疏后的模型保留最大的精度值。
通道置换算法,顾名思义,就是通过沿着权重矩阵的通道维度进行置换,并对其周围的模型层进行适当调整。
如果开启通道置换算法,那么最终的模型精度与置换算法的质量之间存在很大关系,置换的过程可以通过Apex CUDA拓展来进行加速,否则时间会非常的久。
在Installation步骤中,参数--global-option="--permutation_search"
即是用于安装permutation search CUDA extension 。
如果不希望开启通道置换算法,可以在ASP.init_model_for_pruning
方法中将参数allow_permutation
的值设置为False即可,这一点在后续的源代码分析中也会提到。
需要注意的是,当使用多个GPU时,需要为所有的GPU设置相同的随机种子,通过permutation_lib.py中的 set_identical_seed
来进行设置。
import torch
import numpy
import randomtorch.manual_seed(identical_seed)
torch.cuda.manual_seed_all(identical_seed)
numpy.random.seed(identical_seed)
random.seed(identical_seed)
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
Tips:
- 在使用ASP对一个新的(未经过稀疏的)推理模型启用结构化稀疏时需要同时调用
init_model_for_pruning
和compute_sparse_masks
方法。 init_model_for_pruning
会为模型层添加新的mask buffer
,用于保存compute_sparse_masks
生成的mask,因此调用了compute_sparse_masks
后的模型的state_dict
会比之前多出一些数据,这些数据均以_mma_mask
结尾的名字进行命名。- 对于已经使用ASP enable了结构化稀疏的模型,在保存后重新加载时,需要先创建一个新的模型,并调用
init_model_for_pruning
方法为模型添加mask buffer后再load模型的state_dict
,否则因为新模型的state_dict
和之前保存的state_dict
不同而报错。
Example:
写了一个简单的Conv-FC网络,训练后使用ASP进行剪枝,随后再次进行训练
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
from apex.contrib.sparsity import ASP# 定义卷积神经网络模型
class ConvNet(nn.Module):def __init__(self):super(ConvNet, self).__init__()self.conv1 = nn.Conv2d(1, 16, 3, padding=1)self.relu1 = nn.ReLU()self.pool1 = nn.MaxPool2d(2, 2)self.conv2 = nn.Conv2d(16, 32, 3, padding=1)self.relu2 = nn.ReLU()self.pool2 = nn.MaxPool2d(2, 2)self.fc1 = nn.Linear(32 * 7 * 7, 128)self.relu3 = nn.ReLU()self.fc2 = nn.Linear(128, 10)self.sig = nn.Sigmoid()def forward(self, x):x = self.pool1(self.relu1(self.conv1(x)))x = self.pool2(self.relu2(self.conv2(x)))x = x.view(-1, 32 * 7 * 7)x = self.relu3(self.fc1(x))x = self.fc2(x)x = self.sig(x)return xdef train_loop(model, optimizer, criterion):num_epochs = 1for epoch in range(num_epochs):running_loss = 0.0for i, data in enumerate(trainloader, 0):inputs, labels = data[0].to(device), data[1].to(device)optimizer.zero_grad()outputs = model(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()running_loss += loss.item()if i % 100 == 99:print(f'Epoch [{epoch+1}/{num_epochs}], Batch [{i+1}/{len(trainloader)}], Loss: {running_loss/100:.4f}')running_loss = 0.0def val(model):correct = 0total = 0model.eval()with torch.no_grad():for images, labels in testloader:images, labels = images.to(device), labels.to(device)outputs = model(images)_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()accuracy = correct / total * 100print("Test Accuracy :{}%".format(accuracy))return accuracydef main():# 训练网络print('Begin to train the dense network!')train_loop(model, optimizer, criterion)print('Finish training the dense network!')accuracy_dense = val(model)print('The accuracy of the trained dense network is : {}'.format(accuracy_dense))torch.save(model.state_dict(), 'model_weights.pth')ASP.prune_trained_model(model, optimizer)accuracy_sparse = val(model)print('The accuracy of the truned network is : {}'.format(accuracy_sparse))print('Begin to train the sparse network!')train_loop(model, optimizer, criterion)print('Finish training the sparse network!')accuracy_sparse = val(model)print('The accuracy of the trained sparse network is : {}'.format(accuracy_sparse))torch.save(model.state_dict(), 'model_weights_sparse.pth')print('Training finished!')if __name__ == '__main__':transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5,), (0.5,))])trainset = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform)trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)testset = torchvision.datasets.MNIST(root='./data', train=False, download=True, transform=transform)testloader = torch.utils.data.DataLoader(testset, batch_size=64, shuffle=False)device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')model = ConvNet().to(device)print('original weights has been saved!')criterion = nn.CrossEntropyLoss()optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)main()
运行结果
root:/home/shanlin/cnn_demo# python train.py
Found permutation search CUDA kernels
[ASP][Info] permutation_search_kernels can be imported.
original weights has been saved!
Begin to train the dense network!
The accuracy of the trained dense network is : 94.77...The accuracy of the truned network is : 94.15...The accuracy of the trained sparse network is : 96.6
Training finished!
root:/home/shanlin/cnn_demo#
可以看出,第一次训练后accuracy达到了94.77,剪枝后下降到了94.15,再次训练后重新上升到了96.6,比第一次训练还高,应该是因为模型是随便写的且数据集太简单的原因,
相关文章:

英伟达结构化剪枝工具Nvidia Apex Automatic Sparsity [ASP](1)——使用方法
英伟达结构化剪枝工具Nvidia Apex Automatic Sparsity [ASP](1)——使用方法 Apex是Nvdia维护的pytorch工具库,包括混合精度训练和分布式训练,Apex的目的是为了让用户能够更早的使用上这些“新鲜出炉”的训练工具。ASP࿰…...

接口测试,负载测试,并发测试,压力测试区别
接口测试 1.定义:接口测试是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。测试的重点是要检查数据的交换,传递和控制管理过程,以及系统间的相互逻辑依赖关系等。 2.目的…...

WebRTC +Signal + ICE
在 WebRTC 中,ICE(Interactive Connectivity Establishment)服务是用于解决网络地址转换(NAT)和防火墙障碍的关键组件。以下是一些常见的开源 ICE 服务框架,可以用于搭建 ICE 服务器来支持 WebRTC 连接&…...

循环内的try-catch 跟循环外的try-catch有什么不一样
起因:一位面试管突然问了这么一道基础的面试题,反而秀了面试者一脸,经常用的却被问到时不知道怎么回答,所以我们平时在写代码的时候,要多注意细节跟原理。也许你不服:不就是先这样,再那样&#…...

C语言实现Java三大特性
// 前言 面向对象的java语言有着多种设计模式与特性。比如封装、继承、多态等等。 在这篇文章中,我会使用java的代码思路,实现C语言版的JAVA三大特性。 并从写代码的角度,从0开始构建。 定义结构体(对象) 设计了一…...

GBU812-ASEMI新能源专用整流桥GBU812
编辑:ll GBU812-ASEMI新能源专用整流桥GBU812 型号:GBU812 品牌:ASEMI 封装:GBU-4 恢复时间:>50ns 正向电流:80A 反向耐压:1200V 芯片个数:4 引脚数量ÿ…...

数据结构,线性表与线性结构关系,顺序表与顺序结构关系,线性表与顺序表关系
学习数据结构会出现很多的概念如顺序结构,非线性结构,顺序表,顺序结构,顺序表,链表,栈,队列,堆等。今天来小讲以下其中的线性表与线性结构,顺序表与顺序结构的关系。 在数…...

Bigemap Pro国产基础软件介绍——一款多源数据处理软件
一、软件简介 Bigemap Pro是由成都比格图数据处理有限公司(下称”BIGEMAP”)开发和发行的国产大数据处理基础软件。Bigemap Pro是在BIGEMAP GIS Office基础上,经过十年的用户积累与反馈和技术更新迭代出的新一代基础软件产品。Bigemap Pro国产基础软件集成了数据采…...

算法练习Day49|● 121. 买卖股票的最佳时机 ● 122.买卖股票的最佳时机II
LeetCode: 121. 买卖股票的最佳时机 121. 买卖股票的最佳时机 - 力扣(LeetCode) 1.思路 暴力解法、贪心也算比较符合思维,动规不容易想到,且状态处理不易处理 股票每天的状态为持有或不持有:声明dp数组:…...

【Android Framework (十二) 】- 智能硬件设备开发
文章目录 前言智能硬件的定义与应用智能硬件产品开发流程智能硬件开发所涉及的技术体系概述关于主板选型主板CPU芯片的选择关于串口通信 总结 前言 针对我过往工作经历,曾在一家智能科技任职Android开发工程师,简单介绍下关于任职期间接触和开发过的一些…...

若依框架给字典字段新增color值,并且实现下拉列表选项进行颜色设置
首先获取所要新增的字典,并且根据字典的value值选取对应的颜色参数 this.getDicts("risk_level").then(response > {const color {mild:#F1F4BD,moderate:#EEC920,severe:#FF6C0D,very_severe:#FF0000,no_harm:green};const res response.data.map(…...

JDK 8 升级 JDK 17 全流程教学指南
JDK 8 升级 JDK 17 首先已有项目升级是会经历一个较长的调试和自测过程来保证允许和兼容没有问题。先说几个重要的点 遇到问题别放弃仔细阅读报错,精确到每个单词每一行,不是自己项目的代码也要点进去看看源码到底是为啥报错明确你项目引入的包&#x…...

Docker 网络之 ipvlan 和 macvlan
Docker ipvlan 和 macvlan 引言 本文讲解了Docker 网络模式中的 ipvlan 和 macvlan 的区别,目前自己在生产环境中使用的 ipvlan 模式非常问题.也解决了实际业务问题. IPvlan L2 mode example ipvlan 无需网卡混杂模式 , 运行如下命令后可以生成一个 vlan 子接口 , 会和主网卡…...

【Rust】Rust学习 第十三章Rust 中的函数式语言功能:迭代器与闭包
Rust 的设计灵感来源于很多现存的语言和技术。其中一个显著的影响就是 函数式编程(functional programming)。函数式编程风格通常包含将函数作为参数值或其他函数的返回值、将函数赋值给变量以供之后执行等等。 更具体的,我们将要涉及&#…...

【Linux操作系统】详解Linux系统编程中的管道进程通信
在Linux系统编程中,管道是一种常用的进程间通信方式。它可以实现父子进程之间或者兄弟进程之间的数据传输。本文将介绍如何使用管道在Linux系统中进行进程通信,并给出相应的代码示例。 文章目录 1. 管道的概念2. 管道的创建和使用2.1 原型2.2 示例 3. 父…...

【Redis从头学-4】Redis中的String数据类型实战应用场景之验证码、浏览量、点赞量、Json格式存储
🧑💻作者名称:DaenCode 🎤作者简介:啥技术都喜欢捣鼓捣鼓,喜欢分享技术、经验、生活。 😎人生感悟:尝尽人生百味,方知世间冷暖。 📖所属专栏:Re…...

linux 统计命令
统计命令 使用wc来进行统计 # wc [选项] 文件名wc -l a 2 awc -w a 8 a---------------l 统计行数-w 统计单词数-m 统计字符数-c 统计字节数 https://zhhll.icu/2021/linux/基础/统计命令/ 本文由 mdnice 多平台发布...

docker部署springboot应用
一、下载安装docker curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun 启动:systemctl start docker 二、配置国内镜像源 (1)在/etc/docker目录中添加daemon.json文件,内容如下: { …...

YOLO v5、v7、v8 模型优化
YOLO v5、v7、v8 模型优化 魔改YOLOyaml 文件解读模型选择在线做数据标注 YOLO算法改进YOLOv5yolo.pyyolov5.yaml更换骨干网络之 SwinTransformer更换骨干网络之 EfficientNet优化上采样方式:轻量化算子CARAFE 替换 传统(最近邻 / 双线性 / 双立方 / 三线…...

回归预测 | MATLAB实现SSA-BP麻雀搜索算法优化BP神经网络多输入单输出回归预测(多指标,多图)
回归预测 | MATLAB实现SSA-BP麻雀搜索算法优化BP神经网络多输入单输出回归预测(多指标,多图) 目录 回归预测 | MATLAB实现SSA-BP麻雀搜索算法优化BP神经网络多输入单输出回归预测(多指标,多图)效果一览基本…...

QT的mysql(数据库)最佳实践和常见问题解答
涉及到数据库,首先安利一个软件Navicat Premium,用来查询数据库很方便 QMysql驱动是Qt SQL模块使用的插件,用于与MySQL数据库进行通信。要编译QMysql驱动,您需要满足以下条件: 您需要安装MySQL的客户端库和开发头文件…...

使用PyMuPDF库的PDF合并和分拆程序
PDF工具应用程序是一个使用wxPython和PyMuPDF库编写的简单工具,用于合并和分拆PDF文件。它提供了一个用户友好的图形界面,允许用户选择源文件夹和目标文件夹,并对PDF文件进行操作。 C:\pythoncode\blog\pdfmergandsplit.py 功能特点 选择文…...

Data Abstract for .NET and Delphi Crack
Data Abstract for .NET and Delphi Crack .NET和Delphi的数据摘要是一套或RAD工具,用于在.NET、Delphi和Mono中编写多层解决方案。NET和Delphi的数据摘要是一个套件,包括RemObjects.NET和Delphi版本的数据摘要。RemObjects Data Abstract允许您创建访问…...

Eclipse集成MapStruct
Eclipse集成MapStruct 在Eclipse中添加MapStruct依赖配置Eclipse支持MapStruct①安装 m2e-aptEclipse Marketplace的方式安装Install new software的方式安装(JDK8用到) ②添加到pom.xml 今天拿到同事其他项目的源码,导入并运行的时候抛出了异…...

采用pycharm在虚拟环境使用pyinstaller打包python程序
一年多以前,我写过一篇博客描述了如何虚拟环境打包,这一次有所不同,直接用IDE pycharm构成虚拟环境并运行pyinstaller打包 之前的博文: 虚拟环境venu使用pyinstaller打包python程序_伊玛目的门徒的博客-CSDN博客 第一步…...

Rx.NET in Action 中文介绍 前言及序言
Rx 处理器目录 (Catalog of Rx operators) 目标可选方式Rx 处理器(Operator)创建 Observable Creating Observables直接创建 By explicit logicCreate Defer根据范围创建 By specificationRangeRepeatGenerateTimerInterval Return使用预设 Predefined primitivesThrow …...

Azure Blob存储使用
创建存储账户,性能选择标准即可,冗余选择本地冗余存储即可 容器选择类别选择专用即可 可以上传文件到blob中 打开文件可以看到文件的访问路径 4.编辑中可以修改文件 复制链接,尝试访问,可以看到没有办法访问,因为创建容器的时候选…...

mysql、redis面试题
mysql 相关 1、数据库优化查询方法 外键、索引、联合查询、选择特定字段等等2、简述mysql和redis区别 redis: 内存型非关系数据库,数据保存在内存中,速度快mysql:关系型数据库,数据保存在磁盘中,检索的话&…...

22、touchGFX学习Model-View-Presenter设计模式
touchGFX采用MVP架构,如下所示: 本文界面如下所示: 本文将实现两个操作: 1、触摸屏点击开关按键实现打印开关显示信息,模拟开关灯效果 2、板载案按键控制触摸屏LED灯的显示和隐藏 一、触摸屏点击开关按键实现打印开…...