根据文档how to build ncnn, 克隆并编译ncnn。
使用的设备是x86架构,nvidia 3060。
1.推理不使用VULKAN
cd ncnn
mkdir -p build-20220711
cmake -DCMAKE_BUILD_TYPE=Release -DNCNN_BUILD_EXAMPLES=ON ..
make -j$(nproc)
# 安装: make install
2.下载测试样本至ncnn/images
,运行squeezenet Demo,验证ncnn推理是否正常:
cd ncnn/examples
../build-20220711/examples/squeezenet ../images/screenshot.png
置信度最高的三个类别索引分别为281,285,282
。
索引+1对应文件synset_words.txt中的行号。
可以得知281: tabby, tabby cat
, 285: Egyptian cat
, 282: tiger cat
。
置信度最高的三个类别都与cat
有关, 推理是正确的。
1.推理时使用VULKAN:
cd ncnn
mkdir -p build-20220701
cmake -DCMAKE_BUILD_TYPE=Release -DNCNN_VULKAN=ON -DNCNN_BUILD_EXAMPLES=ON ..
make -j$(nproc)
# 安装: make install
2.运行squeezenet Demo,验证ncnn推理是否正常:
cd ncnn/examples
../build-20220701/examples/squeezenet ../images/screenshot.png
置信度最高的三个类别索引分别为128,143,98
。
索引+1对应文件synset_words.txt中的行号。
可以得知128: black stork, Ciconia nigra
, 143: oystercatcher, oyster catcher
, 98: red-breasted merganser, Mergus serrator
。
测试样本对应的类别应该是cat
, 这里推理出了一些问题。
暂时不使用VULKAN进行推理,这可能存在一些问题。
根据qunatization-int8-reference对squeezenet进行量化。
1.Optimize model
${NCNN_DIR}/build-20220711/tools/ncnnoptimize \
fp32/squeezenet_v1.1.param \
fp32/squeezenet_v1.1.bin \
opt/squeezenet_v1.1-opt.param \
opt/squeezenet_v1.1-opt.bin \
0
2.Create the calibration table file
需要下载校准集,并提供imagelist.txt。
# Create calibration table file
${NCNN_DIR}/build-20220711/tools/quantize/ncnn2table \
opt/squeezenet_v1.1-opt.param \
opt/squeezenet_v1.1-opt.bin \
imagelist.txt \
squeezenet_v1.1.table \
mean=[104,117,123] \
norm=[1,1,1] \
shape=[227,227,3] \
pixel=BGR \
thread=1 \
method=kl
3.Quantize model
${NCNN_DIR}/build-20220711/tools/quantize/ncnn2int8 \
opt/squeezenet_v1.1-opt.param \
opt/squeezenet_v1.1-opt.bin \
squeezenet_v1.1-int8.param \
squeezenet_v1.1-int8.bin \
squeezenet_v1.1.table
4.Inference
cd int8
ln -s ../squeezenet_v1.1-int8.bin squeezenet_v1.1.bin
ln -s ../squeezenet_v1.1-int8.param squeezenet_v1.1.param
${NCNN_DIR}/build-20220711/examples/squeezenet ../screenshot.png
# 不考虑dilation, bias, group, padding_mode='zeros', dtype=np.float32
def conv2d(input, weight, padding, stride):
_, ih, iw = input.shape
kn, _, kh, kw = weight.shape
oh = (ih + 2 * padding - kh) // stride + 1
ow = (iw + 2 * padding - kw) // stride + 1
oc = kn
_input = np.pad(input, ((0,0),(padding, padding), (padding, padding)), "constant")
output = np.zeros((oc, oh, ow)).astype(np.float32)
for p in range(oc):
for i in range(oh):
for j in range(ow):
output[p, i, j] = np.sum(_input[:, i:i+kh, j:j+kw] * weight[p])
return output