diff --git a/models/cv/face_recognition/facenet/ixrt/README.md b/models/cv/face_recognition/facenet/ixrt/README.md index 62d4de802ca9a3014cf11ffe66e8ad1b6bae1a3a..cd58c9b9e3ceeb57d077729b7afc781093fb442c 100644 --- a/models/cv/face_recognition/facenet/ixrt/README.md +++ b/models/cv/face_recognition/facenet/ixrt/README.md @@ -18,12 +18,6 @@ Pretrained model: to download the lfw dataset. -```bash -cd ${DeepSparkInference_PATH}/models/cv/face/facenet/ixrt -# download and unzip 20180408-102900.zip -unzip 20180408-102900.zip -``` - ### Install Dependencies ```bash @@ -41,14 +35,8 @@ pip3 install -r requirements.txt ```bash mkdir -p checkpoints mkdir -p facenet_weights -git clone https://github.com/timesler/facenet-pytorch -# facenet-pytorch/dependencies/facenet is submodule, pls make sure it has been cloned or you can clone directly from https://github.com/davidsandberg/facenet/tree/096ed770f163957c1e56efa7feeb194773920f6e -mv /Path/facenet/ixrt/tensorflow2pytorch.py facenet-pytorch -python3 ./facenet-pytorch/tensorflow2pytorch.py \ - --facenet_weights_path ./facenet_weights \ - --facenet_pb_path ./20180408-102900 \ - --onnx_save_name facenet_export.onnx -mv facenet_export.onnx ./facenet_weights +cd facenet_weights +wget http://files.deepspark.org.cn:880/deepspark/facenet_export.onnx ``` ### Data preprocessing diff --git a/models/cv/face_recognition/facenet/ixrt/build_engine.py b/models/cv/face_recognition/facenet/ixrt/build_engine.py index 74a62202defa50397cc4227da2181eebe10ab3e9..057587f81ec202e4b1077e8dc7dd2a0fdc7bfa9e 100644 --- a/models/cv/face_recognition/facenet/ixrt/build_engine.py +++ b/models/cv/face_recognition/facenet/ixrt/build_engine.py @@ -1,18 +1,3 @@ -# Copyright (c) 2024, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - import os import cv2 import argparse @@ -28,13 +13,13 @@ from load_ixrt_plugin import load_ixrt_plugin load_ixrt_plugin() def add_facenet_norm(onnx_model): - norm = helper.make_node('FacenetNorm_IxRT', inputs=['/last_bn/BatchNormalization_output_0'] , outputs=['/Pow_1_output_0'], name='facenet_norm_1', size=512) + norm = helper.make_node('FacenetNorm_IxRT', inputs=['1189'] , outputs=['1190'], name='facenet_norm_1', size=512) onnx_model = onnx.load(onnx_model) graph = onnx_model.graph nodes = graph.node graph.node.append(norm) - output = onnx.helper.make_tensor_value_info('/Pow_1_output_0', TensorProto.FLOAT, [64, 512, 1, 1]) + output = onnx.helper.make_tensor_value_info('1190', TensorProto.FLOAT, [64, 512, 1, 1]) graph = onnx.helper.make_graph( graph.node, "facenet model", diff --git a/models/cv/face_recognition/facenet/ixrt/ci/prepare.sh b/models/cv/face_recognition/facenet/ixrt/ci/prepare.sh index 9d7081e7f053f6117e91bd5df10c9ce25e61c04d..44ffa453bd2d83d1b56ce4274c62dc4c3d19b9fb 100644 --- a/models/cv/face_recognition/facenet/ixrt/ci/prepare.sh +++ b/models/cv/face_recognition/facenet/ixrt/ci/prepare.sh @@ -26,16 +26,6 @@ else fi pip3 install -r requirements.txt -unzip -q /root/data/checkpoints/20180408-102900.zip -d ./ unzip -q /root/data/datasets/facenet_datasets.zip -d ./ -mkdir -p checkpoints mkdir -p facenet_weights -cp -r /root/data/3rd_party/facenet-pytorch ./ -cp ./tensorflow2pytorch.py facenet-pytorch -python3 ./facenet-pytorch/tensorflow2pytorch.py \ - --facenet_weights_path ./facenet_weights \ - --facenet_pb_path ./20180408-102900 \ - --onnx_save_name facenet_export.onnx -mv facenet_export.onnx ./facenet_weights - -sed -i -e 's#/last_bn/BatchNormalization_output_0#1187#g' -e 's#/avgpool_1a/GlobalAveragePool_output_0#1178#g' deploy.py build_engine.py \ No newline at end of file +cp /root/data/checkpoints/facenet_export.onnx ./facenet_weights diff --git a/models/cv/face_recognition/facenet/ixrt/common.py b/models/cv/face_recognition/facenet/ixrt/common.py index 9db1327ad1531c452fb38182d747c81fc6f8eccf..4b9ae1140ebb347f2127c141ec0e5934ef02f59d 100644 --- a/models/cv/face_recognition/facenet/ixrt/common.py +++ b/models/cv/face_recognition/facenet/ixrt/common.py @@ -1,25 +1,10 @@ -# Copyright (c) 2024, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - import os import cv2 import glob import torch import tensorrt import numpy as np -import pycuda.driver as cuda +from cuda import cuda, cudart from torch.utils.data import DataLoader, SubsetRandomSampler, SequentialSampler from torchvision import datasets, transforms @@ -53,13 +38,15 @@ def get_io_bindings(engine): size = np.dtype(tensorrt.nptype(dtype)).itemsize for s in shape: size *= s - allocation = cuda.mem_alloc(size) + err, allocation = cudart.cudaMalloc(size) + assert err == cudart.cudaError_t.cudaSuccess binding = { "index": i, "name": name, "dtype": np.dtype(tensorrt.nptype(dtype)), "shape": list(shape), "allocation": allocation, + "nbytes": size, } print(f"binding {i}, name : {name} dtype : {np.dtype(tensorrt.nptype(dtype))} shape : {list(shape)}") allocations.append(allocation) diff --git a/models/cv/face_recognition/facenet/ixrt/config/FACENET_CONFIG b/models/cv/face_recognition/facenet/ixrt/config/FACENET_CONFIG index 3b3282eff772fa4a2d46d2cc2aace1570ad0f1bb..74ea45fe130915d2c2775a58bbf514fec8c54bdd 100644 --- a/models/cv/face_recognition/facenet/ixrt/config/FACENET_CONFIG +++ b/models/cv/face_recognition/facenet/ixrt/config/FACENET_CONFIG @@ -1,18 +1,3 @@ -# Copyright (c) 2024, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - # IMGSIZE : 模型输入hw大小 # MODEL_NAME : 生成onnx/engine的basename # ORIGINE_MODEL : 原始onnx文件名称 diff --git a/models/cv/face_recognition/facenet/ixrt/deploy.py b/models/cv/face_recognition/facenet/ixrt/deploy.py index 79f4ce5880bb50f78127a923e09c446547ac3fd2..3036363f22df57f86dab738bd827ee993bc5a424 100644 --- a/models/cv/face_recognition/facenet/ixrt/deploy.py +++ b/models/cv/face_recognition/facenet/ixrt/deploy.py @@ -1,18 +1,3 @@ -# Copyright (c) 2024, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - import onnx import os import simplejson as json @@ -34,7 +19,7 @@ def onnx_sim(onnx_name, save_name): def cut_model(onnx_name): input_names = ["input"] - output_names = ["/last_bn/BatchNormalization_output_0"] + output_names = ["1189"] onnx.utils.extract_model(onnx_name, onnx_name, input_names, output_names) def fuse_matmul(onnx_name, save_onnx_name): @@ -94,10 +79,10 @@ def fuse_matmul(onnx_name, save_onnx_name): graph.initializer.append(conv_bias_new_initializer) pre_node.op_type = "Conv" - pre_node.input[0] = "/avgpool_1a/GlobalAveragePool_output_0" + pre_node.input[0] = "1180" pre_node.input[1] = "conv_weights_new" pre_node.input.append("conv_bias_new") - pre_node.output[0] = "/last_bn/BatchNormalization_output_0" + pre_node.output[0] = "1189" dilations = onnx.helper.make_attribute("dilations", [1,1]) group = onnx.helper.make_attribute("group", 1) kernel_shape = onnx.helper.make_attribute("kernel_shape", [1,1]) @@ -119,7 +104,7 @@ def fuse_matmul(onnx_name, save_onnx_name): graph.node.remove(node) if find_matmul==1: - output = onnx.helper.make_tensor_value_info('/last_bn/BatchNormalization_output_0', TensorProto.FLOAT, [64, 512, 1, 1]) + output = onnx.helper.make_tensor_value_info('1189', TensorProto.FLOAT, [64, 512, 1, 1]) graph = onnx.helper.make_graph( graph.node, "facenet model", @@ -389,10 +374,10 @@ def add_facenet_norm(cfg_name): graph_json["nodes"]["facenet_norm_1"] = { "inputs": [ - "/last_bn/BatchNormalization_output_0" + "1189" ], "outputs": [ - "/Pow_1_output_0" + "1190" ], "op_type": "FacenetNorm", "attrbiute": { @@ -400,7 +385,7 @@ def add_facenet_norm(cfg_name): } } graph_json["output"] = [] - graph_json["output"].append({"name":"/Pow_1_output_0", "type":"float32"}) + graph_json["output"].append({"name":"1190", "type":"float32"}) with open(cfg_name, "w") as fh: json.dump(graph_json, fh, indent=4) diff --git a/models/cv/face_recognition/facenet/ixrt/inference.py b/models/cv/face_recognition/facenet/ixrt/inference.py index eaed8b27ca70fb1628c8e5b3351b9e72692150fd..74a43f3e8da05fc5f1559b3a99046040f4cc8412 100644 --- a/models/cv/face_recognition/facenet/ixrt/inference.py +++ b/models/cv/face_recognition/facenet/ixrt/inference.py @@ -1,18 +1,3 @@ -# Copyright (c) 2024, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - #!/usr/bin/env python # -*- coding: utf-8 -*- @@ -25,8 +10,7 @@ from tqdm import tqdm import cv2 import numpy as np -import pycuda.autoinit -import pycuda.driver as cuda +from cuda import cuda, cudart import torch import tensorrt from tensorrt.utils import topk @@ -58,7 +42,6 @@ def main(config): print("Warm Done.") # Inference - metricResult = {"metricResult": {}} if config.test_mode == "FPS": torch.cuda.synchronize() start_time = time.time() @@ -74,7 +57,6 @@ def main(config): print("FPS : ", fps) print(f"Performance Check : Test {fps} >= target {config.fps_target}") - metricResult["metricResult"]["FPS"] = round(fps, 3) if fps >= config.fps_target: print("pass!") exit() @@ -86,7 +68,7 @@ def main(config): classes = [] embeddings = [] - start_time = time.time() + for xb, yb in tqdm(embed_loader): output = np.zeros(outputs[0]["shape"], outputs[0]["dtype"]) @@ -94,9 +76,11 @@ def main(config): xb = xb.numpy() xb = np.ascontiguousarray(xb) - cuda.memcpy_htod(inputs[0]["allocation"], xb) + err, = cuda.cuMemcpyHtoD(inputs[0]["allocation"], xb, xb.nbytes) + assert(err == cuda.CUresult.CUDA_SUCCESS) context.execute_v2(allocations) - cuda.memcpy_dtoh(output, outputs[0]["allocation"]) + err, = cuda.cuMemcpyDtoH(output, outputs[0]["allocation"], outputs[0]["nbytes"]) + assert(err == cuda.CUresult.CUDA_SUCCESS) output = output.reshape(output.shape[0],output.shape[1]) #print("output shape ",output.shape) @@ -104,8 +88,7 @@ def main(config): classes.extend(yb[0:current_imgs_num].numpy()) embeddings.extend(output) - e2e_time = time.time() - start_time - print(f"E2E time: {e2e_time:.3f} seconds") + embeddings_dict = dict(zip(crop_paths,embeddings)) pairs = read_pairs(config.datasets_dir + config.pairs_name) @@ -122,9 +105,6 @@ def main(config): #eer = brentq(lambda x: 1. - x - interpolate.interp1d(fpr, tpr, fill_value="extrapolate")(x), 0., 1.) #print('Equal Error Rate (EER): %1.3f' % eer) - metricResult["metricResult"]["E2E time"] = round(e2e_time, 3) - metricResult["metricResult"]["AUC"] = round(auc, 3) - metricResult["metricResult"]["Acc"] = round(np.mean(accuracy), 3) acc = np.mean(accuracy) print(f"Accuracy Check : Test {acc} >= target {config.acc_target}") if acc >= config.acc_target: @@ -133,7 +113,6 @@ def main(config): else: print("failed!") exit(1) - print(metricResult) def parse_config(): parser = argparse.ArgumentParser() @@ -157,7 +136,7 @@ def parse_config(): "--img", "--img-size", type=int, - default=160, + default=224, help="inference size h,w", ) parser.add_argument("--use_async", action="store_true") @@ -173,4 +152,4 @@ def parse_config(): if __name__ == "__main__": config = parse_config() - main(config) \ No newline at end of file + main(config) diff --git a/models/cv/face_recognition/facenet/ixrt/load_ixrt_plugin.py b/models/cv/face_recognition/facenet/ixrt/load_ixrt_plugin.py index ae47dc8e854b6bea1f768e65c4dd481048bfebce..932efbdfd1a4e91d8ddfd363adf6bce989df1709 100644 --- a/models/cv/face_recognition/facenet/ixrt/load_ixrt_plugin.py +++ b/models/cv/face_recognition/facenet/ixrt/load_ixrt_plugin.py @@ -1,18 +1,3 @@ -# Copyright (c) 2024, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - import ctypes import tensorrt from os.path import join, dirname, exists diff --git a/models/cv/face_recognition/facenet/ixrt/modify_batchsize.py b/models/cv/face_recognition/facenet/ixrt/modify_batchsize.py new file mode 100644 index 0000000000000000000000000000000000000000..f329119d4b79feef2022c4b6a8d7a9ad4ea1f8f6 --- /dev/null +++ b/models/cv/face_recognition/facenet/ixrt/modify_batchsize.py @@ -0,0 +1,39 @@ +import onnx +import numpy as np +import argparse + +def change_dim(model, bsz): + batch_size = bsz + + # The following code changes the first dimension of every input to be batch_size + # Modify as appropriate ... note that this requires all inputs to + # have the same batch_size + for input in model.graph.input: + # Checks omitted.This assumes that all inputs are tensors and have a shape with first dim. + # Add checks as needed. + dim1 = input.type.tensor_type.shape.dim[0] + # update dim to be a symbolic value + if isinstance(batch_size, str): + # set dynamic batch size + dim1.dim_param = batch_size + elif (isinstance(batch_size, str) and batch_size.isdigit()) or isinstance(batch_size, int): + # set given batch size + dim1.dim_value = int(batch_size) + else: + # set batch size of 1 + dim1.dim_value = 1 + + return model + +def parse_args(): + parser = argparse.ArgumentParser() + parser.add_argument("--batch_size", type=int) + parser.add_argument("--origin_model", type=str) + parser.add_argument("--output_model", type=str) + args = parser.parse_args() + return args + +args = parse_args() +model = onnx.load(args.origin_model) +change_dim(model, args.batch_size) +onnx.save(model, args.output_model) diff --git a/models/cv/face_recognition/facenet/ixrt/quant.py b/models/cv/face_recognition/facenet/ixrt/quant.py index 26413e3e0f58f219cce2bd78804de288cba1fd1a..e4bb3780c5788d184e63cba5a32c1f54b056c7a7 100644 --- a/models/cv/face_recognition/facenet/ixrt/quant.py +++ b/models/cv/face_recognition/facenet/ixrt/quant.py @@ -1,19 +1,5 @@ -# Copyright (c) 2024, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - import os + import torch from tensorrt.deploy.api import * from tensorrt.deploy.utils.seed import manual_seed @@ -93,6 +79,14 @@ def quantize_model(args, model_name, model, dataloader): quant_format="qdq", disable_quant_names=None) +def add_1190_scale(cfg_name): + graph_json = json.load(open(cfg_name)) + + graph_json["quant_info"]["1190"] = graph_json["quant_info"]["1189"] + + with open(cfg_name, "w") as fh: + json.dump(graph_json, fh, indent=4) + def create_argparser(*args, **kwargs): parser = ArgumentParser(*args, **kwargs) parser.add_argument("--batch_size", type=int, default=64) @@ -128,6 +122,8 @@ def main(): else: print("[Error] file name not correct ", args.model) quantize_model(args, model_name, model, dataloader) + json_name = f"./facenet_weights/{model_name}.json" + add_1190_scale(json_name) if __name__ == "__main__": main() diff --git a/models/cv/face_recognition/facenet/ixrt/requirements.txt b/models/cv/face_recognition/facenet/ixrt/requirements.txt index b1b549a88d296c1f16d6eeb65bc28b9ddefcaea8..09895311f8ac47415b7774fbdcb78cb6c73f2f1a 100644 --- a/models/cv/face_recognition/facenet/ixrt/requirements.txt +++ b/models/cv/face_recognition/facenet/ixrt/requirements.txt @@ -1,12 +1,9 @@ -tensorflow -onnxsim -scikit-learn -tf_slim tqdm -pycuda -onnx tabulate scipy==1.8.0 -pycocotools -opencv-python==4.6.0.66 -simplejson \ No newline at end of file +scikit-learn +onnx +onnxsim +simplejson +numpy==1.23.5 +opencv-python==4.6.0.66 \ No newline at end of file diff --git a/models/cv/face_recognition/facenet/ixrt/scripts/infer_facenet_fp16_accuracy.sh b/models/cv/face_recognition/facenet/ixrt/scripts/infer_facenet_fp16_accuracy.sh index 27e5e8ad859d95c86dfc9b29fdc78150b0c60c95..d1c797299665ca44546d2927e446b4daca769af3 100644 --- a/models/cv/face_recognition/facenet/ixrt/scripts/infer_facenet_fp16_accuracy.sh +++ b/models/cv/face_recognition/facenet/ixrt/scripts/infer_facenet_fp16_accuracy.sh @@ -1,18 +1,3 @@ -# Copyright (c) 2024, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - #!/bin/bash EXIT_STATUS=0 @@ -43,6 +28,7 @@ do --tgt) TGT=${arguments[index]};; esac done + PROJ_DIR=$(cd $(dirname $0);cd ../../; pwd) echo PROJ_DIR : ${PROJ_DIR} RUN_DIR="${PROJ_DIR}/ixrt/" @@ -102,13 +88,24 @@ if [ $PRECISION == "int8" ];then fi fi +# Change Batchsize +let step++ +echo; +echo [STEP ${step}] : Change Batchsize +FINAL_MODEL=${CHECKPOINTS_DIR}/${MODEL_NAME}_${BSZ}.onnx +if [ -f $FINAL_MODEL ];then + echo " "Change Batchsize Skip, $FINAL_MODEL has been existed +else + python3 ${RUN_DIR}/modify_batchsize.py --batch_size ${BSZ} \ + --origin_model ${SIM_MODEL} --output_model ${FINAL_MODEL} + echo " "Generate ${FINAL_MODEL} +fi # Build Engine let step++ echo; echo [STEP ${step}] : Build Engine ENGINE_FILE=${CHECKPOINTS_DIR}/${MODEL_NAME}_${PRECISION}_bs${BSZ}.engine -FINAL_MODEL=${SIM_MODEL} if [ -f $ENGINE_FILE ];then echo " "Build Engine Skip, $ENGINE_FILE has been existed else @@ -130,7 +127,7 @@ python3 ${RUN_DIR}/inference.py \ --warm_up=${WARM_UP} \ --loop_count ${LOOP_COUNT} \ --test_mode ${RUN_MODE} \ - --fps_target ${TGT} \ + --acc_target ${TGT} \ --bsz ${BSZ}; check_status exit ${EXIT_STATUS} \ No newline at end of file diff --git a/models/cv/face_recognition/facenet/ixrt/scripts/infer_facenet_fp16_performance.sh b/models/cv/face_recognition/facenet/ixrt/scripts/infer_facenet_fp16_performance.sh index 401658cafd85297b9d98f7febb9e7c88746062ef..5e0cf7808166803037683bb2aacf4003503556bb 100644 --- a/models/cv/face_recognition/facenet/ixrt/scripts/infer_facenet_fp16_performance.sh +++ b/models/cv/face_recognition/facenet/ixrt/scripts/infer_facenet_fp16_performance.sh @@ -1,18 +1,3 @@ -# Copyright (c) 2024, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - #!/bin/bash EXIT_STATUS=0 diff --git a/models/cv/face_recognition/facenet/ixrt/scripts/infer_facenet_int8_accuracy.sh b/models/cv/face_recognition/facenet/ixrt/scripts/infer_facenet_int8_accuracy.sh index c2c2f176bcd0ea6bb00acedb6fbda80b47456a08..ea7cb3ecc6f675dc220fe9a2a81f94992c065cef 100644 --- a/models/cv/face_recognition/facenet/ixrt/scripts/infer_facenet_int8_accuracy.sh +++ b/models/cv/face_recognition/facenet/ixrt/scripts/infer_facenet_int8_accuracy.sh @@ -1,18 +1,3 @@ -# Copyright (c) 2024, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - #!/bin/bash EXIT_STATUS=0 diff --git a/models/cv/face_recognition/facenet/ixrt/scripts/infer_facenet_int8_performance.sh b/models/cv/face_recognition/facenet/ixrt/scripts/infer_facenet_int8_performance.sh index 7574347c028dfdb28e3b06016d4c61fb6d3e1328..21c419d73c7a6f69531f195bb0dd8cd0e12484ef 100644 --- a/models/cv/face_recognition/facenet/ixrt/scripts/infer_facenet_int8_performance.sh +++ b/models/cv/face_recognition/facenet/ixrt/scripts/infer_facenet_int8_performance.sh @@ -1,18 +1,3 @@ -# Copyright (c) 2024, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - #!/bin/bash EXIT_STATUS=0 diff --git a/models/cv/face_recognition/facenet/ixrt/tensorflow2pytorch.py b/models/cv/face_recognition/facenet/ixrt/tensorflow2pytorch.py deleted file mode 100644 index f76ba0fff91ae1ac334c2babbc10f0d65139b711..0000000000000000000000000000000000000000 --- a/models/cv/face_recognition/facenet/ixrt/tensorflow2pytorch.py +++ /dev/null @@ -1,387 +0,0 @@ -# Copyright (c) 2024, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import tensorflow.compat.v1 as tf -tf.disable_v2_behavior() -import torch -import json -import os, sys - -from dependencies.facenet.src import facenet -from dependencies.facenet.src.models import inception_resnet_v1 as tf_mdl -from dependencies.facenet.src.align import detect_face - -from models.inception_resnet_v1 import InceptionResnetV1 -from models.mtcnn import PNet, RNet, ONet - - -def import_tf_params(tf_mdl_dir, sess): - """Import tensorflow model from save directory. - - Arguments: - tf_mdl_dir {str} -- Location of protobuf, checkpoint, meta files. - sess {tensorflow.Session} -- Tensorflow session object. - - Returns: - (list, list, list) -- Tuple of lists containing the layer names, - parameter arrays as numpy ndarrays, parameter shapes. - """ - print('\nLoading tensorflow model\n') - if callable(tf_mdl_dir): - tf_mdl_dir(sess) - else: - facenet.load_model(tf_mdl_dir) - - print('\nGetting model weights\n') - images_placeholder = tf.get_default_graph().get_tensor_by_name("input:0") - print(images_placeholder) - tf_layers = tf.trainable_variables() - tf_params = sess.run(tf_layers) - print(tf.get_default_graph()) - - tf_shapes = [p.shape for p in tf_params] - tf_layers = [l.name for l in tf_layers] - - print(tf_shapes) - print(tf_shapes) - - if not callable(tf_mdl_dir): - path = os.path.join(tf_mdl_dir, 'layer_description.json') - else: - path = 'data/layer_description.json' - with open(path, 'w') as f: - json.dump({l: s for l, s in zip(tf_layers, tf_shapes)}, f) - - return tf_layers, tf_params, tf_shapes - - -def get_layer_indices(layer_lookup, tf_layers): - """Giving a lookup of model layer attribute names and tensorflow variable names, - find matching parameters. - - Arguments: - layer_lookup {dict} -- Dictionary mapping pytorch attribute names to (partial) - tensorflow variable names. Expects dict of the form {'attr': ['tf_name', ...]} - where the '...'s are ignored. - tf_layers {list} -- List of tensorflow variable names. - - Returns: - list -- The input dictionary with the list of matching inds appended to each item. - """ - layer_inds = {} - for name, value in layer_lookup.items(): - layer_inds[name] = value + [[i for i, n in enumerate(tf_layers) if value[0] in n]] - return layer_inds - - -def load_tf_batchNorm(weights, layer): - """Load tensorflow weights into nn.BatchNorm object. - - Arguments: - weights {list} -- Tensorflow parameters. - layer {torch.nn.Module} -- nn.BatchNorm. - """ - layer.bias.data = torch.tensor(weights[0]).view(layer.bias.data.shape) - layer.weight.data = torch.ones_like(layer.weight.data) - layer.running_mean = torch.tensor(weights[1]).view(layer.running_mean.shape) - layer.running_var = torch.tensor(weights[2]).view(layer.running_var.shape) - - -def load_tf_conv2d(weights, layer, transpose=False): - """Load tensorflow weights into nn.Conv2d object. - - Arguments: - weights {list} -- Tensorflow parameters. - layer {torch.nn.Module} -- nn.Conv2d. - """ - if isinstance(weights, list): - if len(weights) == 2: - layer.bias.data = ( - torch.tensor(weights[1]) - .view(layer.bias.data.shape) - ) - weights = weights[0] - - if transpose: - dim_order = (3, 2, 1, 0) - else: - dim_order = (3, 2, 0, 1) - - layer.weight.data = ( - torch.tensor(weights) - .permute(dim_order) - .view(layer.weight.data.shape) - ) - - -def load_tf_conv2d_trans(weights, layer): - return load_tf_conv2d(weights, layer, transpose=True) - - -def load_tf_basicConv2d(weights, layer): - """Load tensorflow weights into grouped Conv2d+BatchNorm object. - - Arguments: - weights {list} -- Tensorflow parameters. - layer {torch.nn.Module} -- Object containing Conv2d+BatchNorm. - """ - load_tf_conv2d(weights[0], layer.conv) - load_tf_batchNorm(weights[1:], layer.bn) - - -def load_tf_linear(weights, layer): - """Load tensorflow weights into nn.Linear object. - - Arguments: - weights {list} -- Tensorflow parameters. - layer {torch.nn.Module} -- nn.Linear. - """ - if isinstance(weights, list): - if len(weights) == 2: - layer.bias.data = ( - torch.tensor(weights[1]) - .view(layer.bias.data.shape) - ) - weights = weights[0] - layer.weight.data = ( - torch.tensor(weights) - .transpose(-1, 0) - .view(layer.weight.data.shape) - ) - - -# High-level parameter-loading functions: - -def load_tf_block35(weights, layer): - load_tf_basicConv2d(weights[:4], layer.branch0) - load_tf_basicConv2d(weights[4:8], layer.branch1[0]) - load_tf_basicConv2d(weights[8:12], layer.branch1[1]) - load_tf_basicConv2d(weights[12:16], layer.branch2[0]) - load_tf_basicConv2d(weights[16:20], layer.branch2[1]) - load_tf_basicConv2d(weights[20:24], layer.branch2[2]) - load_tf_conv2d(weights[24:26], layer.conv2d) - - -def load_tf_block17_8(weights, layer): - load_tf_basicConv2d(weights[:4], layer.branch0) - load_tf_basicConv2d(weights[4:8], layer.branch1[0]) - load_tf_basicConv2d(weights[8:12], layer.branch1[1]) - load_tf_basicConv2d(weights[12:16], layer.branch1[2]) - load_tf_conv2d(weights[16:18], layer.conv2d) - - -def load_tf_mixed6a(weights, layer): - if len(weights) != 16: - raise ValueError(f'Number of weight arrays ({len(weights)}) not equal to 16') - load_tf_basicConv2d(weights[:4], layer.branch0) - load_tf_basicConv2d(weights[4:8], layer.branch1[0]) - load_tf_basicConv2d(weights[8:12], layer.branch1[1]) - load_tf_basicConv2d(weights[12:16], layer.branch1[2]) - - -def load_tf_mixed7a(weights, layer): - if len(weights) != 28: - raise ValueError(f'Number of weight arrays ({len(weights)}) not equal to 28') - load_tf_basicConv2d(weights[:4], layer.branch0[0]) - load_tf_basicConv2d(weights[4:8], layer.branch0[1]) - load_tf_basicConv2d(weights[8:12], layer.branch1[0]) - load_tf_basicConv2d(weights[12:16], layer.branch1[1]) - load_tf_basicConv2d(weights[16:20], layer.branch2[0]) - load_tf_basicConv2d(weights[20:24], layer.branch2[1]) - load_tf_basicConv2d(weights[24:28], layer.branch2[2]) - - -def load_tf_repeats(weights, layer, rptlen, subfun): - if len(weights) % rptlen != 0: - raise ValueError(f'Number of weight arrays ({len(weights)}) not divisible by {rptlen}') - weights_split = [weights[i:i+rptlen] for i in range(0, len(weights), rptlen)] - for i, w in enumerate(weights_split): - subfun(w, getattr(layer, str(i))) - - -def load_tf_repeat_1(weights, layer): - load_tf_repeats(weights, layer, 26, load_tf_block35) - - -def load_tf_repeat_2(weights, layer): - load_tf_repeats(weights, layer, 18, load_tf_block17_8) - - -def load_tf_repeat_3(weights, layer): - load_tf_repeats(weights, layer, 18, load_tf_block17_8) - - -def test_loaded_params(mdl, tf_params, tf_layers): - """Check each parameter in a pytorch model for an equivalent parameter - in a list of tensorflow variables. - - Arguments: - mdl {torch.nn.Module} -- Pytorch model. - tf_params {list} -- List of ndarrays representing tensorflow variables. - tf_layers {list} -- Corresponding list of tensorflow variable names. - """ - tf_means = torch.stack([torch.tensor(p).mean() for p in tf_params]) - for name, param in mdl.named_parameters(): - pt_mean = param.data.mean() - matching_inds = ((tf_means - pt_mean).abs() < 1e-8).nonzero() - print(f'{name} equivalent to {[tf_layers[i] for i in matching_inds]}') - - -def compare_model_outputs(pt_mdl, sess, test_data): - """Given some testing data, compare the output of pytorch and tensorflow models. - - Arguments: - pt_mdl {torch.nn.Module} -- Pytorch model. - sess {tensorflow.Session} -- Tensorflow session object. - test_data {torch.Tensor} -- Pytorch tensor. - """ - print('\nPassing test data through TF model\n') - if isinstance(sess, tf.Session): - images_placeholder = tf.get_default_graph().get_tensor_by_name("input:0") - phase_train_placeholder = tf.get_default_graph().get_tensor_by_name("phase_train:0") - embeddings = tf.get_default_graph().get_tensor_by_name("embeddings:0") - feed_dict = {images_placeholder: test_data.numpy(), phase_train_placeholder: False} - tf_output = torch.tensor(sess.run(embeddings, feed_dict=feed_dict)) - else: - tf_output = sess(test_data) - - print(tf_output.shape, tf_output) - - print('\nPassing test data through PT model\n') - pt_output = pt_mdl(test_data.permute(0, 3, 1, 2)) - print(pt_output.shape, pt_output) - - distance = (tf_output - pt_output).norm() - print(f'\nDistance {distance}\n') - - -def compare_mtcnn(pt_mdl, tf_fun, sess, ind, test_data): - tf_mdls = tf_fun(sess) - tf_mdl = tf_mdls[ind] - - print('\nPassing test data through TF model\n') - tf_output = tf_mdl(test_data.numpy()) - tf_output = [torch.tensor(out) for out in tf_output] - print('\n'.join([str(o.view(-1)[:10]) for o in tf_output])) - - print('\nPassing test data through PT model\n') - with torch.no_grad(): - pt_output = pt_mdl(test_data.permute(0, 3, 2, 1)) - pt_output = [torch.tensor(out) for out in pt_output] - for i in range(len(pt_output)): - if len(pt_output[i].shape) == 4: - pt_output[i] = pt_output[i].permute(0, 3, 2, 1).contiguous() - print('\n'.join([str(o.view(-1)[:10]) for o in pt_output])) - - distance = [(tf_o - pt_o).norm() for tf_o, pt_o in zip(tf_output, pt_output)] - print(f'\nDistance {distance}\n') - - -def load_tf_model_weights(mdl, layer_lookup, tf_mdl_dir, is_resnet=True, arg_num=None): - """Load tensorflow parameters into a pytorch model. - - Arguments: - mdl {torch.nn.Module} -- Pytorch model. - layer_lookup {[type]} -- Dictionary mapping pytorch attribute names to (partial) - tensorflow variable names, and a function suitable for loading weights. - Expects dict of the form {'attr': ['tf_name', function]}. - tf_mdl_dir {str} -- Location of protobuf, checkpoint, meta files. - """ - tf.reset_default_graph() - with tf.Session() as sess: - tf_layers, tf_params, tf_shapes = import_tf_params(tf_mdl_dir, sess) - layer_info = get_layer_indices(layer_lookup, tf_layers) - - for layer_name, info in layer_info.items(): - print(f'Loading {info[0]}/* into {layer_name}') - weights = [tf_params[i] for i in info[2]] - layer = getattr(mdl, layer_name) - info[1](weights, layer) - - test_loaded_params(mdl, tf_params, tf_layers) - - if is_resnet: - compare_model_outputs(mdl, sess, torch.randn(5, 160, 160, 3).detach()) - - -def tensorflow2pytorch(args): - lookup_inception_resnet_v1 = { - 'conv2d_1a': ['InceptionResnetV1/Conv2d_1a_3x3', load_tf_basicConv2d], - 'conv2d_2a': ['InceptionResnetV1/Conv2d_2a_3x3', load_tf_basicConv2d], - 'conv2d_2b': ['InceptionResnetV1/Conv2d_2b_3x3', load_tf_basicConv2d], - 'conv2d_3b': ['InceptionResnetV1/Conv2d_3b_1x1', load_tf_basicConv2d], - 'conv2d_4a': ['InceptionResnetV1/Conv2d_4a_3x3', load_tf_basicConv2d], - 'conv2d_4b': ['InceptionResnetV1/Conv2d_4b_3x3', load_tf_basicConv2d], - 'repeat_1': ['InceptionResnetV1/Repeat/block35', load_tf_repeat_1], - 'mixed_6a': ['InceptionResnetV1/Mixed_6a', load_tf_mixed6a], - 'repeat_2': ['InceptionResnetV1/Repeat_1/block17', load_tf_repeat_2], - 'mixed_7a': ['InceptionResnetV1/Mixed_7a', load_tf_mixed7a], - 'repeat_3': ['InceptionResnetV1/Repeat_2/block8', load_tf_repeat_3], - 'block8': ['InceptionResnetV1/Block8', load_tf_block17_8], - 'last_linear': ['InceptionResnetV1/Bottleneck/weights', load_tf_linear], - 'last_bn': ['InceptionResnetV1/Bottleneck/BatchNorm', load_tf_batchNorm], - # 'logits': ['Logits', load_tf_linear], - } - - print('\nLoad CASIA-Webface-trained weights and save\n') - mdl = InceptionResnetV1(num_classes=10575).eval() - tf_mdl_dir = args.facenet_pb_path - - load_tf_model_weights(mdl, lookup_inception_resnet_v1, tf_mdl_dir) - # print(f'????????') - # data_name = 'casia-webfacexxxxxxx' - # state_dict = mdl.state_dict() - # torch.save(state_dict, f'{tf_mdl_dir}-{data_name}.pt') - - x = torch.rand(64, 3, 160, 160)#.cuda() - # y = resnet(x) - # print(y.shape) - - - f = f"{args.facenet_weights_path}/{args.onnx_save_name}" - torch.onnx.export(mdl, x, f, verbose=False, opset_version=11, - input_names=['input'], output_names=['output'], dynamic_axes=None) - - - -import argparse -def parse_args(): - parser = argparse.ArgumentParser("deploy facenet") - parser.add_argument("--facenet_weights_path", default="", help="onnx model path") - parser.add_argument("--facenet_pb_path", default="", help="") - parser.add_argument("--onnx_save_name", default="", help="") - - return parser.parse_args() -args = parse_args() - -tensorflow2pytorch(args) - - -# device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') -# print('Running on device: {}'.format(device)) - -# # Load pretrained resnet model -# resnet = InceptionResnetV1( -# classify=False, -# pretrained='casia-webface' -# )#.to(device) - -# x = torch.rand(64, 3, 160, 160)#.cuda() -# y = resnet(x) -# print(y.shape) - - -# f = f"{args.facenet_weights_path}/{args.onnx_save_name}" -# torch.onnx.export(resnet, x, f, verbose=False, opset_version=11, input_names=['input'], output_names=['output'], dynamic_axes=None) diff --git a/models/cv/face_recognition/facenet/ixrt/utils.py b/models/cv/face_recognition/facenet/ixrt/utils.py index ab8f213bf6bf629ad073140f4ab886760c707759..f908e887663a97766b5006c4472f373ba71dfa60 100644 --- a/models/cv/face_recognition/facenet/ixrt/utils.py +++ b/models/cv/face_recognition/facenet/ixrt/utils.py @@ -1,18 +1,3 @@ -# Copyright (c) 2024, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - import os import math diff --git a/tests/model_info.json b/tests/model_info.json index 466a81d774f16cd4bb51f104a72368436bd9a228..660bdfcd242623e9e7873cadb21d9bb8b35149b3 100644 --- a/tests/model_info.json +++ b/tests/model_info.json @@ -3254,7 +3254,7 @@ "github_repo": "", "github_branch": "", "github_path": "", - "datasets": "local/tmp", + "datasets": "local/facenet_datasets", "download_url": "https://drive.google.com/open?id=1R77HmFADxe87GmoLwzfgMu_HY0IhcyBz", "need_third_part": "", "precisions": [