AIMET API 文档(3)

本文介绍了AIMET对PyTorch模型的相关功能。AIMET提供模型验证器实用程序,可检查模型是否满足应用条件,还展示了修复未通过验证模型的方法。此外,还介绍了AIMET PyTorch定量分析器API,能分析模型量化敏感层,执行每层敏感性和MSE分析等,并给出代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


1.1.4 模型验证实用程序

AIMET 提供了模型验证器实用程序来帮助检查 AIMET 功能是否可以应用于 Pytorch 模型。 模型验证器当前检查以下条件:

  • 没有模块被重用
  • 操作具有与其关联的模块,并且未定义为功能(不包括一组已知操作)

在本节中,我们将介绍未通过验证检查的模型,并展示如何运行模型验证器,以及如何修复模型以使验证检查通过。

示例 1:具有重用模块的模型

我们从以下模型开始,其中包含两个共享同一模块实例的 relu 模块。

class ModelWithReusedNodes(torch.nn.Module):
    """ Model that reuses a relu module. Expects input of shape (1, 3, 32, 32) """

    def __init__(self):
        super(ModelWithReusedNodes, self).__init__()
        self.conv1 = torch.nn.Conv2d(3, 8, kernel_size=2, stride=2, padding=2, bias=False)
        self.bn1 = torch.nn.BatchNorm2d(8)
        self.relu1 = torch.nn.ReLU(inplace=True)
        self.linear = torch.nn.Linear(2592, 10)

    def forward(self, *inputs):
        x = self.conv1(inputs[0])
        x = self.relu1(x)
        x = self.bn1(x)
        x = self.relu1(x)
        x = x.view(x.size(0), -1)
        x = self.linear(x)
        return x

导入模型验证器:

from aimet_torch.model_validator.model_validator import ModelValidator

通过传入模型以及模型输入来在模型上运行模型验证器:

def validate_example_model():

    # Load the model to validate
    model = ModelWithReusedNodes()

    # Output of ModelValidator.validate_model will be True if model is valid, False otherwise
    ModelValidator.validate_model(model, model_input=torch.rand(1, 3, 32, 32))

对于模型上运行的每次验证检查,都会显示记录器打印:

Utils - INFO - Running validator check <function validate_for_reused_modules at 0x7f127685a598>

如果验证检查发现模型有任何问题,日志将包含有关如何解决模型的信息:

Utils - WARNING - The following modules are used more than once in the model: ['relu1']
AIMET features are not designed to work with reused modules. Please redefine your model to use distinct modules for
each instance.

最后,在验证结束时,将记录任何失败的检查:

Utils - INFO - The following validator checks failed:
Utils - INFO -     <function validate_for_reused_modules at 0x7f127685a598>

在这种情况下,validate_for_reused_modules 检查通知 relu1 模块在模型中被多次使用。 我们通过为每种用途定义一个单独的 relu 实例来重写模型:

class ModelWithoutReusedNodes(torch.nn.Module):
    """ Model that is fixed to not reuse modules. Expects input of shape (1, 3, 32, 32) """

    def __init__(self):
        super(ModelWithoutReusedNodes, self).__init__()
        self.conv1 = torch.nn.Conv2d(3, 8, kernel_size=2, stride=2, padding=2, bias=False)
        self.bn1 = torch.nn.BatchNorm2d(8)
        self.relu1 = torch.nn.ReLU(inplace=True)
        self.relu2 = torch.nn.ReLU(inplace=True)
        self.linear = torch.nn.Linear(2592, 10)

    def forward(self, *inputs):
        x = self.conv1(inputs[0])
        x = self.relu1(x)
        x = self.bn1(x)
        x = self.relu2(x)
        x = x.view(x.size(0), -1)
        x = self.linear(x)
        return x

现在,重新运行模型验证器后,所有检查都通过了:

Utils - INFO - Running validator check <function validate_for_reused_modules at 0x7ff577373598>
Utils - INFO - Running validator check <function validate_for_missing_modules at 0x7ff5703eff28>
Utils - INFO - All validation checks passed.

示例 2:具有泛函的模型

我们从以下模型开始,该模型在前向传递中使用了一个torch线性功能层:

class ModelWithFunctionalLinear(torch.nn.Module):
    """ Model that uses a torch functional linear layer. Expects input of shape (1, 3, 32, 32) """

    def __init__(self):
        super(ModelWithFunctionalLinear, self).__init__()
        self.conv1 = torch.nn.Conv2d(3, 8, kernel_size=2, stride=2, padding=2, bias=False)
        self.bn1 = torch.nn.BatchNorm2d(8)
        self.relu1 = torch.nn.ReLU(inplace=True)
        self.relu2 = torch.nn.ReLU(inplace=True)

    def forward(self, *inputs):
        x = self.conv1(inputs[0])
        x = self.relu1(x)
        x = self.bn1(x)
        x = self.relu2(x)
        x = x.view(x.size(0), -1)
        x = F.linear(x, torch.randn(10, 2592))
        return x

运行模型验证器显示 validate_for_missing_modules 检查失败:

Utils - INFO - Running validator check <function validate_for_missing_modules at 0x7f9dd9bd90d0>
Utils - WARNING - Ops with missing modules: ['matmul_8']
This can be due to several reasons:
1. There is no mapping for the op in ConnectedGraph.op_type_map. Add a mapping for ConnectedGraph to recognize and
be able to map the op.
2. The op is defined as a functional in the forward function, instead of as a class module. Redefine the op as a
class module if possible. Else, check 3.
3. This op is one that cannot be defined as a class module, but has not been added to ConnectedGraph.functional_ops.
Add to continue.
Utils - INFO - The following validator checks failed:
Utils - INFO -      <function validate_for_missing_modules at 0x7f9dd9bd90d0>

检查已将 matmul_8 识别为缺少 pytorch 模块的操作。 在这种情况下,这是由于日志中的原因#2,其中该层已被定义为前向函数中的函数。 为了解决这个问题,我们通过将层定义为模块来重写模型。

class ModelWithoutFunctionalLinear(torch.nn.Module):
    """ Model that is fixed to use a linear module instead of functional. Expects input of shape (1, 3, 32, 32) """

    def __init__(self):
        super(ModelWithoutFunctionalLinear, self).__init__()
        self.conv1 = torch.nn.Conv2d(3, 8, kernel_size=2, stride=2, padding=2, bias=False)
        self.bn1 = torch.nn.BatchNorm2d(8)
        self.relu1 = torch.nn.ReLU(inplace=True)
        self.relu2 = torch.nn.ReLU(inplace=True)
        self.linear = torch.nn.Linear(2592, 10)
        with torch.no_grad():
            self.linear.weight = torch.nn.Parameter(torch.randn(10, 2592))

    def forward(self, *inputs):
        x = self.conv1(inputs[0])
        x = self.relu1(x)
        x = self.bn1(x)
        x = self.relu2(x)
        x = x.view(x.size(0), -1)
        x = self.linear(x)
        return x

1.1.5 AIMET PyTorch 定量分析器 API

AIMET PyTorch Quant Analyzer 分析 PyTorch 模型并指出模型中量化的敏感层。 它检查模型对权重和激活量化的敏感性,执行每层敏感性和 MSE 分析。 它还导出每层编码的最小和最大范围以及每层的统计直方图。

1.1.5.1 顶层API

class aimet_torch.quant_analyzer.QuantAnalyzer(model, dummy_input, forward_pass_callback, eval_callback, modules_to_ignore=None)[source]

QuantAnalyzer 工具提供

  1. 模型对权重和激活量化的敏感性
  2. 每层灵敏度分析
  3. 每层编码(最小 - 最大范围)

参数

  • model (Module) – 用于分析量化的 FP32 模型。
  • dummy_input (Union[Tensor, Tuple]) – 将输入传递给模型。
  • forward_pass_callback (CallbackFunc) – 用于模型校准的回调函数,只需在模型上运行前向传递即可计算编码(增量/偏移)。 此回调函数应使用代表性数据,并且应是整个训练/验证数据集(约 1000 个图像/样本)的子集。
  • eval_callback (CallbackFunc) – 用于确定模型性能的模型评估的回调函数。 此回调函数预计返回标量值,表示针对整个测试/评估数据集评估的模型性能。
  • modules_to_ignore (Optional[List[Module]]) – 从分析中排除某些模块。

