---
title: ghostnet
canonical_url: "https://www.modelscope.cn/models/AIBSECO/ghostnet"
md_url: "https://www.modelscope.cn/models/AIBSECO/ghostnet.md"
repository: AIBSECO/ghostnet
last_updated: 2025-11-19
pipeline_tag: image-classification
tasks:
  - image-classification
library_name:
  - pytorch
frameworks:
  - Pytorch
downloads: 9
stars: 0
---

# ghostnet

> ghostnet - AIBSECO 在 ModelScope 开源的模型。1. 模型背景 GhostNet 是一款轻量级卷积神经网络模型，由 华为诺亚方舟实验室（Noah’s Ark Lab） 于 2020年在论文《GhostNet: More Features from Cheap Operations》中首次提出，并发表在 CVPR 2020…

- **Repository**: AIBSECO/ghostnet
- **Tasks**: image-classification
- **Downloads**: 9
- **Stars**: 0
- **Last updated**: 2025-11-19

Source: https://www.modelscope.cn/models/AIBSECO/ghostnet

---

# GhostNet图像分类模型

## 1. 方案简介

### 1.1 算法流程介绍

#### 1. 模型背景
**GhostNet** 是一款轻量级卷积神经网络模型，由 **华为诺亚方舟实验室（Noah’s Ark Lab）** 于 **2020年**在论文《GhostNet: More Features from Cheap Operations》中首次提出，并发表在 **CVPR 2020** 上。该模型旨在为**资源受限设备**（如移动终端、嵌入式系统、AI芯片等）提供**更高效率的神经网络结构**，在降低模型计算复杂度和参数规模的同时，尽可能保持较高的分类精度。GhostNet 针对传统卷积神经网络中的“计算冗余”问题提出了一种创新的解决方案：**Ghost Module（幽灵模块）**。研究者观察到，神经网络中许多特征图之间存在较强的冗余性，因此并不需要使用高成本的标准卷积操作来生成所有特征图。GhostNet 通过少量真实卷积生成部分“原始特征”，然后使用一系列**低成本的线性操作（如深度可分离卷积）**在这些原始特征的基础上“扩展”出更多“Ghost”特征图，从而大大减少计算量。

**GhostNet 的主要特点如下**：

- **参数量和计算量大幅减少**，特别适合部署在 FPGA、NPU 等定制硬件上；
- **兼容主流轻量化框架**（如 MobileNet、ShuffleNet 等），可作为替代结构无缝集成；
- **结构设计简单，易于硬件并行优化和流水线加速**；
- 在 ImageNet 等标准数据集上，GhostNet 在同等或更低计算开销下**实现了优于同类模型的分类精度**。

**GhostNet 击败了其他 SOTA 轻量级 CNN，例如 MobileNetV3 和 FBNet。**

![](./fig/flops_latency.png)

#### 2. 算法流程图
```mermaid
graph TD
    A[输入图像] --> B[前处理]
    B --> C[Stage1: 标准卷积]
    C --> D[Stage2-4: Ghost模块堆叠]
    D --> E[全局平均池化]
    E --> F[全连接层]
    F --> G[后处理]
```



#### 3. 前处理（Host端CPU处理）
**前处理流程**：

```mermaid
graph LR
    A[输入图像路径] --> B[图像加载]
    B --> C[尺寸变换]
    C --> D[张量转换]
    D --> E[DMA准备]

    subgraph 前处理流程
        B -->|cv::IMREAD_COLOR| B1["示例：/data/dog.jpg"]
        C --> C1[Resize短边224px] --> C2["示例：1280x720→256x256"]
        C2 --> C3[rCenterCrop] --> C4["示例：224x224"]
        D --> D1["数据类型转换 uint8→float32"]
        D1 --> D2["归一化 /255.0"]
        D2 --> D3["通道转换 BGR→RGB"]
        D3 --> D4["添加Batch维度 [1,3,224,224]"]
        E --> E1["配置DMA参数"] --> E2["Host→NPU数据传输"]
    end

    style B fill:#F8CECC,stroke:#B85450
    style C fill:#D5E8D4,stroke:#82B366
    style D fill:#DAE8FC,stroke:#6C8EBF
    style E fill:#FFF2CC,stroke:#D6B656
```

**关键操作**：

```cpp
PicPre img(img_path, cv::IMREAD_COLOR); // 图像加载
img.Resize(resize_hw, PicPre::SHORT_SIDE).rCenterCrop(crop_hw); // 调整尺寸+中心裁剪
Tensor img_tensor = CvMat2Tensor(img.dst_img, network); // OpenCV Mat转Tensor
dmaInit(run_sim, netinfo.ImageMake_on, img_tensor, device); // DMA传输初始化
```

**具体处理流程**：

1. **图像加载**：通过OpenCV读取原始图像（`cv::IMREAD_COLOR`保持RGB格式）
   - 示例：输入 `img_path` 为 `"/data/dog.jpg"`
2. **尺寸变换**：
   - `Resize`：将短边缩放到指定尺寸（如256px），保持长宽比
   - `rCenterCrop`：居中裁剪到模型输入尺寸（如224x224）
   - 示例：原始图像1280x720 → Resize为256x256 → 中心裁剪224x224
3. **张量转换**：
   - `CvMat2Tensor` 完成：
     - 数据类型转换（uint8 → float32）
     - 归一化（如除以255.0）
     - 通道顺序转换（BGR → RGB，若模型需要）
     - 添加Batch维度（shape变为[1,3,224,224]）
4. **DMA准备**：
   - `dmaInit` 配置DMA传输参数，将Tensor数据从Host内存复制到NPU设备内存

#### 4. 后处理（Host端CPU处理）

**后处理机制**：

```mermaid
graph LR
    A[NPU输出张量] --> B[数据回传]
    B --> C[结果解析]
    C --> D[概率计算]
    D --> E[结果筛选]
    E --> F[可视化处理]

    subgraph 后处理流程
        B --> B1["to(HostDevice::MemRegion())"]
        B1 --> B2["示例：shape=[1,1000]"]
        C --> C1["(float*)host_tensor_class.data().cptr()"]
        D --> D1["softmax转换"] --> D2["示例：[2.1,-1.3,0.8]→[0.85,0.02,0.11]"]
        E --> E1["topK(5)"] --> E2["示例：[(232,0.92),(123,0.07)]"]
        F --> F1["cv::putText绘制"] --> F2["示例：Labrador Retriever : 0.92"]
    end

    style B fill:#F8CECC,stroke:#B85450
    style C fill:#D5E8D4,stroke:#82B366
    style D fill:#DAE8FC,stroke:#6C8EBF
    style E fill:#FFF2CC,stroke:#D6B656
    style F fill:#E1D5E7,stroke:#9673A6
```

**关键操作**：

```cpp
// 数据回传
auto host_tensor_class = output_tensors[0].to(HostDevice::MemRegion());
// 结果解析
auto outputs_class = (float*)host_tensor_class.data().cptr();
// Softmax归一化
auto softmax_class = softmax(outputs_class, 1, 0, N_CLASS); 
// Top-K筛选
auto topk_res = topK(softmax_class, 5);
// 结果可视化
cv::putText(img.ori_img, text.str(), ...);
```

**具体处理流程**：

1. **数据回传**：
   - `to(HostDevice::MemRegion())` 将NPU输出张量复制回Host内存
   - 示例：输出张量shape为[1,1000]，表示ImageNet分类结果
2. **概率计算**：
   - `softmax` 将原始logits转换为概率分布
   - 示例：输出`[2.1, -1.3, 0.8,...]` → `[0.85, 0.02, 0.11,...]`
3. **结果筛选**：
   - `topK` 提取前5个最高概率的类别
   - 示例：返回 `[(232, 0.92), (123, 0.07), ...]`（类别ID+概率）
4. **可视化处理**：
   - 通过OpenCV将结果绘制到原始图像
   - 示例：在图像左上角添加"Labrador Retriever : 0.92"等文字

### 1.2 硬件资源分配

#### 1. 硬件映射策略
```mermaid
graph TD
    subgraph CPU后端
        E1[Softmax] --> E2[Top-K筛选]
        E2 --> E3[可视化渲染]
    end
    
    subgraph NPU
        D1[Ghost主卷积] --> D2[深度卷积]
        D2 --> D3[特征融合]
    end
    
    subgraph ImageMake模块
        C1[数据归一化] --> C2[排布转换]
        C2 --> C3[通道对齐]
    end

    subgraph CPU前端
        B1[图像加载] --> B2[动态Resize]
        B2 --> B3[中心裁剪]
    end
    
    A[输入图像] --> B[CPU前处理]
    B --> C[ImageMake硬件加速]
    C --> D[NPU推理]
    D --> E[CPU后处理]
```

####  2. **硬件资源分配方案总表**

|       **处理阶段**       |           **主要操作**            | **硬件分配** |             **代码对应位置**             |      **优化措施**       |
| :----------------------: | :-------------------------------: | :----------: | :--------------------------------------: | :---------------------: |
|    **1. 前处理部分**     |                                   |              |                                          |                         |
|        - 图像加载        |      读取图像文件，格式转换       |     CPU      | `PicPre img(img_path, cv::IMREAD_COLOR)` |                         |
|       - 动态Resize       |      短边缩放（保持长宽比）       |     CPU      |         `img.Resize(resize_hw)`          |                         |
|        - 中心裁剪        |        裁剪至模型输入尺寸         |     CPU      |         `.rCenterCrop(crop_hw)`          |                         |
| **2. ImageMake硬件加速** |                                   |              |                                          |                         |
|       - 数据归一化       | `y=(x–mean)*scale` 代替传统归一化 |     FPGA     |       `dmaInit(..., mean, scale)`        |     硬件定点化运算      |
|        - 排布转换        |    四周Padding（最大255像素）     |     FPGA     |                 自动完成                 |   动态配置Padding参数   |
|        - 通道对齐        |      补通道至4对齐，位宽转换      |     FPGA     |           `AlignAxis`硬件替代            |    自动通道填充策略     |
|    **3. NPU计算部分**    |                                   |              |                                          |                         |
|      - Ghost主卷积       |       常规卷积生成部分特征        |     NPU      |      `session.forward()`中的Conv2D       | 核融合（Conv+BN+ReLU6） |
|        - 深度卷积        |       分组卷积生成剩余特征        |     NPU      |      `session.forward()`中的DWConv       |                         |
|        - 特征拼接        |     合并主卷积与廉价操作输出      |     NPU      |              编译器自动优化              |  张量拼接硬件指令加速   |
|    **4. 后处理优化**     |                                   |              |                                          |                         |
|        - Softmax         |       将输出转换为概率分布        |     CPU      |       `softmax(outputs_class,...)`       |                         |
|       - Top-K筛选        |            提取前5类别            |     CPU      |         `topK(softmax_class,5)`          |                         |
|       - 可视化渲染       |       添加分类结果文字标签        |     CPU      |             `cv::putText()`              |                         |

#### 3. **硬件-软件交互示意图**

```mermaid
sequenceDiagram
    participant Host as Host CPU
    participant NPU as NPU/PL
    participant DDR as 设备内存

    Host->>Host: 图像加载/Resize/Crop
    Host->>DDR: DMA传输预处理数据
    NPU->>NPU: 执行模型推理
    DDR->>Host: DMA回传输出张量
    Host->>Host: Softmax/TopK处理
    Host->>Host: 结果可视化与保存
```

## 2. 模型导出说明

在部署 **GhostNet** 网络时，整体计算流程可分为两部分：**Host 侧（CPU）处理** 与 **Device 侧（硬件加速）处理**。

#### 2.1 Host 侧处理（前后处理）

**GhostNet 部署流程中的前处理和后处理通常由 Host CPU 完成，主要包括：**

- **前处理**
  - **图像加载**：如通过 OpenCV / PIL 等方式读取图像；
  - **动态 Resize**：根据模型输入要求进行等比缩放；
  - **中心裁剪**：对缩放后的图像进行中心裁剪，保持输入维度一致；
- **后处理**：
  - **Softmax**：对分类 logits 输出进行归一化；
  - **Top-K 筛选**：从 softmax 结果中选出概率最高的前 K 类别。

#### 2.2 **Device 侧处理（GhostNet 主干）**

1）**基础卷积算子**：

- 常规卷积：`nn.Conv2d`直接实现
- 深度可分离卷积：通过`nn.Conv2d`的`groups`参数实现分组卷积
- 批归一化：`nn.BatchNorm2d`直接实现
- 激活函数：
  - ReLU：`nn.ReLU`或`F.relu`
  - hard_sigmoid：通过`F.relu6(x + 3.) / 6.`数学表达式实现

2）**Ghost模块特有算子**：

