极智AI | 三谈昇腾CANN量化

本文涉及的产品
视觉智能开放平台,视频资源包5000点
视觉智能开放平台,图像资源包5000点
视觉智能开放平台,分割抠图1万点
简介: 大家好,我是极智视界,本文介绍一下 三谈昇腾CANN量化。

大家好,我是极智视界,本文介绍一下 三谈昇腾CANN量化

在之前我已经从原理和命令行的量化执行方面介绍了昇腾CANN的量化,有兴趣的同学可以去查看,附上:

这里我们来谈谈CANN量化的Python API,当然这跟命令行的量化执行一样,功能上也是进行量化操作。

先来一个resnet101的python量化的完整代码,然后再慢慢解释:

import os
import argparse
import cv2
import numpy as np
import onnxruntime as ort
import amct_onnx as amct
PATH = os.path.realpath('./')
IMG_DIR = os.path.join(PATH, 'data/images')
LABLE_FILE = os.path.join(IMG_DIR, 'image_label.txt')
PARSER = argparse.ArgumentParser(description='amct_onnx resnet-101 quantization sample.')
PARSER.add_argument('--nuq', dest='nuq', action='store_true', help='whether use nuq')
ARGS = PARSER.parse_args()
if ARGS.nuq:
    OUTPUTS = os.path.join(PATH, 'outputs/nuq')
else:
    OUTPUTS = os.path.join(PATH, 'outputs/calibration')
TMP = os.path.join(OUTPUTS, 'tmp')
def get_labels_from_txt(label_file):
    """Read all images' name and label from label_file"""
    images = []
    labels = []
    with open(label_file, 'r') as file:
        lines = file.readlines()
        for line in lines:
            images.append(line.split(' ')[0])
            labels.append(int(line.split(' ')[1]))
    return images, labels
def prepare_image_input(
    images, height=256, width=256, crop_size=224, mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]):
    """Read image files to blobs [batch_size, 3, 224, 224]"""
    input_tensor = np.zeros((len(images), 3, crop_size, crop_size), np.float32)
    imgs = np.zeros((len(images), 3, height, width), np.float32)
    for index, im_file in enumerate(images):
        im_data = cv2.imread(im_file)
        im_data = cv2.resize(im_data, (256, 256), interpolation=cv2.INTER_CUBIC)
        cv2.cvtColor(im_data, cv2.COLOR_BGR2RGB)
        imgs[index, :, :, :] = im_data.transpose(2, 0, 1).astype(np.float32)
    h_off = int((height - crop_size) / 2)
    w_off = int((width - crop_size) / 2)
    input_tensor = imgs[:, :, h_off: (h_off + crop_size), w_off: (w_off + crop_size)]
    # trans uint8 image data to float
    input_tensor /= 255
    # do channel-wise reduce mean value
    for channel in range(input_tensor.shape[1]):
        input_tensor[:, channel, :, :] -= mean[channel]
    # do channel-wise divide std
    for channel in range(input_tensor.shape[1]):
        input_tensor[:, channel, :, :] /= std[channel]
    return input_tensor
def img_postprocess(probs, labels):
    """Do image post-process"""
    # calculate top1 and top5 accuracy
    top1_get = 0
    top5_get = 0
    prob_size = probs.shape[1]
    for index, label in enumerate(labels):
        top5_record = (probs[index, :].argsort())[prob_size - 5: prob_size]
        if label == top5_record[-1]:
            top1_get += 1
            top5_get += 1
        elif label in top5_record:
            top5_get += 1
    return float(top1_get) / len(labels), float(top5_get) / len(labels)
def onnx_forward(onnx_model, batch_size=1, iterations=160):
    """forward"""
    ort_session = ort.InferenceSession(onnx_model, amct.AMCT_SO)
    images, labels = get_labels_from_txt(LABLE_FILE)
    images = [os.path.join(IMG_DIR, image) for image in images]
    top1_total = 0
    top5_total = 0
    for i in range(iterations):
        input_batch = prepare_image_input(images[i * batch_size: (i + 1) * batch_size])
        output = ort_session.run(None, {'input': input_batch})
        top1, top5 = img_postprocess(output[0], labels[i * batch_size: (i + 1) * batch_size])
        top1_total += top1
        top5_total += top5
        print('****************iteration:{}*****************'.format(i))
        print('top1_acc:{}'.format(top1))
        print('top5_acc:{}'.format(top5))
    print('******top1:{}'.format(top1_total / iterations))
    print('******top5:{}'.format(top5_total / iterations))
    return top1_total / iterations, top5_total / iterations
def main():
    """main"""
    model_file = './model/resnet-101.onnx'
    print('[INFO] Do original model test:')
    ori_top1, ori_top5 = onnx_forward(model_file, 32, 5)
    config_json_file = os.path.join(TMP, 'config.json')
    skip_layers = []
    batch_num = 1
    if ARGS.nuq:
        amct.create_quant_config(
            config_file=config_json_file, model_file=model_file, skip_layers=skip_layers, batch_num=batch_num,
            activation_offset=True, config_defination='./src/nuq_conf/nuq_quant.cfg')
    else:
        amct.create_quant_config(
            config_file=config_json_file, model_file=model_file, skip_layers=skip_layers, batch_num=batch_num,
            activation_offset=True, config_defination=None)
    # Phase1: do conv+bn fusion, weights calibration and generate
    #         calibration model
    scale_offset_record_file = os.path.join(TMP, 'record.txt')
    modified_model = os.path.join(TMP, 'modified_model.onnx')
    amct.quantize_model(
        config_file=config_json_file, model_file=model_file, modified_onnx_file=modified_model,
        record_file=scale_offset_record_file)
    onnx_forward(modified_model, 32, batch_num)
    # Phase3: save final model, one for onnx do fake quant test, one
    #         deploy model for ATC
    result_path = os.path.join(OUTPUTS, 'resnet-101')
    amct.save_model(modified_model, scale_offset_record_file, result_path)
    # Phase4: run fake_quant model test
    print('[INFO] Do quantized model test:')
    quant_top1, quant_top5 = onnx_forward('%s_%s' % (result_path, 'fake_quant_model.onnx'), 32, 5)
    print('[INFO] ResNet101 before quantize top1:{:>10} top5:{:>10}'.format(ori_top1, ori_top5))
    print('[INFO] ResNet101 after quantize  top1:{:>10} top5:{:>10}'.format(quant_top1, quant_top5))
if __name__ == '__main__':
    main()

关于量化数据集的制作同样可以参考《再谈昇腾CANN量化》里的方法。

以上完整的量化过程,有三个主要的python接口,分别是:create_quant_configquantize_modelsave_model,来分别介绍一下。

create_quant_config的作用是根据graph的结构找到所有可量化的层,自动生成量化配置文件,并将可量化层的量化配置因子写入文件,函数接口如下:

create_quant_config(config_file, model_file, skip_layers=None, batch_unm=1, activation_offset=True, config_defination=None, updated_model=None)

其中:

这个函数会输出一个json格式的量化配置文件,一个简单的调用方法如下:

import amct_onnx
model_file = "resnet101.onnx"
# 生成量化配置文件
amct_onnx.create_quant_config(config_file="config.json",
                             model_file=model_file,
                             skip_layers=None,
                             batch_num=1,
                             activation_offset=True)

接着咱们来看quantize_model,顾铭思议,这个接口就是在做量化。将输入的待量化的graph结构按照create_quant_config生成的量化配置文件进行量化处理,在传入的graph结构中插入量化算子如quant/dequant,然后生成量化因子记录文件record_file,返回修改后的onnx量化校准模型。函数的接口如下:

quantize_model(config_file, model_file, modified_onnx_file, record_file)

其中:

这个函数会返回modified_onnx_file待量化模型record_file量化因子记录文件,以用于下一步生成量化模型。一个简单的调用示例如下:

import amct_onnx
model_file = "resnet101.onnx"
scale_offset_record_file = os.path.join(TMP, 'scale_offset_record.txt')
modified_model = os.path.join(TVM, 'modified_model.onnx')
config_file = "config.json"
# 量化
amct_onnx.quantize_model(config_file,
                        model_file,
                        modified_model,
                        scale_offset_record_file)

最后来看save_model,这个函数的功能是根据量化因子文件record_file和修改后的量化模型modified_model,插入AscendQuantAscendDequant等量化相关算子,生成可以在onnx runtime环境进行精度仿真的face_quant模型 以及 可以在昇腾上推理的deploy模型。函数接口如下:

save_model(modified_onnx_file, record_file, save_path)

其中:

生成的精度仿真模型和推理模型在结构上有什么区别呢,来看:

一个简单的调用示例如下:

import amct_onnx
# 保存量化模型
amct_onnx.save_model(modified_onnx_file="modified_model.onnx",
                    record_file="scale_offset_record_file.txt",
                    save_path="res")

这样整个CANN量化的Python API实现方式就介绍完了。


好了,以上分享三谈昇腾CANN量化,希望我的分享能对你的学习有一点帮助。


logo_show.gif