analyze(quant_scheme=<QuantScheme.post_training_tf_enhanced: 2>, default_param_bw=8, default_output_bw=8, config_file=None, results_dir=‘./tmp/’)[source]

分析模型的量化并通过执行来指出模型的敏感部分/热点

  1. 模型对量化的敏感性,
  2. 通过启用和禁用定量包装器来执行每层敏感性分析,
  3. 导出每层编码的最小 - 最大范围,
  4. 当量化方案为 TF 增强时导出每层统计直方图 (PDF),
  5. 每层MSE分析

参数:

  • quant_scheme (QuantScheme) – 量化方案。 支持的值为 QuantScheme.post_training_tf 或 QuantScheme.post_training_tf_enhanced。
  • default_param_bw (int) – 用于量化图层参数的默认位宽 (4-31)。
  • default_output_bw (int) – 用于量化层输入和输出的默认位宽 (4-31)。
  • config_file (Optional[str]) – 模型量化器的配置文件的路径。
  • results_dir (str) – 保存结果的目录。

enable_per_layer_mse_loss(unlabeled_dataset_iterable, num_batches)[source]

启用每层 MSE 损失分析。
参数:

  • unlabeled_dataset_iterable (Union[DataLoader[+T_co], Collection[+T_co]]) – 迭代未标记数据集的集合(即可使用 len 进行迭代)。 该迭代产生的值预计能够直接传递给模型。
  • num_batches (int) – 批次数。 建议使用大约 256 个样本/图像,因此如果数据加载器的批次大小为 64,则 4 个批次将导致 256 个样本/图像。
1.1.5.2 代码示例

所需引入

from typing import Any
import torch
from torchvision import models
from aimet_common.defs import QuantScheme
from aimet_torch.model_preparer import prepare_model
from aimet_torch.quant_analyzer import QuantAnalyzer, CallbackFunc

准备前向传递回调

# NOTE: In the actual use cases, the users should implement this part to serve
#       their own goals if necessary.
def forward_pass_callback(model: torch.nn.Module, _: Any = None) -> None:
    """
    NOTE: This is intended to be the user-defined model calibration function.
    AIMET requires the above signature. So if the user's calibration function does not
    match this signature, please create a simple wrapper around this callback function.

    A callback function for model calibration that simply runs forward passes on the model to
    compute encoding (delta/offset). This callback function should use representative data and should
    be subset of entire train/validation dataset (~1000 images/samples).

    :param model: PyTorch model.
    :param _: Argument(s) of this callback function. Up to the user to determine the type of this parameter.
    E.g. could be simply an integer representing the number of data samples to use. Or could be a tuple of
    parameters or an object representing something more complex.
    """
    # User action required
    # User should create data loader/iterable using representative dataset and simply run
    # forward passes on the model.

准备 eval 回调

# NOTE: In the actual use cases, the users should implement this part to serve
#       their own goals if necessary.
def eval_callback(model: torch.nn.Module, _: Any = None) -> float:
    """
    NOTE: This is intended to be the user-defined model evaluation function.
    AIMET requires the above signature. So if the user's calibration function does not
    match this signature, please create a simple wrapper around this callback function.

    A callback function for model evaluation that determines model performance. This callback function is
    expected to return scalar value representing the model performance evaluated against entire
    test/evaluation dataset.

    :param model: PyTorch model.
    :param _: Argument(s) of this callback function. Up to the user to determine the type of this parameter.
    E.g. could be simply an integer representing the number of data samples to use. Or could be a tuple of
    parameters or an object representing something more complex.
    :return: Scalar value representing the model performance.
    """
    # User action required
    # User should create data loader/iterable using entire test/evaluation dataset, perform forward passes on
    # the model and return single scalar value representing the model performance.
    return .8