- 主卷积：`nn.Conv2d`+`nn.BatchNorm2d`+`nn.ReLU`组合
- 廉价操作：分组`nn.Conv2d`+`nn.BatchNorm2d`+`nn.ReLU`组合
- 特征拼接：`torch.cat`直接实现

3）**注意力机制算子**：

- 全局平均池化：`nn.AdaptiveAvgPool2d(1)`
- 通道压缩/扩展：`nn.Conv2d`实现的1x1卷积
- 门控函数：`hard_sigmoid`函数实现

4）**特殊操作函数**：

- `_make_divisible`：通过数学运算`int(v + divisor / 2) // divisor * divisor`实现
- `hard_sigmoid`：通过`F.relu6(x + 3.) / 6.`实现

5）**结构模块**：

- GhostBottleneck：组合多个`nn.Conv2d`、`nn.BatchNorm2d`和`nn.ReLU`
- ConvBnAct：`nn.Conv2d`+`nn.BatchNorm2d`+`nn.ReLU`顺序组合

**GhostNet 与 Icraft 硬件支持算子对应表**

| GhostNet 功能组件        | PyTorch 实现方式                                       | Icraft 对应算子组合                                |
| ------------------------ | ------------------------------------------------------ | -------------------------------------------------- |
| **常规卷积**             | `nn.Conv2d`                                            | `Conv2d`                                           |
| **分组卷积**             | `nn.Conv2d(groups=...)`                                | `Conv2d`（设置 groups 参数）                       |
| **深度可分离卷积**       | `nn.Conv2d(groups=in_channels)`                        | `Conv2d`                                           |
| **批归一化**             | `nn.BatchNorm2d`                                       | `BatchNorm2d`                                      |
| **ReLU 激活函数**        | `nn.ReLU` 或 `F.relu`                                  | `ReLU` 或 `Hardtanh` 或 `Swish`                    |
| **HardSigmoid**          | `F.relu6(x + 3.) / 6.`                                 | `Hardsigmoid`                                      |
| **HardSwish**            | `x * F.relu6(x + 3.) / 6.`                             | `Hardswish`                                        |
| **Ghost 主卷积模块**     | `Conv2d + BN + ReLU`                                   | `Conv2d + BatchNorm2d + ReLU`                      |
| **Ghost 廉价操作模块**   | `分组Conv2d + BN + ReLU`                               | `Conv2d + BatchNorm2d + ReLU`（groups>1）          |
| **特征拼接**             | `torch.cat([x1, x2], dim=1)`                           | `Concat`                                           |
| **AdaptiveAvgPool2d(1)** | `nn.AdaptiveAvgPool2d(1)`                              | `AvgPool2d`（kernel=size=feature map）             |
| **1x1卷积（压缩/扩展）** | `nn.Conv2d(kernel_size=1)`                             | `Conv2d`                                           |
| **通道注意力门控**       | `HardSigmoid`                                          | `Hardsigmoid`                                      |
| **_make_divisible**      | `int(v + divisor / 2) // divisor * divisor`            | **非算子**，由 **前处理代码逻辑**实现              |
| **GhostBottleneck**      | 多个 Conv + BN + ReLU + Add + SE 模块组合              | `Conv2d + BatchNorm2d + ReLU + Concat + Add`       |
| **ConvBnAct 快速模块**   | `Conv2d + BatchNorm2d + ReLU`                          | `Conv2d + BatchNorm2d + ReLU`                      |
| **通道间注意力（SE）**   | GAP → Conv1x1 压缩 → ReLU → Conv1x1 扩展 → HardSigmoid | `AvgPool2d + Conv2d + ReLU + Conv2d + Hardsigmoid` |

#### 2.3 导出过程和1_scripts中的脚本运行说明

**直接加载模型，只导出GhostNet 主干，前后处理不保存在在导出模型中。**

~~~
├── 0_infer.py       >框架下推断脚本
├── 1_save.py        >trace模型保存onnx/pt脚本
├── 2_save_infer.py  >onnx/pt推断脚本
~~~

  - **0_infer.py** 
    - 可以推理一张图（或其他格式数据）并得到最终结果，目的是为了快速跑通推理代码，为后续剥离/移植前后处理做准备。为了实现快速不能用整个数据集作为输入。
    - 用法： python 0_infer.py
  - **1_save.py**
    - 保存模型。
    - 导出的模型默认存放至`2_compile/fmodel`路径下，如`../2_compile/fmodel/ghostnet_224x224.pt`
    - 用法： python 1_save.py
  - **2_save_infer.py** 
    - 用修改后保存的模型做前向推理，目的是为了与**0_infer**的结果对比，确保导出静态模型的正确性。
    - 用法： python 2_save_infer.py

## 3. cpu处理部分c++工程移植说明

#### 3.1 cpu环节实现的功能

**CPU（Host 端）**承担了**模型部署**与推理流程中大量关键的**前处理**、**后处理**和**控制逻辑**。

1）**配置与初始化（控制逻辑）**

1. **读取 YAML 配置文件：**
   - 包括模型路径、仿真与实卡运行开关、是否可视化输出、是否保存结果等。
   - 加载图像路径、类别标签文件、网络输入尺寸等信息。
2. **构建模型路径、打开设备并加载模型：**
   - 根据配置动态拼接 JSON 模型路径和 RAW 参数路径。
   - 判断是否在仿真（sim）还是实际设备（实卡）上运行。
   - 加载网络结构并初始化 `Session` 和 `Device`。

2）**前处理（Preprocess）**

这是典型的 **在 CPU 上运行的图像前处理操作**，目标是将原始图片转为模型输入格式：

1. **图像读取：**
   - 使用 OpenCV 加载图像为 BGR 格式。
2. **图像缩放与裁剪：**
   - 首先根据短边进行等比例缩放（`Resize(resize_hw, PicPre::SHORT_SIDE)`）。
   - 然后执行中心裁剪（`rCenterCrop(crop_hw)`）获得定尺寸输入。
3. **图像转换为张量：**
   - 将裁剪后的图像转为 NCHW 格式、float 类型张量，用于输入模型（`CvMat2Tensor()`）。
4. **输入 DMA 传输：**
   - 将 CPU 中的图像张量传输给设备端执行推理（`dmaInit()`）。

3）**模型执行控制**

1. **执行模型前向推理：**
   - 由 CPU 调用 `session.forward()` 启动一次推理流程，控制输入和获取输出。
   - 返回的是在设备端计算完成的结果张量。
2. **设备端输出转回 Host 内存：**
   - 将设备端输出张量（float*）搬运回 CPU 内存空间供后处理使用（`to(HostDevice::MemRegion())`）。

4）**后处理（Postprocess）**

这些操作也是由 CPU 进行的，主要包括：

1. **Softmax 计算：**
   - 将模型输出转化为类别概率分布。
2. **Top-K 筛选：**
   - 从 softmax 输出中选取概率最高的前 5 个类别及其概率。
3. **可视化与输出处理：**
   - 在图像上用 OpenCV `putText` 写入类别名称和概率。
   - 根据平台（Windows 或 Linux）显示图像、保存图像或保存分类结果为 TXT 文件。

#### 3.2 各环节耗时

**命令行输入`icraft run ./config/GhostNet_8.toml`，以仿真int8量化后的模型为例，单一输入图像对理时间输如下：**

```c
// icraft run ./config/GhostNet_8.toml

[05/18/25 13:33:38.384] [I] network wall:   0.0139 ms
Load Json Time:   74.988 ms
Load Raw Time:   60.878 ms
opId: 0    opType: Input           wall:   20.548 ms  mem:    0.000 ms  hard:    0.000 ms  other:   20.548 ms
opId: 1    opType: Resize          wall:    2.022 ms  mem:    0.000 ms  hard:    0.000 ms  other:    2.022 ms
opId: 846  opType: ImageMake       wall:    8.844 ms  mem:    0.000 ms  hard:    0.000 ms  other:    8.844 ms
opId: 1300 opType: HardOp          wall:  801.274 ms  mem:    0.000 ms  hard:    0.000 ms  other:  801.274 ms
opId: 1101 opType: Cast            wall:    0.101 ms  mem:    0.000 ms  hard:    0.000 ms  other:    0.101 ms
opId: 1102 opType: PruneAxis       wall:    0.092 ms  mem:    0.000 ms  hard:    0.000 ms  other:    0.092 ms
opId: 437  opType: Output          wall:    0.012 ms  mem:    0.000 ms  hard:    0.000 ms  other:    0.012 ms
```

**当前仿真系统的cpu配置情况**

