Commit 550ebf64 authored by liucong's avatar liucong
Browse files

加入int8量化代码

parent 697faa92
......@@ -75,7 +75,53 @@ ErrorCode Classifier::Classify(const std::vector<cv::Mat> &srcImages,std::vector
blobFromImagesWithParams()函数支持多个输入图像,首先对输入图像各通道减对应的均值,然后乘以各通道对应的缩放系数,最后转换为NCHW,最终将转换好的数据保存到inputBlob中,然后就可以输入到模型中执行推理了。
## 量化
该示例工程提供了fp16和int8两种量化方法,可以在Resource/Configuration.xml文件中设置是否需要量化:
```c++
<opencv_storage>
<!--分类器-->
<Classifier>
...
<UseInt8>0</UseInt8> // 设置为1时,开启INT8量化
<UseFP16>0</UseFP16> // 设置为1时,开启FP16量化
</Classifier>
</opencv_storage>
```
### FP16量化
使用FP16模式只需要在编译前调用migraphx::quantize_fp16() 即可。
```c++
migraphx::quantize_fp16(net);
```
### INT8量化
使用INT8模式需要提供量化校准数据,MIGraphX采用线性量化算法,通过校准数据计算量化参数并生成量化模型。为了保证量化精度,一般使用测试集或验证集中的数据作为校准数据。
```c++
// 创建量化校准数据,建议使用测试集中的多张典型图像
cv::Mat srcImage=cv::imread("../Resource/Images/ImageNet_test.jpg",1);
std::vector<cv::Mat> srcImages;
for(int i=0;i<inputShape.lens()[0];++i)
{
srcImages.push_back(srcImage);
}
// 数据预处理
...
// 创建量化数据
std::unordered_map<std::string, migraphx::argument> inputData;
inputData[inputName]= migraphx::argument{inputShape, (float*)inputBlob.data};
std::vector<std::unordered_map<std::string, migraphx::argument>> calibrationData = {inputData};
// INT8量化
migraphx::quantize_int8(net, gpuTarget, calibrationData);
```
## 推理
......@@ -108,10 +154,10 @@ ErrorCode Classifier::Classify(const std::vector<cv::Mat> &srcImages,std::vector
另外,如果想要指定输出节点,可以在eval()方法中通过提供outputNames参数来实现:
```
```c++
...
// 推理
std::vector<std::string> outputNames = {"resnetv24_dense0_fwd"}
std::vector<std::string> outputNames = {"resnetv24_dense0_fwd"};
std::vector<migraphx::argument> results = net.eval(inputData, outputNames);
...
```
......
......@@ -22,7 +22,7 @@
本示例代码采用了OpenCV实现了预处理操作:
```
```python
def Preprocessing(pathOfImage):
image = cv2.imread(pathOfImage, cv2.IMREAD_COLOR)
......@@ -62,13 +62,51 @@ def Preprocessing(pathOfImage):
return norm_img_data
```
## 量化
该示例工程提供了FP16和INT8两种量化方法,可以根据选项设置是否需要量化:
```python
use_int8 = False // 设置为True时开启INT8量化
use_fp16 = False // 设置为True时开启FP16量化
```
### FP16量化
使用FP16模式只需要在编译前调用migraphx.quantize_fp16() 即可。
```python
if __name__ == '__main__':
...
if use_fp16:
migraphx.quantize_fp16(model)
...
```
### INT8量化
使用INT8模式需要提供量化校准数据,MIGraphX采用线性量化算法,通过校准数据计算量化参数并生成量化模型。为了保证量化精度,一般使用测试集或验证集中的数据作为校准数据。
```python
if __name__ == '__main__':
...
if use_int8:
dic = dict() # 创建字典
testofImage = "../Resource/Images/ImageNet_test.jpg" # 提供的量化校准数据
testimage = Preprocessing(testofImage)
dic[inputName] = migraphx.argument(testimage) # 创建量化数据
calibration = [dic]
# INT8量化
migraphx.quantize_int8(model, migraphx.get_target("gpu"), calibration)
...
```
## 推理
完成预处理后,就可以执行推理了:
```
```python
if __name__ == '__main__':
...
......
......@@ -46,6 +46,10 @@ def Preprocessing(pathOfImage):
if __name__ == '__main__':
# 量化方法选项
use_int8 = False
use_fp16 = False
# 设置最大输入shape
maxInput={"data":[1,3,224,224]}
......@@ -66,6 +70,18 @@ if __name__ == '__main__':
inputName="data"
inputShape=inputs[inputName].lens()
# INT8量化
if use_int8:
dic = dict()
testofImage = "../Resource/Images/ImageNet_test.jpg"
testimage = Preprocessing(testofImage)
dic[inputName] = migraphx.argument(testimage)
calibration = [dic]
migraphx.quantize_int8(model, migraphx.get_target("gpu"), calibration)
if use_fp16:
migraphx.quantize_fp16(model)
# 编译
model.compile(t=migraphx.get_target("gpu"),device_id=0) # device_id: 设置GPU设备,默认为0号设备
......
......@@ -84,7 +84,7 @@ ErrorCode Classifier::Initialize(InitializationParameterOfClassifier initializat
if(useInt8)
{
// 创建量化校准数据,建议使用测试集中的多张典型图像
cv::Mat srcImage=cv::imread("../Resource/Images/ImageNet_01.jpg",1);
cv::Mat srcImage=cv::imread("../Resource/Images/ImageNet_test.jpg",1);
std::vector<cv::Mat> srcImages;
for(int i=0;i<inputShape.lens()[0];++i)
{
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment