2023-03-21最適化された(ネットワーク構造が変更された)YOLO モデルを tensorrt モデルに変換するにはどうすればよいですか?

ヒント: 自己トレーニングされた yolo モデルを tensorrt 関連のモデルに変換する方法に関する記事を以前に書きました。yolo モデルは元のネットワーク構造を変更せずに使用するため、関連する変換プロセスは段階的に行うだけで済みます。 , いくつかの修正が加えられています. パラメーターは十分です. 詳細については、リンクを参照してください: https://blog.csdn.net/LJ1120142576/article/details/127614612 . 今日書かれたメソッドは、以前のものに基づいています。 yolo モデル、特にネットワーク構造の最適化です. yolo モデルでは、活性化関数と活性化関数にいくつかの変更があります. 以下に具体的な方法を紹介します (主に yolov3-tiny モデルの最適化に焦点を当てます)

1. yolov3-tiny最適化のポイント

1) Leaky 活性化関数を mish に変更します
: ただし、tensorrt は mish 活性化関数をサポートしていないため、後で mish 活性化関数を実装する方法を見つける必要があります 2
) 1x1 畳み込みネットワークを yolov3-tiny に追加しますネットワークの深さを増やし、計算量を削減します。
詳細なネットワーク構造図については、下の図を参照してください。
この図は、netron ソフトウェアで .cfg ファイルを開くと実現されます。Netron Web バージョンのリンク: https://netron.アプリ/
ここに画像の説明を挿入します

2. 最適化された yolov3-tiny を tensorrt 関連モデル (.trt) に変換します。

1) yolov3-tiny.pt を .wts モデルに変換します。
この手順はhttps://blog.csdn.net/LJ1120142576/article/details/127614612の内容と同じです。変更はありません。操作
2 ) のこの記事の内容 .wts モデルを .trt モデルに変換する
この部分の操作はhttps://blog.csdn.net/LJ1120142576/article/details/127614612の手順とも一致しますが、次の操作が必要です。これらの手順を実行する前に、yolov3-tiny.cpp を変更してください ファイルを修正します (主に活性化関数とネットワーク構造を変更します) 以下にステップごとに説明します ① 活性化関数
mish の実装
以下の図からわかるように、tensorrtでは、mish 関数がサポートされていません。では、mish 関数を実装するにはどうすればよいでしょうか?
ここに画像の説明を挿入します
大きく 2 つの方法があります。具体的な実装プロセスについては、リンクhttps://zhuanlan.zhihu.com/p/410707154を参照してください。この記事はとても詳しく書かれています。読んでとても勉強になりました。皆さんのお役に立てれば幸いです。ははは、yolov3-tiny.cpp ファイル内のこのセクションの具体的な場所は次のとおりです: ② モデル構造の変更 1 回モデル構造が
ここに画像の説明を挿入します
変更されます
。.trt ファイルをビルドするときに、ネットワーク層が認識されないという問題が発生するため、独自の .cfg ファイルに従って、yolov3-tiny.cpp ファイルの createEngine クラスで変更する必要があります。 。

