当前位置:   article > 正文

【代码分析】Pytorch版YOLO V4代码分析_pytorch训练yolo结果解析

pytorch训练yolo结果解析

YOLO V4出来也几天了,论文大致看了下,然后看到大量的优秀者实现了各个版本的YOLOV4了。

Yolo v4 论文: https://arxiv.org/abs/2004.10934

AB大神Darknet版本的源码实现: https://github.com/AlexeyAB/darknet

本文针对Pytorch版本实现的YOLOV4进行分析,感谢Tianxiaomo 分享的工程:Pytorch-YoloV4


作者分享的权重文件,下载地址:

该权重文件yolov4.weights 是在coco数据集上训练的,目标类有80种,当前工程支持推理,不包括训练~

我的测试环境是anaconda配置的环境,pytorch1.0.1, torchvision 0.2.1;


工程目录如下:

终端运行指令:

  1. # 指令需要传入cfg文件路径,权重文件路径,图像路径
  2. >>python demo.py cfg/yolov4.cfg yolov4.weights data/dog.jpg

运行结果会生成一张检测后的图:predictions.jpg

接下来对源码做分析:

其中demo.py中,主要调用了函数detect(),其代码如下:

  1. def detect(cfgfile, weightfile, imgfile):
  2. m = Darknet(cfgfile) #穿件Darknet模型对象m
  3. m.print_network() # 打印网络结构
  4. m.load_weights(weightfile) #加载权重值
  5. print('Loading weights from %s... Done!' % (weightfile))
  6. num_classes = 80
  7. if num_classes == 20:
  8. namesfile = 'data/voc.names'
  9. elif num_classes == 80:
  10. namesfile = 'data/coco.names'
  11. else:
  12. namesfile = 'data/names'
  13. use_cuda = 0 # 是否使用cuda,工程使用的是cpu执行
  14. if use_cuda:
  15. m.cuda() # 如果使用cuda则将模型对象拷贝至显存,默认GUP ID为0;
  16. img = Image.open(imgfile).convert('RGB') # PIL打开图像
  17. sized = img.resize((m.width, m.height))
  18. for i in range(2):
  19. start = time.time()
  20. boxes = do_detect(m, sized, 0.5, 0.4, use_cuda) # 做检测,返回的boxes是昨晚nms后的检测框;
  21. finish = time.time()
  22. if i == 1:
  23. print('%s: Predicted in %f seconds.' % (imgfile, (finish - start)))
  24. class_names = load_class_names(namesfile) # 加载类别名
  25. plot_boxes(img, boxes, 'predictions.jpg', class_names)# 画框,并输出检测结果图像文件;

在创建Darknet()对象过程中,会根据传入的cfg文件做初始化工作,主要是cfg文件的解析,提取cfg中的每个block;网络结构的构建;(如下图)


 现在先说下根据cfg文件是如何解析网络结果吧,主要调用了tool/cfg.py的parse_cfg()函数,它会返回blocks,网络结果是长这个样子的(使用Netron网络查看工具 打开cfg文件,完整版请自行尝试):


创建网络模型是调用了darknet2pytorch.py中的create_network()函数,它会根据解析cfg得到的blocks构建网络,先创建个ModuleList模型列表,为每个block创建个Sequential(),将每个block中的卷积操作,BN操作,激活操作都放到这个Sequential()中;可以理解为每个block对应一个Sequential();

