diff --git a/research/cv/sknet/infer/convert/atc.sh b/research/cv/sknet/infer/convert/atc.sh new file mode 100644 index 0000000000000000000000000000000000000000..aa8060ab9960145b5007f09903d6c9569a07e97f --- /dev/null +++ b/research/cv/sknet/infer/convert/atc.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +# Copyright 2022 Huawei Technologies Co., Ltd +# +# 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. +# ============================================================================ +model="../data/models/sknet.air" +output="../data/models/sknet" +soc_version=Ascend310 +input_shape="x:32,3,224,224" +# help message +if [[ $1 == --help || $1 == -h ]];then + echo"usage:bash ./ATC_AIR_2_OM.sh <args>" + echo "parameter explain: + --model set model place, default: --model=../data/models/sknet.air + --output set the name and place of OM model, default: --output=../data/models/sknet + --soc_version set the soc_version, default: --soc_version=Ascend310 + --input_shape set the input node and shape, default: --input_shape='x:32,3,224,224' + -h/--help show help message + " + exit 1 +fi + +for para in "$@" +do + if [[ $para == --model* ]];then + model=`echo ${para#*=}` + elif [[ $para == --output* ]];then + output=`echo ${para#*=}` + elif [[ $para == --soc_version* ]];then + soc_version=`echo ${para#*=}` + elif [[ $para == --input_shape* ]];then + input_shape=`echo ${para#*=}` + fi +done + +if [[ $model == "" ]];then + echo "[Error] para \"model \" must be config" + exit 1 +fi + +if [[ $output == "" ]];then + echo "[Error] para \"output \" must be config" + exit 1 +fi + +atc \ + --model=${model} \ + --output=${output} \ + --soc_version=${soc_version} \ + --input_shape=${input_shape} \ + --framework=1 \ + --input_format=NCHW diff --git a/research/cv/sknet/infer/data/config/sknet.cfg b/research/cv/sknet/infer/data/config/sknet.cfg new file mode 100644 index 0000000000000000000000000000000000000000..ce465cf56b7c3b2a4c412576c01201b04848b1f0 --- /dev/null +++ b/research/cv/sknet/infer/data/config/sknet.cfg @@ -0,0 +1,3 @@ +CLASS_NUM=10 +SOFTMAX=false +TOP_K=5 \ No newline at end of file diff --git a/research/cv/sknet/infer/data/config/sknet.pipeline b/research/cv/sknet/infer/data/config/sknet.pipeline new file mode 100644 index 0000000000000000000000000000000000000000..0377d8e31a92a4659c3f1bd2db95cd62460a7f28 --- /dev/null +++ b/research/cv/sknet/infer/data/config/sknet.pipeline @@ -0,0 +1,47 @@ +{ + "im_sknet": { + "stream_config": { + "deviceId": "0" + }, + "appsrc0": { + "props": { + "blocksize": "409600" + }, + "factory": "appsrc", + "next": "mxpi_tensorinfer0" + }, + "mxpi_tensorinfer0": { + "props": { + "dataSource": "appsrc0", + "modelPath": "../data/models/sknet.om", + "waitingTime": "50000", + "outputDeviceId": "-1" + }, + "factory": "mxpi_tensorinfer", + "next": "mxpi_classpostprocessor0" + }, + "mxpi_classpostprocessor0": { + "props": { + "dataSource": "mxpi_tensorinfer0", + "postProcessConfigPath": "../data/config/sknet.cfg", + "labelPath": "../data/config/cifar10.names", + "postProcessLibPath": "libresnet50postprocess.so" + }, + "factory": "mxpi_classpostprocessor", + "next": "mxpi_dataserialize0" + }, + "mxpi_dataserialize0": { + "props": { + "outputDataKeys": "mxpi_classpostprocessor0" + }, + "factory": "mxpi_dataserialize", + "next": "appsink0" + }, + "appsink0": { + "props": { + "blocksize": "4096000" + }, + "factory": "appsink" + } + } +} diff --git a/research/cv/sknet/infer/data/image/unzip_cifar10_test.py b/research/cv/sknet/infer/data/image/unzip_cifar10_test.py new file mode 100644 index 0000000000000000000000000000000000000000..a4e7a83e674786947b8dac364f1cf586e6329882 --- /dev/null +++ b/research/cv/sknet/infer/data/image/unzip_cifar10_test.py @@ -0,0 +1,83 @@ +# Copyright 2022 Huawei Technologies Co., Ltd +# +# 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 argparse +import os +import struct +import cv2 +import numpy as np + + +def _read_a_label(file_object): + raw_label = file_object.read(1) + label = struct.unpack(">B", raw_label) + return label + + +def _read_a_image(file_object): + raw_img = file_object.read(32 * 32) + red_img = struct.unpack(">1024B", raw_img) + + raw_img = file_object.read(32 * 32) + green_img = struct.unpack(">1024B", raw_img) + + raw_img = file_object.read(32 * 32) + blue_img = struct.unpack(">1024B", raw_img) + + img = np.zeros(shape=(1024, 3)) + for i in range(1024): + l = [red_img[i], green_img[i], blue_img[i]] + img[i] = l + img = np.reshape(img, [32, 32, 3]) + return img + + +def save_image(image, file_path): + cv2.imwrite(file_path, image) + + +def unzip(dataset_path, result_path): + if not os.path.exists(dataset_path): + print(f"not such file:{dataset_path}") + exit(-1) + if not os.path.exists(result_path): + os.mkdir(result_path) + if os.path.exists("label.txt"): + os.remove("label.txt") + with open(dataset_path, "rb") as file: + count = 1 + while True: + try: + label = _read_a_label(file) + image = _read_a_image(file) + filename = "img" + str(count) + save_image(image, os.path.join(result_path, filename + ".png")) + print(f"{filename} saved") + with open("label.txt", "a+") as f: + f.write(filename + " " + str(label[0]) + "\n") + + except IOError as err: + print(err) + break + count += 1 + if count > 10000: + return + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description="unzip cifar10 test") + parser.add_argument('--dataset_path', type=str, default='./test_batch.bin', help='path of file "test_batch.bin"') + parser.add_argument('--result_path', type=str, default='./test_batch', help='path of folder to save unzip images') + args_opt = parser.parse_args() + unzip(args_opt.dataset_path, args_opt.result_path) diff --git a/research/cv/sknet/infer/docker_start_infer.sh b/research/cv/sknet/infer/docker_start_infer.sh new file mode 100644 index 0000000000000000000000000000000000000000..4c38dd4a934c2bebdb484e227441a0dc6b327164 --- /dev/null +++ b/research/cv/sknet/infer/docker_start_infer.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash + +# Copyright 2022 Huawei Technologies Co., Ltd +# +# 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. + +docker_image=$1 +data_dir=$2 + +function show_help() { + echo "Usage: docker_start.sh docker_image data_dir" +} + +function param_check() { + if [ -z "${docker_image}" ]; then + echo "please input docker_image" + show_help + exit 1 + fi + + if [ -z "${data_dir}" ]; then + echo "please input data_dir" + show_help + exit 1 + fi +} + +param_check + +docker run -it -u root --ipc=host \ + --device=/dev/davinci0 \ + --device=/dev/davinci_manager \ + --device=/dev/devmm_svm \ + --device=/dev/hisi_hdc \ + -v /usr/local/Ascend/driver:/usr/local/Ascend/driver \ + -v ${data_dir}:${data_dir} \ + ${docker_image} \ + /bin/bash diff --git a/research/cv/sknet/infer/mxbase/CMakeLists.txt b/research/cv/sknet/infer/mxbase/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..ccc171aceadef32c17dac28232be56ed73c8d76f --- /dev/null +++ b/research/cv/sknet/infer/mxbase/CMakeLists.txt @@ -0,0 +1,60 @@ +cmake_minimum_required(VERSION 3.10.0) +project(sknet) + +set(TARGET sknet) + +add_definitions(-DENABLE_DVPP_INTERFACE) +add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0) +add_definitions(-Dgoogle=mindxsdk_private) +add_compile_options(-std=c++11 -fPIE -fstack-protector-all -fPIC -Wall) +add_link_options(-Wl,-z,relro,-z,now,-z,noexecstack -s -pie) + +# Check environment variable +if(NOT DEFINED ENV{ASCEND_HOME}) + message(FATAL_ERROR "please define environment variable:ASCEND_HOME") +endif() +if(NOT DEFINED ENV{ASCEND_VERSION}) + message(WARNING "please define environment variable:ASCEND_VERSION") +endif() +if(NOT DEFINED ENV{ARCH_PATTERN}) + message(WARNING "please define environment variable:ARCH_PATTERN") +endif() + +set(ACL_INC_DIR $ENV{ASCEND_HOME}/$ENV{ASCEND_VERSION}/$ENV{ARCH_PATTERN}/acllib/include) +set(ACL_LIB_DIR $ENV{ASCEND_HOME}/$ENV{ASCEND_VERSION}/$ENV{ARCH_PATTERN}/acllib/lib64) + +set(MXBASE_ROOT_DIR $ENV{MX_SDK_HOME}) +set(MXBASE_INC ${MXBASE_ROOT_DIR}/include) +set(MXBASE_LIB_DIR ${MXBASE_ROOT_DIR}/lib) +set(MXBASE_POST_LIB_DIR ${MXBASE_ROOT_DIR}/lib/modelpostprocessors) +set(MXBASE_POST_PROCESS_DIR ${MXBASE_ROOT_DIR}/include/MxBase/postprocess/include) + +if(DEFINED ENV{MXSDK_OPENSOURCE_DIR}) + set(OPENSOURCE_DIR $ENV{MXSDK_OPENSOURCE_DIR}) +else() + set(OPENSOURCE_DIR ${MXBASE_ROOT_DIR}/opensource) +endif() + + +include_directories(${ACL_INC_DIR}) +include_directories($ENV{ASCEND_HOME}/ascend-toolkit/5.0.4/x86_64-linux/runtime/include) +include_directories(${OPENSOURCE_DIR}/include) +include_directories(${OPENSOURCE_DIR}/include/opencv4) +include_directories(${MXBASE_INC}) +include_directories(${MXBASE_POST_PROCESS_DIR}) + +include_directories($ENV{ASCEND_HOME}/$ENV{ASCEND_VERSION}/x86_64-linux/runtime/include) +link_directories($ENV{ASCEND_HOME}/$ENV{ASCEND_VERSION}/x86_64-linux/x86_64-linux/lib64/) + +link_directories(${ACL_LIB_DIR}) +link_directories(${OPENSOURCE_DIR}/lib) +link_directories(${MXBASE_LIB_DIR}) +link_directories(${MXBASE_POST_LIB_DIR}) + + +add_executable(${TARGET} src/main.cpp src/SKNet.cpp) + +target_link_libraries(${TARGET} glog cpprest mxbase resnet50postprocess opencv_world) + +install(TARGETS ${TARGET} RUNTIME DESTINATION ${PROJECT_SOURCE_DIR}/) + diff --git a/research/cv/sknet/infer/mxbase/build.sh b/research/cv/sknet/infer/mxbase/build.sh new file mode 100644 index 0000000000000000000000000000000000000000..f88a7d12f72d117d67af5e7f8ff61515c3f86834 --- /dev/null +++ b/research/cv/sknet/infer/mxbase/build.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# Copyright 2022 Huawei Technologies Co., Ltd +# +# 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. + +# env + +mkdir -p build +cd build || exit + +function make_plugin() { + if ! cmake ..; + then + echo "cmake failed." + return 1 + fi + + if ! (make); + then + echo "make failed." + return 1 + fi + + return 0 +} + +if make_plugin; +then + echo "INFO: Build successfully." +else + echo "ERROR: Build failed." +fi + +cd - || exit diff --git a/research/cv/sknet/infer/mxbase/src/SKNet.cpp b/research/cv/sknet/infer/mxbase/src/SKNet.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3e91142b4804378f9ae5650c35d31e25b43dfa70 --- /dev/null +++ b/research/cv/sknet/infer/mxbase/src/SKNet.cpp @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2022. Huawei Technologies 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. + */ + +#include "SKNet.h" +#include <memory> +#include <string> +#include <vector> +#include <map> +#include <iostream> +#include "MxBase/DeviceManager/DeviceManager.h" +#include <opencv2/dnn.hpp> +#include "MxBase/Log/Log.h" + +using namespace MxBase; +using namespace cv::dnn; +namespace { + const uint32_t YUV_BYTE_NU = 3; + const uint32_t YUV_BYTE_DE = 2; + const uint32_t VPC_H_ALIGN = 2; + const uint32_t BATCH_SIZE = 32; +} + +APP_ERROR SKNet::Init(const InitParam &initParam) { + deviceId_ = initParam.deviceId; + APP_ERROR ret = MxBase::DeviceManager::GetInstance()->InitDevices(); + if (ret != APP_ERR_OK) { + LogError << "Init devices failed, ret=" << ret << "."; + return ret; + } + ret = MxBase::TensorContext::GetInstance()->SetContext(initParam.deviceId); + if (ret != APP_ERR_OK) { + LogError << "Set context failed, ret=" << ret << "."; + return ret; + } + model_ = std::make_shared<MxBase::ModelInferenceProcessor>(); + ret = model_->Init(initParam.modelPath, modelDesc_); + if (ret != APP_ERR_OK) { + LogError << "ModelInferenceProcessor init failed, ret=" << ret << "."; + return ret; + } + MxBase::ConfigData configData; + const std::string softmax = initParam.softmax ? "true" : "false"; + + configData.SetJsonValue("CLASS_NUM", std::to_string(initParam.classNum)); + configData.SetJsonValue("TOP_K", std::to_string(initParam.topk)); + configData.SetJsonValue("SOFTMAX", softmax); + + auto jsonStr = configData.GetCfgJson().serialize(); + std::map<std::string, std::shared_ptr<void>> config; + config["postProcessConfigContent"] = std::make_shared<std::string>(jsonStr); + config["labelPath"] = std::make_shared<std::string>(initParam.labelPath); + + post_ = std::make_shared<MxBase::Resnet50PostProcess>(); + ret = post_->Init(config); + if (ret != APP_ERR_OK) { + LogError << "PostProcess init failed, ret=" << ret << "."; + return ret; + } + return APP_ERR_OK; +} + +APP_ERROR SKNet::DeInit() { + model_->DeInit(); + post_->DeInit(); + MxBase::DeviceManager::GetInstance()->DestroyDevices(); + return APP_ERR_OK; +} + +APP_ERROR SKNet::ReadImage(const std::string &imgPath, cv::Mat *imageMat) { + *imageMat = cv::imread(imgPath, cv::IMREAD_COLOR); + return APP_ERR_OK; +} + +APP_ERROR SKNet::ProcessImage(const cv::Mat &srcImageMat, cv::Mat &dstImageMat) { + static constexpr uint32_t resizeHeight = 224; + static constexpr uint32_t resizeWidth = 224; + cv::resize(srcImageMat, dstImageMat, cv::Size(resizeWidth, resizeHeight)); + cv::Scalar mean = cv::Scalar(0.4914, 0.4822, 0.4465); + cv::Scalar std = cv::Scalar(0.2023, 0.1994, 0.2010); + dstImageMat = dstImageMat / 255; + dstImageMat = (dstImageMat - mean) / std; + return APP_ERR_OK; +} + +APP_ERROR SKNet::CVMatToTensorBase(const cv::Mat &imageMat, MxBase::TensorBase &tensorBase) { + std::vector<float> dst_data; + std::vector<cv::Mat> bgrChannels(3); + cv::split(imageMat, bgrChannels); + for (unsigned int i = 0; i < bgrChannels.size(); i++) { + std::vector<float> data = std::vector<float>(bgrChannels[i].reshape(1, 1)); + dst_data.insert(dst_data.end(), data.begin(), data.end()); + } + float *buffer = new float[dst_data.size()]; + if (!dst_data.empty()) { + memcpy(buffer, &dst_data[0], dst_data.size()*sizeof(float)); + } + const uint32_t dataSize = 3 * 224 * 224 * 4; + MxBase::MemoryData memoryDataDst(dataSize, MxBase::MemoryData::MEMORY_DEVICE, deviceId_); + MxBase::MemoryData memoryDataSrc(buffer, dataSize, MxBase::MemoryData::MEMORY_HOST_MALLOC); + APP_ERROR ret = MxBase::MemoryHelper::MxbsMallocAndCopy(memoryDataDst, memoryDataSrc); + if (ret != APP_ERR_OK) { + LogError << GetError(ret) << "Memory malloc failed."; + return ret; + } + std::vector<uint32_t> shape = {3, 224, 224}; + tensorBase = MxBase::TensorBase(memoryDataDst, false, shape, MxBase::TENSOR_DTYPE_FLOAT32); + return APP_ERR_OK; +} + +APP_ERROR SKNet::Inference(const std::vector<MxBase::TensorBase> &inputs, + std::vector<MxBase::TensorBase> *outputs) { + auto dtypes = model_->GetOutputDataType(); + for (size_t i = 0; i < modelDesc_.outputTensors.size(); ++i) { + std::vector<uint32_t> shape = {}; + for (size_t j = 0; j < modelDesc_.outputTensors[i].tensorDims.size(); ++j) { + shape.push_back((uint32_t)modelDesc_.outputTensors[i].tensorDims[j]); + } + TensorBase tensor(shape, dtypes[i], MemoryData::MemoryType::MEMORY_DEVICE, deviceId_); + APP_ERROR ret = TensorBase::TensorBaseMalloc(tensor); + if (ret != APP_ERR_OK) { + LogError << "TensorBaseMalloc failed, ret=" << ret << "."; + return ret; + } + outputs->push_back(tensor); + } + DynamicInfo dynamicInfo = {}; + dynamicInfo.dynamicType = DynamicType::STATIC_BATCH; + auto startTime = std::chrono::high_resolution_clock::now(); + APP_ERROR ret = model_->ModelInference(inputs, *outputs, dynamicInfo); + auto endTime = std::chrono::high_resolution_clock::now(); + double costMs = std::chrono::duration<double, std::milli>(endTime - startTime).count(); + inferCostTimeMilliSec += costMs; + if (ret != APP_ERR_OK) { + LogError << "ModelInference failed, ret=" << ret << "."; + return ret; + } + return APP_ERR_OK; +} + +APP_ERROR SKNet::PostProcess(const std::vector<MxBase::TensorBase> &inputs, + std::vector<std::vector<MxBase::ClassInfo>> *clsInfos) { + APP_ERROR ret = post_->Process(inputs, *clsInfos); + if (ret != APP_ERR_OK) { + LogError << "Process failed, ret=" << ret << "."; + return ret; + } + return APP_ERR_OK; +} + +APP_ERROR SKNet::SaveResult(const std::vector<std::string> &batchImgPaths, + const std::vector<std::vector<MxBase::ClassInfo>> &batchClsInfos) { + uint32_t batchIndex = 0; + for (auto &imgPath : batchImgPaths) { + std::string fileName = imgPath.substr(imgPath.find_last_of("/") + 1); + size_t dot = fileName.find_last_of("."); + std::string resFileName = "./results/" + fileName.substr(0, dot) + ".txt"; + std::ofstream outfile(resFileName); + if (outfile.fail()) { + LogError << "Failed to open result file: "; + return APP_ERR_COMM_FAILURE; + } + auto clsInfos = batchClsInfos[batchIndex]; + std::string resultStr; + for (auto clsInfo : clsInfos) { + LogDebug << " className:" << clsInfo.className << " confidence:" << clsInfo.confidence << + " classIndex:" << clsInfo.classId; + resultStr += std::to_string(clsInfo.classId) + " "; + } + outfile << resultStr << std::endl; + batchIndex++; + outfile.close(); + } + return APP_ERR_OK; +} + +APP_ERROR SKNet::Process(const std::vector<std::string> &batchImgPaths) { + APP_ERROR ret = APP_ERR_OK; + std::vector<MxBase::TensorBase> inputs = {}; + std::vector<MxBase::TensorBase> outputs = {}; + std::vector<MxBase::TensorBase> batchImgMat = {}; + for (auto &imgPath : batchImgPaths) { + cv::Mat imageMat; + ret = ReadImage(imgPath, &imageMat); + if (ret != APP_ERR_OK) { + LogError << "ReadImage failed, ret=" << ret << "."; + return ret; + } + imageMat.convertTo(imageMat, CV_32F); + ret = ProcessImage(imageMat, imageMat); + if (ret != APP_ERR_OK) { + LogError << "ProcessImage failed, ret=" << ret << "."; + return ret; + } + MxBase::TensorBase tensorBase; + ret = CVMatToTensorBase(imageMat, tensorBase); + if (ret != APP_ERR_OK) { + LogError << "CVMatToTensorBase failed, ret=" << ret << "."; + return ret; + } + + batchImgMat.push_back(tensorBase); + } + MxBase::TensorBase tensorBase; + tensorBase.BatchStack(batchImgMat, tensorBase); + inputs.push_back(tensorBase); + auto startTime = std::chrono::high_resolution_clock::now(); + ret = Inference(inputs, &outputs); + auto endTime = std::chrono::high_resolution_clock::now(); + double costMs = std::chrono::duration<double, std::milli>(endTime - startTime).count(); + inferCostTimeMilliSec += costMs; + if (ret != APP_ERR_OK) { + LogError << "Inference failed, ret=" << ret << "."; + return ret; + } + std::vector<std::vector<MxBase::ClassInfo>> BatchClsInfos = {}; + ret = PostProcess(outputs, &BatchClsInfos); + if (ret != APP_ERR_OK) { + LogError << "PostProcess failed, ret=" << ret << "."; + return ret; + } + ret = SaveResult(batchImgPaths, BatchClsInfos); + if (ret != APP_ERR_OK) { + LogError << "Save infer results into file failed. ret = " << ret << "."; + return ret; + } + return APP_ERR_OK; +} diff --git a/research/cv/sknet/infer/mxbase/src/SKNet.h b/research/cv/sknet/infer/mxbase/src/SKNet.h new file mode 100644 index 0000000000000000000000000000000000000000..9d0f4f681671eb0dfa4018c7d83c66c679c21b7c --- /dev/null +++ b/research/cv/sknet/infer/mxbase/src/SKNet.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2022. Huawei Technologies 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. + */ + +#ifndef MXBASE_SKNet_H +#define MXBASE_SKNet_H +#include <memory> +#include <string> +#include <vector> +#include <opencv2/opencv.hpp> +#include "MxBase/DvppWrapper/DvppWrapper.h" +#include "MxBase/ModelInfer/ModelInferenceProcessor.h" +#include "ClassPostProcessors/Resnet50PostProcess.h" +#include "MxBase/Tensor/TensorContext/TensorContext.h" + +struct InitParam { + uint32_t deviceId; + std::string labelPath; + uint32_t classNum; + uint32_t topk; + bool softmax; + bool checkTensor; + std::string modelPath; +}; + +class SKNet { + public: + APP_ERROR Init(const InitParam &initParam); + APP_ERROR DeInit(); + APP_ERROR ReadImage(const std::string &imgPath, cv::Mat *imageMat); + APP_ERROR ProcessImage(const cv::Mat &srcImageMat, cv::Mat &dstImageMat); + APP_ERROR CVMatToTensorBase(const cv::Mat &imageMat, MxBase::TensorBase &tensorBase); + APP_ERROR Inference(const std::vector<MxBase::TensorBase> &inputs, std::vector<MxBase::TensorBase> *outputs); + APP_ERROR PostProcess(const std::vector<MxBase::TensorBase> &inputs, + std::vector<std::vector<MxBase::ClassInfo>> *clsInfos); + APP_ERROR Process(const std::vector<std::string> &batchImgPaths); + // get infer time + double GetInferCostMilliSec() const {return inferCostTimeMilliSec;} + + private: + APP_ERROR SaveResult(const std::vector<std::string> &batchImgPaths, + const std::vector<std::vector<MxBase::ClassInfo>> &batchClsInfos); + + private: + std::shared_ptr<MxBase::ModelInferenceProcessor> model_; + std::shared_ptr<MxBase::Resnet50PostProcess> post_; + MxBase::ModelDesc modelDesc_; + uint32_t deviceId_ = 0; + // infer time + double inferCostTimeMilliSec = 0.0; +}; + +#endif diff --git a/research/cv/sknet/infer/mxbase/src/main.cpp b/research/cv/sknet/infer/mxbase/src/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7d784a8fc404b65b564ca2dc020589e96d069bf1 --- /dev/null +++ b/research/cv/sknet/infer/mxbase/src/main.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2022. Huawei Technologies 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. + */ + +#include <dirent.h> +#include "MxBase/Log/Log.h" +#include "SKNet.h" + +namespace { + const uint32_t CLASS_NUM = 10; + const uint32_t BATCH_SIZE = 32; +} // namespace + +APP_ERROR ScanImages(const std::string &path, std::vector<std::string> *imgFiles) { + DIR *dirPtr = opendir(path.c_str()); + if (dirPtr == nullptr) { + LogError << "opendir failed. dir:" << path; + return APP_ERR_INTERNAL_ERROR; + } + dirent *direntPtr = nullptr; + while ((direntPtr = readdir(dirPtr)) != nullptr) { + std::string fileName = direntPtr->d_name; + if (fileName == "." || fileName == "..") { + continue; + } + + imgFiles->push_back(path + "/" + fileName); + } + closedir(dirPtr); + return APP_ERR_OK; +} + +int main(int argc, char* argv[]) { + if (argc <= 1) { + LogWarn << "Please input image path, such as '../data/image/test_batch'."; + return APP_ERR_OK; + } + + InitParam initParam = {}; + initParam.deviceId = 0; + initParam.classNum = CLASS_NUM; + initParam.labelPath = "../data/config/cifar10.names"; + initParam.topk = 5; + initParam.softmax = false; + initParam.checkTensor = true; + initParam.modelPath = "../data/models/sknet.om"; + auto sknet = std::make_shared<SKNet>(); + APP_ERROR ret = sknet->Init(initParam); + if (ret != APP_ERR_OK) { + LogError << "SKNetClassify init failed, ret=" << ret << "."; + return ret; + } + + std::string imgPath = argv[1]; + std::vector<std::string> imgFilePaths; + ret = ScanImages(imgPath, &imgFilePaths); + if (ret != APP_ERR_OK) { + return ret; + } + int inferImgsCount = 0; + LogInfo << "Number of total images load from input data path: " << imgFilePaths.size(); + for (uint32_t i = 0; i <= imgFilePaths.size() - BATCH_SIZE; i += BATCH_SIZE) { + std::vector<std::string>batchImgFilePaths(imgFilePaths.begin()+i, imgFilePaths.begin()+(i+BATCH_SIZE)); + ret = sknet->Process(batchImgFilePaths); + if (ret != APP_ERR_OK) { + LogError << "SKNetClassify process failed, ret=" << ret << "."; + sknet->DeInit(); + return ret; + } + inferImgsCount += BATCH_SIZE; + } + + sknet->DeInit(); + double fps = 1000.0 * inferImgsCount / sknet->GetInferCostMilliSec(); + LogInfo << "[Process Delay] cost: " << sknet->GetInferCostMilliSec() << " ms\tfps: " << fps << " imgs/sec"; + return APP_ERR_OK; +} diff --git a/research/cv/sknet/infer/result_statistics/classification_task_metric.py b/research/cv/sknet/infer/result_statistics/classification_task_metric.py new file mode 100644 index 0000000000000000000000000000000000000000..26461e88744d183f415c11abaa5418d96ffc82ba --- /dev/null +++ b/research/cv/sknet/infer/result_statistics/classification_task_metric.py @@ -0,0 +1,145 @@ +# coding = utf-8 +# Copyright 2022 Huawei Technologies Co., Ltd +# +# Licensed under the BSD 3-Clause License (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://opensource.org/licenses/BSD-3-Clause +# +# 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 sys +import json +import numpy as np + +np.set_printoptions(threshold=sys.maxsize) + + +def cre_groundtruth_dict_fromtxt(gtfile_path): + """ + :param filename: file contains the imagename and label number + :return: dictionary key imagename, value is label number + """ + img_gt_dict = {} + with open(gtfile_path, 'r') as f: + for line in f.readlines(): + temp = line.strip().split() + img_name = temp[0].split(".")[0] + img_lab = temp[1] + img_gt_dict[img_name] = img_lab + return img_gt_dict + + +def load_statistical_predict_result(filepath): + """ + function: + the prediction result file data extraction + input: + result file:filepath + output: + n_label:number of label + data_vec: the probability of prediction in the 1000 + :return: probabilities, number of label, in_type, color + """ + with open(filepath, 'r') as f: + data = f.readline() + temp = data.strip().split(" ") + n_label = len(temp) + data_vec = np.zeros((n_label), dtype=np.float32) + for ind, cls_ind in enumerate(temp): + data_vec[ind] = np.int32(cls_ind) + return data_vec, n_label + + +def create_visualization_statistical_result(prediction_file_path, + rst_store_path, js_file_name, + img_gt_dict, topn=5): + """ + :param prediction_file_path: + :param result_store_path: + :param json_file_name: + :param img_gt_dict: + :param topn: + :return: + """ + writer = open(os.path.join(rst_store_path, js_file_name), 'w') + table_dict = {} + table_dict["title"] = "Overall statistical evaluation" + table_dict["value"] = [] + + count = 0 + res_cnt = 0 + n_labels = "" + count_hit = np.zeros(topn) + for tfile_name in os.listdir(prediction_file_path): + count += 1 + img_name = tfile_name.split(".")[0] + filepath = os.path.join(prediction_file_path, tfile_name) + + ret = load_statistical_predict_result(filepath) + prediction = ret[0] + n_labels = ret[1] + gt = img_gt_dict[img_name] + real_label = int(gt) + + res_cnt = min(len(prediction), topn) + for i in range(res_cnt): + if str(real_label) == str(int(prediction[i])): + count_hit[i] += 1 + break + if 'value' not in table_dict.keys(): + print("the item value does not exist!") + else: + table_dict["value"].extend( + [{"key": "Number of images", "value": str(count)}, + {"key": "Number of classes", "value": str(n_labels)}]) + if count == 0: + accuracy = 0 + else: + accuracy = np.cumsum(count_hit) / count + for i in range(res_cnt): + table_dict["value"].append({"key": "Top" + str(i + 1) + " accuracy", + "value": str( + round(accuracy[i] * 100, 2)) + '%'}) + json.dump(table_dict, writer) + writer.write("\n") + writer.close() + + +if __name__ == '__main__': + try: + # txt file path + folder_davinci_target = sys.argv[1] + # annotation files path, "val_label.txt" + annotation_file_path = sys.argv[2] + # the path to store the results json path + result_json_path = sys.argv[3] + # result json file name + json_file_name = sys.argv[4] + except IndexError: + print("Please enter target file result folder path | ground truth label file path | result json file path | " + "result json file name,\n" + "such as '../sdk/results/ ../data/image/label.txt ./ sdk.json'\n" + "or\n" + "'../mxbase/results/ ../data/image/label.txt ./ mxbase.json'") + exit(1) + + if not os.path.exists(folder_davinci_target): + print("Target file folder does not exist.") + + if not os.path.exists(annotation_file_path): + print("Ground truth file does not exist.") + + if not os.path.exists(result_json_path): + print("Result folder doesn't exist.") + + img_label_dict = cre_groundtruth_dict_fromtxt(annotation_file_path) + create_visualization_statistical_result(folder_davinci_target, + result_json_path, json_file_name, + img_label_dict, topn=5) diff --git a/research/cv/sknet/infer/sdk/infer.py b/research/cv/sknet/infer/sdk/infer.py new file mode 100644 index 0000000000000000000000000000000000000000..16a7db53e475f97790dd9438f83dd9edf0ed627f --- /dev/null +++ b/research/cv/sknet/infer/sdk/infer.py @@ -0,0 +1,126 @@ +# Copyright 2022 Huawei Technologies Co., Ltd +# +# 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. +# ============================================================================ +""" Model Infer """ +import json +import logging +import numpy as np +import MxpiDataType_pb2 as MxpiDataType +from StreamManagerApi import StreamManagerApi, MxDataInput, InProtobufVector, MxProtobufIn, StringVector + + +class SdkApi: + """ Class SdkApi """ + INFER_TIMEOUT = 50000 + STREAM_NAME = 'im_sknet' + + def __init__(self, pipeline_cfg): + self.pipeline_cfg = pipeline_cfg + self._stream_api = None + self._data_input = None + self._device_id = None + + def init(self): + """ Initialize Stream """ + with open(self.pipeline_cfg, 'r') as fp: + self._device_id = int( + json.loads(fp.read())[self.STREAM_NAME]["stream_config"] + ["deviceId"]) + print(f"The device id: {self._device_id}.") + + # create api + self._stream_api = StreamManagerApi() + + # init stream mgr + ret = self._stream_api.InitManager() + if ret != 0: + print(f"Failed to init stream manager, ret={ret}.") + return False + + # create streams + with open(self.pipeline_cfg, 'rb') as fp: + pipe_line = fp.read() + + ret = self._stream_api.CreateMultipleStreams(pipe_line) + if ret != 0: + print(f"Failed to create stream, ret={ret}.") + return False + + self._data_input = MxDataInput() + return True + + def __del__(self): + if not self._stream_api: + return + + self._stream_api.DestroyAllStreams() + + def _send_protobuf(self, stream_name, plugin_id, element_name, buf_type, + pkg_list): + """ Send Stream """ + protobuf = MxProtobufIn() + protobuf.key = element_name.encode("utf-8") + protobuf.type = buf_type + protobuf.protobuf = pkg_list.SerializeToString() + protobuf_vec = InProtobufVector() + protobuf_vec.push_back(protobuf) + err_code = self._stream_api.SendProtobuf(stream_name, plugin_id, + protobuf_vec) + if err_code != 0: + logging.error( + "Failed to send data to stream, stream_name(%s), plugin_id(%s), element_name(%s), " + "buf_type(%s), err_code(%s).", stream_name, plugin_id, + element_name, buf_type, err_code) + return False + return True + + def send_tensor_input(self, stream_name, plugin_id, element_name, + input_data, data_type, batch_size): + tensor_list = MxpiDataType.MxpiTensorPackageList() + for i in range(batch_size): + data = np.expand_dims(input_data[i, :], 0) + tensor_pkg = tensor_list.tensorPackageVec.add() + # init tensor vector + tensor_vec = tensor_pkg.tensorVec.add() + tensor_vec.deviceId = self._device_id + tensor_vec.memType = 0 + tensor_vec.tensorShape.extend(data.shape) + tensor_vec.tensorDataType = data_type + tensor_vec.dataStr = data.tobytes() + tensor_vec.tensorDataSize = data.shape[0] + # tensor_vec.tensorDataSize = data.size + # print("*"*30+str(data.shape)+"*"*30) + print(type(tensor_list)) + buf_type = b"MxTools.MxpiTensorPackageList" + return self._send_protobuf(stream_name, plugin_id, element_name, + buf_type, tensor_list) + + def get_result(self, stream_name, out_plugin_id=0): + """ Get Result """ + keys = [b"mxpi_tensorinfer0"] + keyVec = StringVector() + for key in keys: + keyVec.push_back(key) + infer_result = self._stream_api.GetProtobuf(stream_name, 0, keyVec) + if infer_result.size() == 0: + print("infer_result is null") + exit() + + if infer_result[0].errorCode != 0: + print("GetProtobuf error. errorCode=%d" % ( + infer_result[0].errorCode)) + exit() + TensorList = MxpiDataType.MxpiTensorPackageList() + TensorList.ParseFromString(infer_result[0].messageBuf) + return TensorList diff --git a/research/cv/sknet/infer/sdk/main.py b/research/cv/sknet/infer/sdk/main.py new file mode 100644 index 0000000000000000000000000000000000000000..65418f53c3ba2ba287f9f46f41bb4660bd3e996e --- /dev/null +++ b/research/cv/sknet/infer/sdk/main.py @@ -0,0 +1,120 @@ +# Copyright 2022 Huawei Technologies Co., Ltd +# +# 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. +# ============================================================================ +""" Model Main """ +import argparse +import os +import time +import numpy as np +from infer import SdkApi +import cv2 + + +def parse_args(): + """set and check parameters.""" + parser = argparse.ArgumentParser(description="sknet process") + parser.add_argument("--pipeline_path", type=str, default="../data/config/sknet.pipeline", help="SDK infer pipeline") + parser.add_argument("--data_dir", type=str, default="../data/image/test_batch/", + help="Dataset contain batch_spare batch_label batch_dense") + parser.add_argument("--batch_size", type=int, default=32) + parser.add_argument("--result_dir", type=str, default="./results", + help="cache dir of inference result. The default is './results'.") + args_opt = parser.parse_args() + return args_opt + + +def image_proc(img_path, bgr2rgb=False, dsize=(224, 224), rescale=1.0 / 255.0, mean=(0.4914, 0.4822, 0.4465), + std=(0.2023, 0.1994, 0.2010)): + ''' get input data ''' + data_numpy = cv2.imread( + img_path, cv2.IMREAD_UNCHANGED) + + if bgr2rgb: + data_numpy = cv2.cvtColor(data_numpy, cv2.COLOR_BGR2RGB) + + if data_numpy is None: + raise ValueError('Fail to read {}'.format(img_path)) + + data_numpy = cv2.resize(data_numpy, dsize=dsize, interpolation=cv2.INTER_LINEAR) + data_numpy = data_numpy * rescale + data_numpy = (data_numpy - mean) / std + data_numpy = data_numpy.transpose(2, 0, 1) + return data_numpy + + +def inference(pipeline_path, stream_name, batch_size): + args_ = parse_args() + # init stream manager + sdk_api = SdkApi(pipeline_path) + if not sdk_api.init(): + exit(-1) + dir_name = args_.data_dir + file_list = os.listdir(dir_name) + if not os.path.exists(args_.result_dir): + os.makedirs(args_.result_dir) + cnt = 0 + data_input = list() + file_name_list = list() + if os.path.exists("result.txt"): + os.remove("result.txt") + for file_name in file_list: + file_path = os.path.join(dir_name, file_name) + if not (file_name.lower().endswith(".jpg") or file_name.lower().endswith(".jpeg") or + file_name.lower().endswith(".png")): + continue + file_name_list.append(file_name.split(".")[0]) + start_time = time.time() + data_input.append(image_proc(file_path)) + cnt += 1 + if cnt % batch_size != 0: + continue + data_input = np.array(data_input, dtype=np.float32) + sdk_api.send_tensor_input(stream_name, 0, "appsrc0", data_input, 0, batch_size) + data_input = list() + result = sdk_api.get_result(stream_name) + pred = np.array( + [np.frombuffer(result.tensorPackageVec[i].tensorVec[0].dataStr, dtype=np.float32) for i in + range(batch_size)]) + with open('result.txt', 'a+') as f: + for i in range(batch_size): + f.write(file_name_list[i] + ":") + for j in range(10): + f.write(str(pred[i][j]) + " ") + f.write("\n") + file_name_list.clear() + end_time = time.time() - start_time + print(f"image {cnt - batch_size}:{cnt} run time {end_time}") + + +def save_result(result_dir, top_n): + with open("result.txt", "r") as f: + for line in f.readlines(): + file_name = line.split(":")[0] + data = line.split(":")[1].strip().split(" ") + confidences = {} + for i in range(len(data)): + confidences[i] = np.float32(data[i]) + confidences = sorted(confidences.items(), key=lambda x: x[1], reverse=True) + top = list() + for i in range(top_n): + top.append(str(confidences[i][0])) + with open(result_dir + "/" + file_name + ".txt", "w") as f_write: + f_write.writelines(" ".join(top)) + + +if __name__ == "__main__": + args = parse_args() + args.stream_name = b'im_sknet' + inference(args.pipeline_path, args.stream_name, args.batch_size) + save_result(args.result_dir, 5) diff --git a/research/cv/sknet/infer/sdk/run.sh b/research/cv/sknet/infer/sdk/run.sh new file mode 100644 index 0000000000000000000000000000000000000000..84dbde9fe1c44dcb1fefa815ae008f732051081d --- /dev/null +++ b/research/cv/sknet/infer/sdk/run.sh @@ -0,0 +1,17 @@ +#!/usr/bin/bash +set -e + +# Simple log helper functions +info() { echo -e "\033[1;34m[INFO ][MxStream] $1\033[1;37m" ; } +warn() { echo >&2 -e "\033[1;31m[WARN ][MxStream] $1\033[1;37m" ; } + +export LD_LIBRARY_PATH=${MX_SDK_HOME}/lib:${MX_SDK_HOME}/opensource/lib:${MX_SDK_HOME}/opensource/lib64:/usr/local/Ascend/ascend-toolkit/latest/acllib/lib64:${LD_LIBRARY_PATH} +export GST_PLUGIN_SCANNER=${MX_SDK_HOME}/opensource/libexec/gstreamer-1.0/gst-plugin-scanner +export GST_PLUGIN_PATH=${MX_SDK_HOME}/opensource/lib/gstreamer-1.0:${MX_SDK_HOME}/lib/plugins + +#to set PYTHONPATH, import the StreamManagerApi.py +export PYTHONPATH=$PYTHONPATH:${MX_SDK_HOME}/python + +python3 main.py +exit 0 + diff --git a/research/cv/sknet/modelarts/start.py b/research/cv/sknet/modelarts/start.py new file mode 100644 index 0000000000000000000000000000000000000000..697a34336a4779dc424b45cf42bdd64da9ba39b8 --- /dev/null +++ b/research/cv/sknet/modelarts/start.py @@ -0,0 +1,223 @@ +# Copyright 2022 Huawei Technologies Co., Ltd +# +# 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. +# ============================================================================ +"""train net.""" +import os +import argparse +import ast +import glob +import datetime +import numpy as np +import moxing as mox +from mindspore import context +from mindspore import Tensor, export +from mindspore.nn.optim.momentum import Momentum +from mindspore.train.model import Model +from mindspore.context import ParallelMode +from mindspore.nn.loss import SoftmaxCrossEntropyWithLogits +from mindspore.train.callback import ModelCheckpoint, CheckpointConfig, LossMonitor, TimeMonitor +from mindspore.train.loss_scale_manager import FixedLossScaleManager +from mindspore.train.serialization import load_checkpoint, load_param_into_net +from mindspore.communication.management import init +from mindspore.common import set_seed +from mindspore.parallel import set_algo_parameters +import mindspore.nn as nn +import mindspore.common.initializer as weight_init +from src.lr_generator import get_lr +from src.CrossEntropySmooth import CrossEntropySmooth +from src.var_init import KaimingNormal + + +def obs_data2modelarts(FLAGS): + """ + Copy train data from obs to modelarts by using moxing api. + """ + start_ = datetime.datetime.now() + print("===>>>Copy files from obs:{} to modelarts dir:{}".format(FLAGS.dataset_path, FLAGS.modelarts_data_dir)) + mox.file.copy_parallel(src_url=FLAGS.dataset_path, dst_url=FLAGS.modelarts_data_dir) + end_ = datetime.datetime.now() + print("===>>>Copy from obs to modelarts, time use:{}(s)".format((end_ - start_).seconds)) + files = os.listdir(FLAGS.modelarts_data_dir) + print("===>>>Files:", files) + if FLAGS.pre_trained: + print("Copy ckpt from bos to modelarts") + mox.file.copy_parallel(src_url=FLAGS.ckpt_path, dst_url=FLAGS.modelarts_ckpt_dir) + files = os.listdir(FLAGS.modelarts_ckpt_dir) + print("===>>>Files:", files) + + +def modelarts_result2obs(FLAGS): + """ + Copy debug data from modelarts to obs. + According to the switch flags, the debug data may contains auto tune repository, + dump data for precision comparison, even the computation graph and profiling data. + """ + + mox.file.copy_parallel(src_url=FLAGS.modelarts_result_dir, dst_url=FLAGS.train_url) + print("===>>>Copy Event or Checkpoint from modelarts dir:{} to obs:{}".format(FLAGS.modelarts_result_dir, + FLAGS.train_url)) + files = os.listdir() + print("===>>>current Files:", files) + mox.file.copy(src_url='sknet.air', dst_url=FLAGS.train_url + '/sknet.air') + + +def export_AIR(args_opt_, cfg): + """start modelarts export""" + ckpt_list = glob.glob(args_opt_.modelarts_result_dir + "/sknet*.ckpt") + if not ckpt_list: + print("ckpt file not generated.") + + ckpt_list.sort(key=os.path.getmtime) + ckpt_model = ckpt_list[-1] + print("checkpoint path", ckpt_model) + + net_ = sknet(cfg.class_num) + param_dict_ = load_checkpoint(ckpt_model) + load_param_into_net(net_, param_dict_) + input_arr = Tensor(np.zeros([32, 3, 224, 224], np.float32)) + export(net_, input_arr, file_name="sknet", file_format='AIR') + + +if __name__ == '__main__': + code_dir = os.path.dirname(__file__) + work_dir = os.getcwd() + print("===>>>code_dir:{}, work_dir:{}".format(code_dir, work_dir)) + + parser = argparse.ArgumentParser(description='Image classification') + parser.add_argument("--train_url", type=str, default="./output") + parser.add_argument("--modelarts_data_dir", type=str, default="/cache/dataset") + parser.add_argument("--modelarts_result_dir", type=str, default="/cache/result") + parser.add_argument("--modelarts_ckpt_dir", type=str, default="/cache/ckpt") + parser.add_argument("--ckpt_path", type=str, default="./ckpt") + parser.add_argument('--net', type=str, default="sknet50", help='sknet Model') + parser.add_argument('--dataset', type=str, default="cifar10", help='Dataset, either cifar10 or imagenet2012') + parser.add_argument('--run_distribute', type=ast.literal_eval, default=False, help='Run distribute') + parser.add_argument('--device_id', type=int, default=0, help='Device id.') + parser.add_argument('--device_num', type=int, default=1, help='Device num.') + parser.add_argument('--epoch_size', type=int, default=90, help='Size of train epoch.') + parser.add_argument('--dataset_path', type=str, default="/path/to/cifar10", help='Dataset path') + parser.add_argument('--device_target', type=str, default='Ascend', choices="Ascend", + help="Device target, support Ascend.") + parser.add_argument('--pre_trained', type=str, default=None, help='Pretrained checkpoint path') + parser.add_argument('--parameter_server', type=ast.literal_eval, default=False, help='Run parameter server train') + args_opt = parser.parse_args() + set_seed(1) + target = args_opt.device_target + + if args_opt.net == "sknet50": + from src.sknet50 import sknet50 as sknet + + if args_opt.dataset == "cifar10": + from src.config import config1 as config + from src.dataset import create_dataset_cifar10 as create_dataset + + obs_data2modelarts(args_opt) + + ckpt_save_dir = args_opt.modelarts_result_dir + # init context + context.set_context(mode=context.GRAPH_MODE, device_target=target, save_graphs=False) + if args_opt.parameter_server: + context.set_ps_context(enable_ps=True) + if args_opt.run_distribute: + device_id = int(os.getenv('DEVICE_ID')) + context.set_context(device_id=device_id) + context.set_auto_parallel_context(device_num=args_opt.device_num, parallel_mode=ParallelMode.DATA_PARALLEL, + gradients_mean=True) + set_algo_parameters(elementwise_op_strategy_follow=True) + if args_opt.net == "sknet50": + context.set_auto_parallel_context(all_reduce_fusion_config=[85, 160]) + init() + else: + device_id = args_opt.device_id + context.set_context(device_id=device_id) + # create dataset + dataset = create_dataset(dataset_path=args_opt.modelarts_data_dir, do_train=True, repeat_num=1, + batch_size=config.batch_size, target=target, distribute=args_opt.run_distribute) + step_size = dataset.get_dataset_size() + print(step_size) + # define net + net = sknet(class_num=config.class_num) + if args_opt.parameter_server: + net.set_param_ps() + + # init weight + if args_opt.pre_trained: + param_dict = load_checkpoint(args_opt.modelarts_ckpt_dir + '/' + args_opt.pre_trained) + load_param_into_net(net, param_dict) + else: + for _, cell in net.cells_and_names(): + if isinstance(cell, nn.Conv2d): + cell.weight.set_data(weight_init.initializer(KaimingNormal(mode='fan_out'), + cell.weight.shape, + cell.weight.dtype)) + if isinstance(cell, nn.Dense): + cell.weight.set_data(weight_init.initializer(weight_init.TruncatedNormal(), + cell.weight.shape, + cell.weight.dtype)) + + # init lr + lr = get_lr(lr_init=config.lr_init, lr_end=config.lr_end, lr_max=config.lr_max, + warmup_epochs=config.warmup_epochs, total_epochs=args_opt.epoch_size, steps_per_epoch=step_size, + lr_decay_mode=config.lr_decay_mode) + lr = Tensor(lr) + + # define opt + decayed_params = [] + no_decayed_params = [] + for param in net.trainable_params(): + if 'beta' not in param.name and 'gamma' not in param.name and 'bias' not in param.name: + decayed_params.append(param) + else: + no_decayed_params.append(param) + + group_params = [{'params': decayed_params, 'weight_decay': config.weight_decay}, + {'params': no_decayed_params}, + {'order_params': net.trainable_params()}] + # define loss, model + if args_opt.dataset == "imagenet": + opt = nn.SGD(group_params, lr, config.momentum, loss_scale=config.loss_scale) + if not config.use_label_smooth: + config.label_smooth_factor = 0.0 + loss = CrossEntropySmooth(sparse=True, reduction="mean", + smooth_factor=config.label_smooth_factor, num_classes=config.class_num) + else: + opt = Momentum(group_params, lr, config.momentum, loss_scale=config.loss_scale) + loss = SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean') + loss_scale = FixedLossScaleManager(config.loss_scale, drop_overflow_update=False) + model = Model(net, loss_fn=loss, optimizer=opt, loss_scale_manager=loss_scale, metrics={'acc'}, + amp_level="O2", keep_batchnorm_fp32=False) + + # define callbacks + time_cb = TimeMonitor(data_size=step_size) + loss_cb = LossMonitor() + cb = [time_cb, loss_cb] + if config.save_checkpoint: + config_ck = CheckpointConfig(save_checkpoint_steps=config.save_checkpoint_epochs * step_size, + keep_checkpoint_max=config.keep_checkpoint_max) + ckpt_cb = ModelCheckpoint(prefix="sknet", directory=ckpt_save_dir, config=config_ck) + cb += [ckpt_cb] + + # train model + model.train(args_opt.epoch_size - config.pretrain_epoch_size, dataset, callbacks=cb, + sink_size=dataset.get_dataset_size(), dataset_sink_mode=True) + + ## start export air + if device_id == 0: + print("start to export air model") + start = datetime.datetime.now() + export_AIR(args_opt, config) + end = datetime.datetime.now() + print("===>>end up exporting air model, time use:{}(s)".format((end - start).seconds)) + ## copy result from modelarts to obs + modelarts_result2obs(args_opt) diff --git a/research/cv/sknet/scripts/docker_start.sh b/research/cv/sknet/scripts/docker_start.sh new file mode 100644 index 0000000000000000000000000000000000000000..6b452b3d3f4b1596501ed63d6047052717115c0f --- /dev/null +++ b/research/cv/sknet/scripts/docker_start.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# Copyright (c) 2022. Huawei Technologies Co., Ltd +# +# 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. +# ============================================================================ + +docker_image=$1 +data_dir=$2 +model_dir=$3 + +docker run -it -u root --ipc=host \ + --device=/dev/davinci0 \ + --device=/dev/davinci1 \ + --device=/dev/davinci2 \ + --device=/dev/davinci3 \ + --device=/dev/davinci4 \ + --device=/dev/davinci5 \ + --device=/dev/davinci6 \ + --device=/dev/davinci7 \ + --device=/dev/davinci_manager \ + --device=/dev/devmm_svm \ + --device=/dev/hisi_hdc \ + --privileged \ + -v /usr/local/Ascend/driver:/usr/local/Ascend/driver \ + -v /usr/local/Ascend/add-ons/:/usr/local/Ascend/add-ons \ + -v ${data_dir}:${data_dir} \ + -v ${model_dir}:${model_dir} \ + -v /root/ascend/log:/root/ascend/log ${docker_image} /bin/bash \ No newline at end of file