相关文章
|
14天前
|
机器学习/深度学习 存储 人工智能
【AI系统】感知量化训练 QAT
本文介绍感知量化训练(QAT)流程,旨在减少神经网络从FP32量化至INT8时的精度损失。通过在模型中插入伪量化节点(FakeQuant)模拟量化误差,并在训练中最小化这些误差,使模型适应量化环境。文章还探讨了伪量化节点的作用、正向与反向传播处理、TensorRT中的QAT模型高效推理,以及QAT与PTQ的对比,提供了实践技巧,如从良好校准的PTQ模型开始、采用余弦退火学习率计划等。
53 2
【AI系统】感知量化训练 QAT
|
14天前
|
机器学习/深度学习 存储 人工智能
【AI系统】训练后量化与部署
本文详细介绍了训练后量化技术,涵盖动态和静态量化方法,旨在将模型权重和激活从浮点数转换为整数,以优化模型大小和推理速度。通过KL散度等校准方法和量化粒度控制,文章探讨了如何平衡模型精度与性能,同时提供了端侧量化推理部署的具体实现步骤和技术技巧。
40 1
【AI系统】训练后量化与部署
|
16天前
|
机器学习/深度学习 人工智能 调度
【AI系统】CANN 算子类型
本文介绍了算子的基本概念及其在编程和数学中的作用,重点探讨了CANN算子在AI编程和神经网络中的应用,特别是华为CANN算子在AI CPU上的架构和开发要求。CANN是华为推出的异构计算架构,旨在优化AI处理器的计算效率,支持多种AI框架,涵盖AI Core和AI CPU算子,以适应不同类型的计算需求。文中还详细说明了AI CPU算子的开发流程和适用场景,为开发者提供了宝贵的指导。
35 2
|
16天前
|
机器学习/深度学习 人工智能 API
【AI系统】昇腾异构计算架构 CANN
本文介绍了昇腾 AI 异构计算架构 CANN,涵盖硬件层面的达·芬奇架构和软件层面的全栈支持,旨在提供高性能神经网络计算所需的硬件基础和软件环境。通过多层级架构,CANN 实现了高效的 AI 应用开发与性能优化,支持多种主流 AI 框架,并提供丰富的开发工具和接口,助力开发者快速构建和优化神经网络模型。
37 1
|
22天前
|
存储 人工智能 编译器
【AI系统】昇腾数据布局转换
华为昇腾NPU采用独特的NC1HWC0五维数据格式,旨在优化AI处理器的矩阵乘法运算和访存效率。此格式通过将C维度分割为C1份C0,适应达芬奇架构的高效计算需求,支持FP16和INT8数据类型。此外,昇腾还引入了NZ分形格式,进一步提升数据搬运和矩阵计算效率。AI编译器通过智能布局转换,确保在不同硬件上达到最优性能。
46 3
|
22天前
|
存储 机器学习/深度学习 人工智能
【AI系统】昇腾 AI 核心单元
本文深入解析了华为昇腾AI处理器的核心——AI Core及其达芬奇架构。AI Core采用特定域架构(DSA),专为深度学习算法优化,通过矩阵、向量和标量计算单元的高效协作,实现了对深度学习算法的加速。文章详细介绍了AI Core的计算单元、存储系统及控制单元的设计,展示了其如何通过优化数据通路和控制流程,显著提升计算性能。
47 3
|
22天前
|
存储 机器学习/深度学习 人工智能
【AI系统】昇腾 AI 处理器
本文介绍华为昇腾AI处理器的架构与卷积加速原理,基于达芬奇架构设计,支持云边端一体化解决方案,具备高能效比和强大的3D Cube矩阵计算单元。文章详细解析了昇腾AI处理器的核心组件及其高效的数据处理机制,旨在通过软硬件优化实现高效的卷积计算加速。
62 2
|
22天前
|
人工智能 atlas 开发工具
【AI系统】昇腾 AI 架构介绍
昇腾计算产业基于华为昇腾系列处理器,涵盖硬件、基础软件、应用使能等,构建全栈AI计算基础设施。华为通过开放硬件、开源软件,支持多框架,推动AI技术在端、边、云的广泛应用,促进AI产业生态繁荣。
48 1
|
15天前
|
人工智能 PyTorch 算法框架/工具
【AI系统】昇腾推理引擎 MindIE
本文详细介绍华为昇腾推理引擎 MindIE,涵盖其基本介绍、关键功能特性及三大组件:MindIE-Service、MindIE-Torch 和 MindIE-RT。文章深入探讨了各组件在服务化部署、大模型推理和推理运行时方面的功能和应用场景,旨在帮助读者全面了解 MindIE 如何支持 AI 业务的高效运行和模型的快速部署。
34 0
|
3月前
|
人工智能 自然语言处理 运维
钉钉x昇腾:用AI一体机撬动企业数字资产智能化
大模型在过去两年迅速崛起,正加速应用于各行各业。尤其在办公领域,其主要模态——文字和图片,成为了数字化办公的基础内容,催生了公文写作、表格生成、文本翻译等多种应用场景,显著提升了工作效率。然而,AI引入办公场景也带来了数据安全与成本等问题。为此,钉钉与昇腾联合推出的“钉钉专属AI一体机解决方案”,通过本地化部署解决了数据安全、成本高昂及落地难等痛点,实现了从硬件到软件的深度协同优化,为企业提供了开箱即用的AI服务,推动了办公场景的智能化升级。
155 11

热门文章

最新文章

下一篇
DataWorks