准备模型

    model = models.resnet18(pretrained=True).cuda().eval()
    input_shape = (1, 3, 224, 224)
    dummy_input = torch.randn(*input_shape).cuda()
    prepared_model = prepare_model(model)

创建 QuantAnalyzer 对象

    quant_analyzer = QuantAnalyzer(model=prepared_model,
                                   dummy_input=dummy_input,
                                   forward_pass_callback=forward_pass_callback_fn,
                                   eval_callback=eval_callback_fn)
    # Approximately 256 images/samples are recommended for MSE loss analysis. So, if the dataloader
    # has batch_size of 64, then 4 number of batches leads to 256 images/samples.
    quant_analyzer.enable_per_layer_mse_loss(unlabeled_dataset_iterable=unlabeled_data_loader, num_batches=4)

运行定量分析器

    quant_analyzer.analyze(quant_scheme=QuantScheme.post_training_tf_enhanced,
                           default_param_bw=8,
                           default_output_bw=8,
                           config_file=None,
                           results_dir="./quant_analyzer_results/")
### 六路灰度寻迹算法原理 六路灰度寻迹是指通过六个灰度传感器组成的阵列来实现路径跟踪的一种技术。这种技术的核心在于利用灰度传感器感知地面颜色的变化,从而判断机器人或设备相对于目标轨迹的位置偏差,并基于此调整运动方向。 #### 灰度传感器工作原理 灰度传感器的工作机制依赖于光线反射强度的不同。当传感器照射到黑色区域时,由于黑色吸光特性强,反射回来的光较少;而白色或其他浅色表面会反射较多的光。因此,灰度传感器能够区分不同颜色的地表[^3]。具体来说,在循迹过程中,如果传感器检测到的是黑线,则输出高电平;如果是白底,则输出低电平。 #### 数据采集与处理 对于六路灰度寻迹系统而言,通常将这六个传感器均匀分布在一个固定宽度上,覆盖整个赛道或者至少部分赛道范围。假设这些传感器按照顺序编号为S1至S6,那么可以根据各个传感器的状态组合得出当前车辆偏离中心的程度以及前进的方向指示: - 如果仅有中间某个特定编号如 S3 返回代表黑线存在的信号(即高电平),则说明此时车体基本处于理想直线行驶状态; - 当左侧几个连续传感器(S1,S2)感应到了黑线存在时表明车身已经偏向右侧需适当修正左转角度; - 反之亦然,若右边多个相邻探头发现障碍物则应往右调整姿态保持平衡稳定运行下去直到重新回到预定路线之上为止[^1]. #### 控制策略-PID控制的应用 为了更精确地完成上述提到的各种情况下的转向操作,可以引入PID控制器来进行闭环反馈调节过程中的参数优化设置.这里简单介绍一下如何构建这样一个控制系统: 给定期望值r(k)(比如让车子沿着既定轨道平稳移动),实际测量值得y(k)[也就是由那些安装好的光电元件所获取的信息],计算误差e(k)= r(k)- y(k).接着依据前面提及过的离散化后的表达式分别求取比例项P、积分项I还有微分D三个组成部分之后加权求和形成最终输出u(k): \[ u(k) = K_p e(k)+K_i \sum_{j=0}^{k}{e(j)}T_s+K_d\frac{e(k)-e(k-1)}{T_s}\] 其中\(K_p\) \(K_i\) 和\(K_d\) 分别表示各自对应的增益系数;Ts指的是采样间隔时间长度.[^2] 以上就是关于六通道类型的灰色级别追踪方法背后隐藏的一些基础知识要点概述. ```python def pid_control(error, prev_error, sum_error, kp, ki, kd, dt): """ 计算PID控制器的输出 参数: error (float): 当前误差 prev_error (float): 上一次误差 sum_error (float): 积累误差总和 kp (float): 比例增益 ki (float): 积分增益 kd (float): 微分增益 dt (float): 时间步长 返回: float: PID控制器输出 """ p_term = kp * error i_term = ki * sum_error * dt d_term = kd * (error - prev_error) / dt output = p_term + i_term + d_term return output ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值