构建好的的ModuleList模型列表大致结构如下:

  1. Darknet(
  2. (models): ModuleList(
  3. (0): Sequential(
  4. (conv1): Conv2d(3, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  5. (bn1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  6. (mish1): Mish()
  7. )
  8. (1): Sequential(
  9. (conv2): Conv2d(32, 64, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
  10. (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  11. (mish2): Mish()
  12. )
  13. (2): Sequential(
  14. (conv3): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
  15. (bn3): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  16. (mish3): Mish()
  17. )
  18. (3): EmptyModule()
  19. (4): Sequential(
  20. (conv4): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
  21. (bn4): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  22. (mish4): Mish()
  23. )
  24. (5): Sequential(
  25. (conv5): Conv2d(64, 32, kernel_size=(1, 1), stride=(1, 1), bias=False)
  26. (bn5): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  27. (mish5): Mish()
  28. )
  29. (6): Sequential(
  30. (conv6): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  31. (bn6): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  32. (mish6): Mish()
  33. )
  34. (7): EmptyModule()
  35. (8): Sequential(
  36. (conv7): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
  37. (bn7): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  38. (mish7): Mish()
  39. )
  40. (9): EmptyModule()
  41. (10): Sequential(
  42. (conv8): Conv2d(128, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
  43. (bn8): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  44. (mish8): Mish()
  45. )
  46. (11): Sequential(
  47. (conv9): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
  48. (bn9): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  49. (mish9): Mish()
  50. )
  51. (12): Sequential(
  52. (conv10): Conv2d(128, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
  53. (bn10): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  54. (mish10): Mish()
  55. )
  56. (13): EmptyModule()
  57. (14): Sequential(
  58. (conv11): Conv2d(128, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
  59. (bn11): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  60. (mish11): Mish()
  61. )
  62. (15): Sequential(
  63. (conv12): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
  64. (bn12): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  65. (mish12): Mish()
  66. )
  67. (16): Sequential(
  68. (conv13): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  69. (bn13): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  70. (mish13): Mish()
  71. )
  72. (17): EmptyModule()
  73. (18): Sequential(
  74. (conv14): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
  75. (bn14): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  76. (mish14): Mish()
  77. )
  78. (19): Sequential(
  79. (conv15): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  80. (bn15): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  81. (mish15): Mish()
  82. )
  83. (20): EmptyModule()
  84. (21): Sequential(
  85. (conv16): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
  86. (bn16): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  87. (mish16): Mish()
  88. )
  89. (22): EmptyModule()
  90. (23): Sequential(
  91. (conv17): Conv2d(128, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
  92. (bn17): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  93. (mish17): Mish()
  94. )
  95. (24): Sequential(
  96. (conv18): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
  97. (bn18): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  98. (mish18): Mish()
  99. )
  100. (25): Sequential(
  101. (conv19): Conv2d(256, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
  102. (bn19): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  103. (mish19): Mish()
  104. )
  105. (26): EmptyModule()
  106. (27): Sequential(
  107. (conv20): Conv2d(256, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
  108. (bn20): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  109. (mish20): Mish()
  110. )
  111. (28): Sequential(
  112. (conv21): Conv2d(128, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
  113. (bn21): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  114. (mish21): Mish()
  115. )
  116. (29): Sequential(
  117. (conv22): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  118. (bn22): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  119. (mish22): Mish()
  120. )
  121. (30): EmptyModule()
  122. (31): Sequential(
  123. (conv23): Conv2d(128, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
  124. (bn23): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  125. (mish23): Mish()
  126. )
  127. (32): Sequential(
  128. (conv24): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  129. (bn24): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  130. (mish24): Mish()
  131. )
  132. (33): EmptyModule()
  133. (34): Sequential(
  134. (conv25): Conv2d(128, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
  135. (bn25): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  136. (mish25): Mish()
  137. )
  138. (35): Sequential(
  139. (conv26): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  140. (bn26): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  141. (mish26): Mish()
  142. )
  143. (36): EmptyModule()
  144. (37): Sequential(
  145. (conv27): Conv2d(128, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
  146. (bn27): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  147. (mish27): Mish()
  148. )
  149. (38): Sequential(
  150. (conv28): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  151. (bn28): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  152. (mish28): Mish()
  153. )
  154. (39): EmptyModule()
  155. (40): Sequential(
  156. (conv29): Conv2d(128, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
  157. (bn29): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  158. (mish29): Mish()
  159. )
  160. (41): Sequential(
  161. (conv30): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  162. (bn30): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  163. (mish30): Mish()
  164. )
  165. (42): EmptyModule()
  166. (43): Sequential(
  167. (conv31): Conv2d(128, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
  168. (bn31): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  169. (mish31): Mish()
  170. )
  171. (44): Sequential(
  172. (conv32): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  173. (bn32): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  174. (mish32): Mish()
  175. )
  176. (45): EmptyModule()
  177. (46): Sequential(
  178. (conv33): Conv2d(128, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
  179. (bn33): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  180. (mish33): Mish()
  181. )
  182. (47): Sequential(
  183. (conv34): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  184. (bn34): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  185. (mish34): Mish()
  186. )
  187. (48): EmptyModule()
  188. (49): Sequential(
  189. (conv35): Conv2d(128, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
  190. (bn35): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  191. (mish35): Mish()
  192. )
  193. (50): Sequential(
  194. (conv36): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  195. (bn36): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  196. (mish36): Mish()
  197. )
  198. (51): EmptyModule()
  199. (52): Sequential(
  200. (conv37): Conv2d(128, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
  201. (bn37): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  202. (mish37): Mish()
  203. )
  204. (53): EmptyModule()
  205. (54): Sequential(
  206. (conv38): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  207. (bn38): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  208. (mish38): Mish()
  209. )
  210. (55): Sequential(
  211. (conv39): Conv2d(256, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
  212. (bn39): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  213. (mish39): Mish()
  214. )
  215. (56): Sequential(
  216. (conv40): Conv2d(512, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  217. (bn40): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  218. (mish40): Mish()
  219. )
  220. (57): EmptyModule()
  221. (58): Sequential(
  222. (conv41): Conv2d(512, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  223. (bn41): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  224. (mish41): Mish()
  225. )
  226. (59): Sequential(
  227. (conv42): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  228. (bn42): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  229. (mish42): Mish()
  230. )
  231. (60): Sequential(
  232. (conv43): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  233. (bn43): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  234. (mish43): Mish()
  235. )
  236. (61): EmptyModule()
  237. (62): Sequential(
  238. (conv44): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  239. (bn44): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  240. (mish44): Mish()
  241. )
  242. (63): Sequential(
  243. (conv45): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  244. (bn45): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  245. (mish45): Mish()
  246. )
  247. (64): EmptyModule()
  248. (65): Sequential(
  249. (conv46): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  250. (bn46): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  251. (mish46): Mish()
  252. )
  253. (66): Sequential(
  254. (conv47): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  255. (bn47): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  256. (mish47): Mish()
  257. )
  258. (67): EmptyModule()
  259. (68): Sequential(
  260. (conv48): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  261. (bn48): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  262. (mish48): Mish()
  263. )
  264. (69): Sequential(
  265. (conv49): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  266. (bn49): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  267. (mish49): Mish()
  268. )
  269. (70): EmptyModule()
  270. (71): Sequential(
  271. (conv50): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  272. (bn50): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  273. (mish50): Mish()
  274. )
  275. (72): Sequential(
  276. (conv51): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  277. (bn51): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  278. (mish51): Mish()
  279. )
  280. (73): EmptyModule()
  281. (74): Sequential(
  282. (conv52): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  283. (bn52): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  284. (mish52): Mish()
  285. )
  286. (75): Sequential(
  287. (conv53): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  288. (bn53): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  289. (mish53): Mish()
  290. )
  291. (76): EmptyModule()
  292. (77): Sequential(
  293. (conv54): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  294. (bn54): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  295. (mish54): Mish()
  296. )
  297. (78): Sequential(
  298. (conv55): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  299. (bn55): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  300. (mish55): Mish()
  301. )
  302. (79): EmptyModule()
  303. (80): Sequential(
  304. (conv56): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  305. (bn56): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  306. (mish56): Mish()
  307. )
  308. (81): Sequential(
  309. (conv57): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  310. (bn57): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  311. (mish57): Mish()
  312. )
  313. (82): EmptyModule()
  314. (83): Sequential(
  315. (conv58): Conv2d(256, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  316. (bn58): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  317. (mish58): Mish()
  318. )
  319. (84): EmptyModule()
  320. (85): Sequential(
  321. (conv59): Conv2d(512, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
  322. (bn59): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  323. (mish59): Mish()
  324. )
  325. (86): Sequential(
  326. (conv60): Conv2d(512, 1024, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
  327. (bn60): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  328. (mish60): Mish()
  329. )
  330. (87): Sequential(
  331. (conv61): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
  332. (bn61): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  333. (mish61): Mish()
  334. )
  335. (88): EmptyModule()
  336. (89): Sequential(
  337. (conv62): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
  338. (bn62): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  339. (mish62): Mish()
  340. )
  341. (90): Sequential(
  342. (conv63): Conv2d(512, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
  343. (bn63): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  344. (mish63): Mish()
  345. )
  346. (91): Sequential(
  347. (conv64): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  348. (bn64): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  349. (mish64): Mish()
  350. )
  351. (92): EmptyModule()
  352. (93): Sequential(
  353. (conv65): Conv2d(512, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
  354. (bn65): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  355. (mish65): Mish()
  356. )
  357. (94): Sequential(
  358. (conv66): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  359. (bn66): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  360. (mish66): Mish()
  361. )
  362. (95): EmptyModule()
  363. (96): Sequential(
  364. (conv67): Conv2d(512, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
  365. (bn67): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  366. (mish67): Mish()
  367. )
  368. (97): Sequential(
  369. (conv68): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  370. (bn68): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  371. (mish68): Mish()
  372. )
  373. (98): EmptyModule()
  374. (99): Sequential(
  375. (conv69): Conv2d(512, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
  376. (bn69): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  377. (mish69): Mish()
  378. )
  379. (100): Sequential(
  380. (conv70): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  381. (bn70): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  382. (mish70): Mish()
  383. )
  384. (101): EmptyModule()
  385. (102): Sequential(
  386. (conv71): Conv2d(512, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
  387. (bn71): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  388. (mish71): Mish()
  389. )
  390. (103): EmptyModule()
  391. (104): Sequential(
  392. (conv72): Conv2d(1024, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
  393. (bn72): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  394. (mish72): Mish()
  395. )
  396. (105): Sequential(
  397. (conv73): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
  398. (bn73): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  399. (leaky73): LeakyReLU(negative_slope=0.1, inplace)
  400. )
  401. (106): Sequential(
  402. (conv74): Conv2d(512, 1024, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  403. (bn74): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  404. (leaky74): LeakyReLU(negative_slope=0.1, inplace)
  405. )
  406. (107): Sequential(
  407. (conv75): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
  408. (bn75): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  409. (leaky75): LeakyReLU(negative_slope=0.1, inplace)
  410. )
  411. (108): MaxPoolStride1()
  412. (109): EmptyModule()
  413. (110): MaxPoolStride1()
  414. (111): EmptyModule()
  415. (112): MaxPoolStride1()
  416. (113): EmptyModule()
  417. (114): Sequential(
  418. (conv76): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
  419. (bn76): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  420. (leaky76): LeakyReLU(negative_slope=0.1, inplace)
  421. )
  422. (115): Sequential(
  423. (conv77): Conv2d(512, 1024, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  424. (bn77): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  425. (leaky77): LeakyReLU(negative_slope=0.1, inplace)
  426. )
  427. (116): Sequential(
  428. (conv78): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
  429. (bn78): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  430. (leaky78): LeakyReLU(negative_slope=0.1, inplace)
  431. )
  432. (117): Sequential(
  433. (conv79): Conv2d(512, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  434. (bn79): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  435. (leaky79): LeakyReLU(negative_slope=0.1, inplace)
  436. )
  437. (118): Upsample()
  438. (119): EmptyModule()
  439. (120): Sequential(
  440. (conv80): Conv2d(512, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  441. (bn80): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  442. (leaky80): LeakyReLU(negative_slope=0.1, inplace)
  443. )
  444. (121): EmptyModule()
  445. (122): Sequential(
  446. (conv81): Conv2d(512, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  447. (bn81): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  448. (leaky81): LeakyReLU(negative_slope=0.1, inplace)
  449. )
  450. (123): Sequential(
  451. (conv82): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  452. (bn82): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  453. (leaky82): LeakyReLU(negative_slope=0.1, inplace)
  454. )
  455. (124): Sequential(
  456. (conv83): Conv2d(512, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  457. (bn83): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  458. (leaky83): LeakyReLU(negative_slope=0.1, inplace)
  459. )
  460. (125): Sequential(
  461. (conv84): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  462. (bn84): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  463. (leaky84): LeakyReLU(negative_slope=0.1, inplace)
  464. )
  465. (126): Sequential(
  466. (conv85): Conv2d(512, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  467. (bn85): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  468. (leaky85): LeakyReLU(negative_slope=0.1, inplace)
  469. )
  470. (127): Sequential(
  471. (conv86): Conv2d(256, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
  472. (bn86): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  473. (leaky86): LeakyReLU(negative_slope=0.1, inplace)
  474. )
  475. (128): Upsample()
  476. (129): EmptyModule()
  477. (130): Sequential(
  478. (conv87): Conv2d(256, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
  479. (bn87): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  480. (leaky87): LeakyReLU(negative_slope=0.1, inplace)
  481. )
  482. (131): EmptyModule()
  483. (132): Sequential(
  484. (conv88): Conv2d(256, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
  485. (bn88): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  486. (leaky88): LeakyReLU(negative_slope=0.1, inplace)
  487. )
  488. (133): Sequential(
  489. (conv89): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  490. (bn89): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  491. (leaky89): LeakyReLU(negative_slope=0.1, inplace)
  492. )
  493. (134): Sequential(
  494. (conv90): Conv2d(256, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
  495. (bn90): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  496. (leaky90): LeakyReLU(negative_slope=0.1, inplace)
  497. )
  498. (135): Sequential(
  499. (conv91): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  500. (bn91): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  501. (leaky91): LeakyReLU(negative_slope=0.1, inplace)
  502. )
  503. (136): Sequential(
  504. (conv92): Conv2d(256, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
  505. (bn92): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  506. (leaky92): LeakyReLU(negative_slope=0.1, inplace)
  507. )
  508. (137): Sequential(
  509. (conv93): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  510. (bn93): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  511. (leaky93): LeakyReLU(negative_slope=0.1, inplace)
  512. )
  513. (138): Sequential(
  514. (conv94): Conv2d(256, 255, kernel_size=(1, 1), stride=(1, 1))
  515. )
  516. (139): YoloLayer()
  517. (140): EmptyModule()
  518. (141): Sequential(
  519. (conv95): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
  520. (bn95): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  521. (leaky95): LeakyReLU(negative_slope=0.1, inplace)
  522. )
  523. (142): EmptyModule()
  524. (143): Sequential(
  525. (conv96): Conv2d(512, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  526. (bn96): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  527. (leaky96): LeakyReLU(negative_slope=0.1, inplace)
  528. )
  529. (144): Sequential(
  530. (conv97): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  531. (bn97): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  532. (leaky97): LeakyReLU(negative_slope=0.1, inplace)
  533. )
  534. (145): Sequential(
  535. (conv98): Conv2d(512, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  536. (bn98): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  537. (leaky98): LeakyReLU(negative_slope=0.1, inplace)
  538. )
  539. (146): Sequential(
  540. (conv99): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  541. (bn99): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  542. (leaky99): LeakyReLU(negative_slope=0.1, inplace)
  543. )
  544. (147): Sequential(
  545. (conv100): Conv2d(512, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  546. (bn100): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  547. (leaky100): LeakyReLU(negative_slope=0.1, inplace)
  548. )
  549. (148): Sequential(
  550. (conv101): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  551. (bn101): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  552. (leaky101): LeakyReLU(negative_slope=0.1, inplace)
  553. )
  554. (149): Sequential(
  555. (conv102): Conv2d(512, 255, kernel_size=(1, 1), stride=(1, 1))
  556. )
  557. (150): YoloLayer()
  558. (151): EmptyModule()
  559. (152): Sequential(
  560. (conv103): Conv2d(256, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
  561. (bn103): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  562. (leaky103): LeakyReLU(negative_slope=0.1, inplace)
  563. )
  564. (153): EmptyModule()
  565. (154): Sequential(
  566. (conv104): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
  567. (bn104): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  568. (leaky104): LeakyReLU(negative_slope=0.1, inplace)
  569. )
  570. (155): Sequential(
  571. (conv105): Conv2d(512, 1024, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  572. (bn105): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  573. (leaky105): LeakyReLU(negative_slope=0.1, inplace)
  574. )
  575. (156): Sequential(
  576. (conv106): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
  577. (bn106): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  578. (leaky106): LeakyReLU(negative_slope=0.1, inplace)
  579. )
  580. (157): Sequential(
  581. (conv107): Conv2d(512, 1024, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  582. (bn107): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  583. (leaky107): LeakyReLU(negative_slope=0.1, inplace)
  584. )
  585. (158): Sequential(
  586. (conv108): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
  587. (bn108): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  588. (leaky108): LeakyReLU(negative_slope=0.1, inplace)
  589. )
  590. (159): Sequential(
  591. (conv109): Conv2d(512, 1024, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  592. (bn109): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  593. (leaky109): LeakyReLU(negative_slope=0.1, inplace)
  594. )
  595. (160): Sequential(
  596. (conv110): Conv2d(1024, 255, kernel_size=(1, 1), stride=(1, 1))
  597. )
  598. (161): YoloLayer()
  599. )
  600. )

返回demo.py 的detect()函数,构件好Darknet对象后,打印网络结构图,然后调用darknet2pytorch.py中的load_weights()加载权重文件,这里介绍下这个权重文件中的数值分别是什么以及怎么排序的。

对于没有bias的模型数据,从yolov4.weights加载的模型数据,其数值排列顺序为先是BNbiasgamma),然后是BNweightalpha)值,然后是BNmean,然后是BNvar, 最后是卷积操作的权重值,如下图,buf是加载后的yolov4.weights数据内容;网络第一个卷积核个数为32个,其对应的BN2操作的bias也有32个,而卷积核参数为3x3x3x32 =864 (含义分别是输入通道是3,因为图像是三通道的,3x3的卷积核大小,然后输出核个数是32)

 

 而如下几个block类型在训练过程中是不会生成权重值的,所以不用从yolov4.weights中取值;

  1. elif block['type'] == 'maxpool':
  2. pass
  3. elif block['type'] == 'reorg':
  4. pass
  5. elif block['type'] == 'upsample':
  6. pass
  7. elif block['type'] == 'route':
  8. pass
  9. elif block['type'] == 'shortcut':
  10. pass
  11. elif block['type'] == 'region':
  12. pass
  13. elif block['type'] == 'yolo':
  14. pass
  15. elif block['type'] == 'avgpool':
  16. pass
  17. elif block['type'] == 'softmax':
  18. pass
  19. elif block['type'] == 'cost':
  20. pass

完成cfg文件的解析,模型的创建与权重文件的加载之后,现在要做的就是执行检测操作了,主要调用了utils/utils.py中的do_detect()函数,在demo.py中就是这行代码:boxes = do_detect(m, sized, 0.5, 0.4, use_cuda)

  1. def do_detect(model, img, conf_thresh, nms_thresh, use_cuda=1):
  2. model.eval() #模型做推理
  3. t0 = time.time()
  4. if isinstance(img, Image.Image):
  5. width = img.width
  6. height = img.height
  7. img = torch.ByteTensor(torch.ByteStorage.from_buffer(img.tobytes()))
  8. img = img.view(height, width, 3).transpose(0, 1).transpose(0, 2).contiguous() # CxHxW
  9. img = img.view(1, 3, height, width) # 对图像维度做变换,BxCxHxW
  10. img = img.float().div(255.0) # [0-255] --> [0-1]
  11. elif type(img) == np.ndarray and len(img.shape) == 3: # cv2 image
  12. img = torch.from_numpy(img.transpose(2, 0, 1)).float().div(255.0).unsqueeze(0)
  13. elif type(img) == np.ndarray and len(img.shape) == 4:
  14. img = torch.from_numpy(img.transpose(0, 3, 1, 2)).float().div(255.0)
  15. else:
  16. print("unknow image type")
  17. exit(-1)
  18. if use_cuda:
  19. img = img.cuda()
  20. img = torch.autograd.Variable(img)
  21. list_boxes = model(img) # 主要是调用了模型的forward操作,返回三个yolo层的输出
  22. anchors = [12, 16, 19, 36, 40, 28, 36, 75, 76, 55, 72, 146, 142, 110, 192, 243, 459, 401]
  23. num_anchors = 9 # 3个yolo层共9种锚点
  24. anchor_masks = [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
  25. strides = [8, 16, 32] # 每个yolo层相对输入图像尺寸的减少倍数分别为8,16,32
  26. anchor_step = len(anchors) // num_anchors
  27. boxes = []
  28. for i in range(3):
  29. masked_anchors = []
  30. for m in anchor_masks[i]:
  31. masked_anchors += anchors[m * anchor_step:(m + 1) * anchor_step]
  32. masked_anchors = [anchor / strides[i] for anchor in masked_anchors]
  33. boxes.append(get_region_boxes1(list_boxes[i].data.numpy(), 0.6, 80, masked_anchors, len(anchor_masks[i])))
  34. # boxes.append(get_region_boxes(list_boxes[i], 0.6, 80, masked_anchors, len(anchor_masks[i])))
  35. if img.shape[0] > 1:
  36. bboxs_for_imgs = [
  37. boxes[0][index] + boxes[1][index] + boxes[2][index]
  38. for index in range(img.shape[0])]
  39. # 分别对每一张图像做nms
  40. boxes = [nms(bboxs, nms_thresh) for bboxs in bboxs_for_imgs]
  41. else:
  42. boxes = boxes[0][0] + boxes[1][0] + boxes[2][0]
  43. boxes = nms(boxes, nms_thresh)
  44. return boxes # 返回nms后的boxes

模型forward后输出结果存在list_boxes中,因为有3yolo输出层,所以这个列表list_boxes中又分为3个子列表;

其中list_boxes[0]中存放的是第一个yolo层输出,其特征图大小对于原图缩放尺寸为8,即strides[0], 对于608x608图像来说,该层的featuremap尺寸为608/8=76;则该层的yolo输出数据维度为[batch, (classnum+4+1)*num_anchors, feature_h, feature_w] , 对于80类的coco来说,测试图像为1,每个yolo层每个特征图像点有3个锚点,该yolo层输出是[1,255,76,76];对应锚点大小为[1.5,2.0,2.375,4.5,5.0,3.5]; (6个数分别是3个锚点的wh,按照w1,h1,w2,h2,w3,h3排列);

同理第二个yolo层检测结果维度为[1,255,38,38],对应锚点大小为:[2.25,4.6875,4.75,3.4375,4.5,9.125],输出为 [1,255,38,38]

第三yolo层检测维度为[1,255,19,19],对应锚点大小为:[4.4375,3.4375,6.0,7.59375,14.34375,12.53125]输出为 [1,255,19,19];


do_detect()函数中主要是调用了get_region_boxes1(output, conf_thresh, num_classes, anchors, num_anchors, only_objectness=1, validation=False) 这个函数对forward后的output做解析并做nms操作;

每个yolo层输出数据分析,对于第一个yolo层,输出维度为[1,85*3,76,76 ]; 会将其reshape[85, 1*3*76*76],即有1*3*76*76个锚点在预测,每个锚点预测信息有80个类别的概率和4个位置信息和1个是否包含目标的置信度;下图是第一个yolo输出层的数据(实际绘制网格数量不正确,此处只是做说明用

 每个输出的对应代码实现为:

继续结合上面的图,分析对于某一个yolo层输出的数据是怎么排列的,其示意图如下:

 

 如果置信度满足阈值要求,则将预测的box保存到列表(其中id是所有output的索引,其值在0~batch*anchor_num*h*w范围内)

 

  1. if conf > conf_thresh:
  2. bcx = xs[ind]
  3. bcy = ys[ind]
  4. bw = ws[ind]
  5. bh = hs[ind]
  6. cls_max_conf = cls_max_confs[ind]
  7. cls_max_id = cls_max_ids[ind]
  8. box = [bcx / w, bcy / h, bw / w, bh / h, det_conf, cls_max_conf, cls_max_id]

对于3个yolo层先是简单的对每个yolo层输出中是否含有目标做了过滤(含有目标的概率大于阈值);然后就是对三个过滤后的框合并到一个list中作NMS操作了;涉及的代码如下:

  1. def nms(boxes, nms_thresh):
  2. if len(boxes) == 0:
  3. return boxes
  4. det_confs = torch.zeros(len(boxes))
  5. for i in range(len(boxes)):
  6. det_confs[i] = 1 - boxes[i][4]
  7. _, sortIds = torch.sort(det_confs) # sort是按照从小到大排序,那么sortlds中是按照有目标的概率由大到小排序
  8. out_boxes = []
  9. for i in range(len(boxes)):
  10. box_i = boxes[sortIds[i]]
  11. if box_i[4] > 0:
  12. out_boxes.append(box_i) # 取出有目标的概率最大的box放入out_boxes中;
  13. for j in range(i + 1, len(boxes)): #然后将剩下的box_j都和这个box_i进行IOU计算,若与box_i重叠率大于阈值,则将box_j的包含目标概率值置为0(即不选它)
  14. box_j = boxes[sortIds[j]]
  15. if bbox_iou(box_i, box_j, x1y1x2y2=False) > nms_thresh:
  16. # print(box_i, box_j, bbox_iou(box_i, box_j, x1y1x2y2=False))
  17. box_j[4] = 0
  18. return out_boxes

补充:

论文中提到的mish激活函数

公式是这样的(其中x是输入)

对应的图是:

 

  1. ##Pytorch中的代码实现为:
  2. class Mish(torch.nn.Module):
  3. def __init__(self):
  4. super().__init__()
  5. def forward(self, x):
  6. x = x * (torch.tanh(torch.nn.functional.softplus(x)))
  7. return x
  8. #--------------------------------------------------------------#
  9. Tensorflow的代码实现为:
  10. import tensorflow as tf
  11. from tensorflow.keras.layers import Activation
  12. from tensorflow.keras.utils import get_custom_objects
  13. class Mish(Activation):
  14. def __init__(self, activation, **kwargs):
  15. super(Mish, self).__init__(activation, **kwargs)
  16. self.__name__ = 'Mish'
  17. def mish(inputs):
  18. return inputs * tf.math.tanh(tf.math.softplus(inputs))
  19. get_custom_objects().update({'Mish': Mish(mish)})
  20. #使用方法
  21. x = Activation('Mish')(x)

文中提到的SPP结构大致是:

 

Pytorch指定运行的GPUID号的方法,https://www.cnblogs.com/jfdwd/p/11434332.html 

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/499806
推荐阅读
相关标签
  

闽ICP备14008679号