ICudaEngine* createEngine(unsigned int maxBatchSize, IBuilder* builder, IBuilderConfig* config, DataType dt) { 

    INetworkDefinition* network = builder->createNetworkV2(0U);
    // Create input tensor of shape {3, INPUT_H, INPUT_W} with name INPUT_BLOB_NAME
    ITensor* data = network->addInput(INPUT_BLOB_NAME, dt, Dims3{3, INPUT_H, INPUT_W});
    assert(data);

    std::map<std::string, Weights> weightMap = loadWeights("../yolov3-tiny-DIY.wts");
    Weights emptywts{DataType::kFLOAT, nullptr, 0};

    auto lr0 = convBnLeaky(network, weightMap, *data, 16, 3, 1, 1, 0); //cfg25-31
    auto pool1 = network->addPoolingNd(*lr0->getOutput(0), PoolingType::kMAX, DimsHW{2, 2});//cfg33-35
    pool1->setStrideNd(DimsHW{2, 2});
    auto lr2 = convBnLeaky(network, weightMap, *pool1->getOutput(0), 32, 3, 1, 1, 2);//cfg37-43
    auto pool3 = network->addPoolingNd(*lr2->getOutput(0), PoolingType::kMAX, DimsHW{2, 2});//cfg45-47
    pool3->setStrideNd(DimsHW{2, 2});
    // add conv1*1
    auto lr4 = convBnLeaky(network, weightMap, *pool3->getOutput(0), 32, 1, 1, 0, 4);//cfg50-56
    auto lr5 = convBnLeaky(network, weightMap, *lr4->getOutput(0), 64, 3, 1, 1, 5);//cfg58-64
    auto pool6 = network->addPoolingNd(*lr5->getOutput(0), PoolingType::kMAX, DimsHW{2, 2});//cfg66-68
    pool6->setStrideNd(DimsHW{2, 2});
    auto lr7 = convBnLeaky(network, weightMap, *pool6->getOutput(0), 64, 1, 1, 0, 7);//cfg71-77
    auto lr8 = convBnLeaky(network, weightMap, *lr7->getOutput(0), 128, 3, 1, 1, 8);//cfg80-86
    auto pool9 = network->addPoolingNd(*lr8->getOutput(0), PoolingType::kMAX, DimsHW{2, 2});//cfg88-90    
    pool9->setStrideNd(DimsHW{2, 2});
    auto lr10 = convBnLeaky(network, weightMap, *pool9->getOutput(0), 128, 1, 1, 0, 10);//cfg93-99
    auto lr11 = convBnLeaky(network, weightMap, *lr10->getOutput(0), 256, 3, 1, 1, 11);//cfg101-107
    auto pool12 = network->addPoolingNd(*lr11->getOutput(0), PoolingType::kMAX, DimsHW{2, 2});//cfg109-111    
    pool12->setStrideNd(DimsHW{2, 2});
    auto lr13 = convBnLeaky(network, weightMap, *pool12->getOutput(0), 256, 1, 1, 0, 13);//cfg114-120
    auto lr14 = convBnLeaky(network, weightMap, *lr13->getOutput(0), 512, 3, 1, 1, 14);//cfg122-128
    auto pad15 = network->addPaddingNd(*lr14->getOutput(0), DimsHW{0, 0}, DimsHW{1, 1});//这一步还没有搞明白为什么要填充,但是不填充会报错,所以根据之前的yolov3-tiny模型我就照样填充了
    auto pool15 = network->addPoolingNd(*pad15->getOutput(0), PoolingType::kMAX, DimsHW{2, 2});//cfg130-132    
    pool15->setStrideNd(DimsHW{1, 1});
    auto lr16 = convBnLeaky(network, weightMap, *pool15->getOutput(0), 512, 1, 1, 0, 16);//cfg135-141
    auto lr17 = convBnLeaky(network, weightMap, *lr16->getOutput(0), 1024, 3, 1, 1, 17);//cfg143-149
    auto lr18 = convBnLeaky(network, weightMap, *lr17->getOutput(0), 256, 1, 1, 0, 18);//cfg153-159
    auto lr19 = convBnLeaky(network, weightMap, *lr18->getOutput(0), 512, 3, 1, 1, 19);//cfg161-167
    IConvolutionLayer* conv20 = network->addConvolutionNd(*lr19->getOutput(0), 3*(Yolo::CLASS_NUM + 5), DimsHW{1, 1}, weightMap["module_list.20.Conv2d.weight"], weightMap["module_list.20.Conv2d.bias"]);
    //cfg169-174 21 is yolo
    auto lr22 = lr18;
    auto lr23 = convBnLeaky(network, weightMap, *lr22->getOutput(0), 128, 1, 1, 0, 23);//cfg191-197
    float *deval = reinterpret_cast<float*>(malloc(sizeof(float) * 128 * 2 * 2));
    for (int i = 0; i < 128 * 2 * 2; i++) {
        deval[i] = 1.0;
    }
    //cfg199-200
    Weights deconvwts24{DataType::kFLOAT, deval, 128 * 2 * 2};
    IDeconvolutionLayer* deconv24 = network->addDeconvolutionNd(*lr23->getOutput(0), 128, DimsHW{2, 2}, deconvwts24, emptywts);
    assert(deconv24);
    deconv24->setStrideNd(DimsHW{2, 2});
    deconv24->setNbGroups(128);
    weightMap["deconv24"] = deconvwts24;
    //cfg202-203
    ITensor* inputTensors[] = {deconv24->getOutput(0), lr10->getOutput(0)};
    auto cat25 = network->addConcatenation(inputTensors, 2);
    auto lr26 = convBnLeaky(network, weightMap, *cat25->getOutput(0), 256, 3, 1, 1, 26);//cfg205-211
    IConvolutionLayer* conv27 = network->addConvolutionNd(*lr26->getOutput(0), 3 * (Yolo::CLASS_NUM + 5), DimsHW{1, 1}, weightMap["module_list.27.Conv2d.weight"], weightMap["module_list.27.Conv2d.bias"]);
    //  cfg213-218  28 is yolo
    
    auto creator = getPluginRegistry()->getPluginCreator("YoloLayer_TRT", "1");
    const PluginFieldCollection* pluginData = creator->getFieldNames();
    IPluginV2 *pluginObj = creator->createPlugin("yololayer", pluginData);
    ITensor* inputTensors_yolo[] = {conv20->getOutput(0), conv27->getOutput(0)};
    auto yolo = network->addPluginV2(inputTensors_yolo, 2, *pluginObj);
    
	yolo->getOutput(0)->setName(OUTPUT_BLOB_NAME);
    network->markOutput(*yolo->getOutput(0));
    
    // Build engine
    builder->setMaxBatchSize(maxBatchSize);
    config->setMaxWorkspaceSize(16 * (1 << 20));  // 16MB
#ifdef USE_FP16
    config->setFlag(BuilderFlag::kFP16);
#endif
    std::cout << "Building engine, please wait for a while..." << std::endl;
    ICudaEngine* engine = builder->buildEngineWithConfig(*network, *config);
    std::cout << "Build engine successfully!" << std::endl;

    // Don't need the network any more
    network->destroy();

    // Release host memory
    for (auto& mem : weightMap)
    {
        free((void*) (mem.second.values));
    }

    return engine;
}

注: 問題を回避し、迅速に正しく書き込むために、この部分の内容は、書き込むときにネットワーク構造 .cfg ファイルの重み係数 .pt ファイルに従って変更する必要があります。また、この部分を書いているときに問題が発生したので、これまでの知識を修正する必要がありましたが、cfg ファイルでは、pad=1 は埋められる数値が 1 であることを意味するのではなく、kernel_size/2 であることを意味するため、モデルを書くときに、パラメータの意味に注意してください。cfg ファイルのパラメータの詳細については、リンクを参照してください: https://zhuanlan.zhihu.com/p/352494414

ここまででほぼ修正は完了ですので、上記の手順でスムーズにモデル変換を行うことができます!何か間違っていることがあれば、遠慮なく言ってください!ありがとう

おすすめ

転載: blog.csdn.net/LJ1120142576/article/details/129680865