```
D:\dtpw\Desktop\icraft_workplace\ghostnet\2_compile>wmic cpu get name,numberofcores,numberoflogicalprocessors,maxclockspeed
MaxClockSpeed  Name                                    NumberOfCores  NumberOfLogicalProcessors
1800           AMD Ryzen 7 4800U with Radeon Graphics  8              16
```

**分析**

* **核心推理耗时在 `HardOp`，即模型主干部分（801ms）**，这是真正的前向计算阶段；
* **前处理部分（Resize + ImageMake）耗时约 10.8ms**；
* **类型转换和输出阶段耗时非常低**（<0.2ms）；
* **输入阶段 Input 的 20ms 大概率包括从文件加载图像时间**；
* 虽然 `network wall` 显示为 `0.0139ms`，但它不是整个模型推理的时间，而是启动模型调度器的一个时间片段，不代表整体执行。

## 4. ICRAFT编译

## **编译通过**

- 使用运行时仿真得到的仿真效果截图或数据，需提供下述表格

  > 比赛报告中要求有：框架动态图推理、导出静态模型推理、解析组件仿真、量化组件仿真、指令组件仿真的仿真效果截图或数据。对于解析组件仿真、量化组件仿真、指令组件仿真等中间过程仿真该怎么做？文档中并没写明，只能参考[docs/Part 2_2 icraft tools.md · spiger/TUTORIAL - 码云 - 开源中国](https://gitee.com/mxh-spiger/tutorial-runtime/blob/tt3.7.1/docs/Part 2_2 icraft tools.md#34-结果分析)中的`icraft run`工作简单输出每个组件的仿真。


#### 1. 框架动态图推理

* 输入图片

  * <img src="./fig/dog.jpg" style="zoom:25%;" />

* 框架推理

  * `python 0_infer.py`

  * 输出结果：

    * ```
      D:\dtpw\Desktop\icraft_workplace\ghostnet\1_scripts>python 0_infer.py
      input size = torch.Size([3, 224, 224])
      output size = torch.Size([1000])
      
      --------Classification results----------
      Samoyed: 0.6540         //萨摩耶
      Pomeranian: 0.0577      //博美犬
      Eskimo dog: 0.0179      //爱斯基摩犬
      white wolf: 0.0108      //白狼
      Arctic fox: 0.0107      //北极狐
      ```

#### 2. 导出静态模型推理

* 输入图片：同上

* 导出静态模型推理

  * `python 2_save_infer.py`

  * ```
    D:\dtpw\Desktop\icraft_workplace\ghostnet\1_scripts>python 2_save_infer.py
    input size = torch.Size([3, 224, 224])
    GhostNet模型加载完成
    output size = torch.Size([1000])
    
    --------分类结果--------
    Samoyed: 0.6540
    Pomeranian: 0.0577
    Eskimo dog: 0.0179
    white wolf: 0.0108
    Arctic fox: 0.0107
    ```

#### 3. 解析组件仿真

* 命令：

  * ```
    # GhostNet_8.toml文件中
    [run]
    log_time = true
    log_io = true
    dump_format = "SFB"
    json = "../3_deploy/modelzoo/GhostNet/imodel/8/GhostNet_parsed.json"  					
    raw = "../3_deploy/modelzoo/GhostNet/imodel/8/GhostNet_parsed.raw"                      
    input = "./qtset/imagenet/ILSVRC2012_val_00000003.JPEG"
    backends = "Host"
    ```

  * 命令行运行`\ghostnet\2_compile>icraft run ./config/GhostNet_8.toml`

 * 输出截图
   * <img src="./fig/解析组件仿真.png" style="zoom:100%;" />

#### 4. 量化组件仿真

* 命令：

  * ```
    # GhostNet_8.toml文件中
    [run]
    log_time = true
    log_io = true
    dump_format = "SFB"
    json = "../3_deploy/modelzoo/GhostNet/imodel/8/GhostNet_quantized.json"  					
    raw = "../3_deploy/modelzoo/GhostNet/imodel/8/GhostNet_quantized.raw"                      
    input = "./qtset/imagenet/ILSVRC2012_val_00000003.JPEG"
    backends = "Host"
    ```

  * 命令行运行`\ghostnet\2_compile>icraft run ./config/GhostNet_8.toml`

 * 输出截图
   * <img src="./fig/量化组件仿真.png" style="zoom:100%;" />

#### 5. 指令组件仿真

* 命令：

  * ```
    # GhostNet_8.toml文件中
    [run]
    log_time = true
    log_io = true
    dump_format = "SFB"
    json = "../3_deploy/modelzoo/GhostNet/imodel/8/GhostNet_BY.json"  					
    raw = "../3_deploy/modelzoo/GhostNet/imodel/8/GhostNet_BY.raw"                      
    input = "./qtset/imagenet/ILSVRC2012_val_00000003.JPEG"
    backends = "Host"
    ```

  * 命令行运行`\ghostnet\2_compile>icraft run ./config/GhostNet_8.toml`

* 输出截图
  * <img src="./fig/指令组件仿真.png" style="zoom:100%;" />

#### 6. 完整的c++工程仿真输出（c++  runtime）

* 在`3_deploy/modelzoo/GhostNet/build_win`目录下运行：

  ```shell
  Release\GhostNet.exe ..\cfg\GhostNet_8.yaml  #注意，windows中一般用\,而/可以用但有些时假会报错
  
  Release\GhostNet.exe ..\cfg\GhostNet_16.yaml
  
  Release\GhostNet.exe ..\cfg\GhostNet_mix.yaml
  ```

* 输出截图

  * <img src="./fig/res_dog.png" style="zoom:50%;" />
  * **分类结果在右上角，用蓝色字体标出，可放大验证。**

#### 7.   8bit，16bit，混合精度的精度测试结果

*  分别运行以下命令，得到8bit，16bit，混合精度模型在[imagenet2012val](https://image-net.org/download.php)的前5000张图像上的分类结果。

  ~~~
  Release\GhostNet.exe ..\cfg\GhostNet_test_8.yaml  #注意，windows中一般用\,而/可以用但有些时假会报错
  
  Release\GhostNet.exe ..\cfg\GhostNet_test_16.yaml
  
  Release\GhostNet.exe ..\cfg\GhostNet_test_mix.yaml
  ~~~

  结果分别保存在

  ```
  3_deploy\modelzoo\GhostNet\io\output\8\val_5000
  3_deploy\modelzoo\GhostNet\io\output\16\val_5000
  3_deploy\modelzoo\GhostNet\io\output\mix\val_5000
  ```

* 运行精度测试命令`Release\GhostNet.exe ..\cfg\GhostNet_test_8.yaml `后，**使用metrics测试脚本**，根据保存的测试结果计算出精度指标。

  metrics测试脚本使用与配置说明：

  - 精度测试脚本存放于：[https://gitee.com/mxh-spiger/benchmark](https://gitee.com/mxh-spiger/benchmark)
  - 本模型使用 `./topn/topn_acc.py`
  - 输入命令`benchmark-master\topn>python .\topn_acc.py D:\dtpw\Desktop\icraft_workplace\ghostnet\3_deploy\modelzoo\GhostNet\io\output\8\val_5000 --gtPath ImageNet2012_val5000.txt`
  - `resDir`字段设置为预测结果存放路径

* 精度结果

  * | GhostNet | input shape      | 精度                      |
    | -------- | ---------------- | ------------------------- |
    | int8     | [1, 3, 224, 224] | top1: 64.92%;top5: 86.1%  |
    | int16    | [1, 3, 224, 224] | top1: 68.26%;top5: 88.26% |

> 由于混合精度在编译过程不能通过，负责人回复为组件bug，所以没有混合精度的测试结果。
>
> 具体bug见：
>
> [Bug]: 混合量化的结果在适配阶段不能通过
>
> https://gitee.com/mxh-spiger/fwb/issues/IC8QZ3

#### 8. 编译过程的一些特殊说明

* 注意，windows中的命令行中，一般用左\,右/可以用但有些时假会报错

* 编译命令注意事项

  * ```
    cd 3_deploy\modelzoo\GhostNet
    mkdir -p build_win
    cd build_win
    
    cmake -G "Visual Studio 17 2022" -A x64 ..    # 不要直接cmake ..
    cmake --build . --config Release
    ```

  * 不能直接使用`cmake ..`命令，因为如果系统上多种编译器，且默认cmake使用的编译器不是[visualstudio2022](https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=Community&channel=Release&version=VS2022&source=VSLandingPage&passive=false&cid=2030)会出错，所以使用`-G "Visual Studio 17 2022" -A x64`命令，让cmake使用visualstudio2022编译器编译。
