ヒント: 自己トレーニングされた 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
ここまででほぼ修正は完了ですので、上記の手順でスムーズにモデル変換を行うことができます!!何か間違っていることがあれば、遠慮なく言ってください!ありがとう