MyCaffe  1.12.2.41
Deep learning software for Windows C# programmers.
MultiBoxLossLayer.cs
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using MyCaffe.basecode;
6using MyCaffe.common;
7using MyCaffe.param;
8using MyCaffe.param.ssd;
9
10namespace MyCaffe.layers.ssd
11{
24 public class MultiBoxLossLayer<T> : LossLayer<T>
25 {
26 // The internal localization loss layer.
27 Layer<T> m_locLossLayer;
29 float m_fLocWeight;
30 // Bottom vector holder used in forward function.
31 BlobCollection<T> m_colLocBottom = new BlobCollection<T>();
32 // Top vector holder used in forward function.
33 BlobCollection<T> m_colLocTop = new BlobCollection<T>();
34 // Blob which stores the matched location prediction.
35 Blob<T> m_blobLocPred;
36 // Blob which stores the corresponding matched ground truth.
37 Blob<T> m_blobLocGt;
38 // Localization loss.
39 Blob<T> m_blobLocLoss;
40
41 // The internal confidence loss layer.
42 Layer<T> m_confLossLayer;
44 // Bottom vector holder used in the forward function.
45 BlobCollection<T> m_colConfBottom = new BlobCollection<T>();
46 // Top vector holder used in the forward function.
47 BlobCollection<T> m_colConfTop = new BlobCollection<T>();
48 // Blob which stores the confidence prediction.
49 Blob<T> m_blobConfPred;
50 // Blob which stores the corresponding ground truth.
51 Blob<T> m_blobConfGt;
52 // Confidence loss.
53 Blob<T> m_blobConfLoss;
54
55 HostBuffer<T> m_hostGt;
56 HostBuffer<T> m_hostLoc;
57 HostBuffer<T> m_hostConf;
58 HostBuffer<T> m_hostPrio;
59
60 int m_nNumClasses;
61 bool m_bShareLocation;
62 int m_nBackgroundLabelId;
63 bool m_bUseDifficultGt;
64 bool m_bDoNegMining;
66
67 int m_nLocClasses;
68 int m_nNumGt;
69 int m_nNum;
70 int m_nNumPriors;
71
72 int m_nNumMatches;
73 int m_nNumConf;
74
75 List<DictionaryMap<List<int>>> m_rgAllMatchIndices = new List<DictionaryMap<List<int>>>();
76 List<List<int>> m_rgrgAllNegIndices = new List<List<int>>();
77 BBoxUtility<T> m_bboxUtil;
78 long m_hSsd = 0;
79
89 : base(cuda, log, p)
90 {
91 m_type = LayerParameter.LayerType.MULTIBOX_LOSS;
92
93 m_blobLocPred = new Blob<T>(cuda, log);
94 m_blobLocPred.Name = m_param.name + " loc_pred";
95 m_blobLocGt = new Blob<T>(cuda, log);
96 m_blobLocGt.Name = m_param.name + " loc_gt";
97 m_blobLocLoss = new Blob<T>(cuda, log);
98 m_blobLocLoss.Name = m_param.name + " loc_loss";
99
100 m_blobConfPred = new Blob<T>(cuda, log);
101 m_blobConfPred.Name = m_param.name + " conf_pred";
102 m_blobConfGt = new Blob<T>(cuda, log);
103 m_blobConfGt.Name = m_param.name + " conf_gt";
104 m_blobConfLoss = new Blob<T>(cuda, log);
105 m_blobConfLoss.Name = m_param.name + " conf_loss";
106
107 m_bboxUtil = new BBoxUtility<T>(cuda, log);
108
109 m_hostConf = new HostBuffer<T>(cuda);
110 m_hostLoc = new HostBuffer<T>(cuda);
111 m_hostGt = new HostBuffer<T>(cuda);
112 m_hostPrio = new HostBuffer<T>(cuda);
113 }
114
115 private void dispose(ref Blob<T> b)
116 {
117 if (b != null)
118 {
119 b.Dispose();
120 b = null;
121 }
122 }
123
127 protected override void dispose()
128 {
129 dispose(ref m_blobLocPred);
130 dispose(ref m_blobLocGt);
131 dispose(ref m_blobLocLoss);
132 dispose(ref m_blobConfPred);
133 dispose(ref m_blobConfGt);
134 dispose(ref m_blobConfLoss);
135
136 if (m_hSsd != 0)
137 {
138 m_cuda.FreeSSD(m_hSsd);
139 m_hSsd = 0;
140 }
141
142 if (m_locLossLayer != null)
143 {
144 m_locLossLayer.Dispose();
145 m_locLossLayer = null;
146 }
147
148 if (m_confLossLayer != null)
149 {
150 m_confLossLayer.Dispose();
151 m_confLossLayer = null;
152 }
153
154 if (m_bboxUtil != null)
155 {
156 m_bboxUtil.Dispose();
157 m_bboxUtil = null;
158 }
159
160 if (m_hostConf != null)
161 {
162 m_hostConf.Dispose();
163 m_hostConf = null;
164 }
165
166 if (m_hostLoc != null)
167 {
168 m_hostLoc.Dispose();
169 m_hostLoc = null;
170 }
171
172 if (m_hostGt != null)
173 {
174 m_hostGt.Dispose();
175 m_hostGt = null;
176 }
177
178 if (m_hostPrio != null)
179 {
180 m_hostPrio.Dispose();
181 m_hostPrio = null;
182 }
183
184 base.dispose();
185 }
186
188 protected override void setup_internal_blobs(BlobCollection<T> col)
189 {
190 if (col.Count > 0)
191 return;
192
193 col.Add(m_blobConfPred);
194 col.Add(m_blobLocGt);
195 col.Add(m_blobLocLoss);
196 col.Add(m_blobConfPred);
197 col.Add(m_blobConfGt);
198 col.Add(m_blobConfLoss);
199 }
200
210 public override int ExactNumBottomBlobs
211 {
212 get { return 4; }
213 }
214
218 public override int ExactNumTopBlobs
219 {
220 get { return 1; }
221 }
222
228 public override void LayerSetUp(BlobCollection<T> colBottom, BlobCollection<T> colTop)
229 {
230 base.LayerSetUp(colBottom, colTop);
231
232 if (m_param.propagate_down.Count == 0)
233 {
234 m_param.propagate_down.Add(true);
235 m_param.propagate_down.Add(true);
236 m_param.propagate_down.Add(false);
237 m_param.propagate_down.Add(false);
238 }
239
240 m_nNum = colBottom[0].num;
241 m_nNumPriors = colBottom[2].height / 4;
242
243 // Get other parameters.
244 m_nNumClasses = (int)m_param.multiboxloss_param.num_classes;
245 m_log.CHECK_GE(m_nNumClasses, 1, "The num_classes should not be less than 1.");
246
247 m_bShareLocation = m_param.multiboxloss_param.share_location;
248 m_nLocClasses = (m_bShareLocation) ? 1 : m_nNumClasses;
249
250 m_nBackgroundLabelId = (int)m_param.multiboxloss_param.background_label_id;
251 m_bUseDifficultGt = m_param.multiboxloss_param.use_difficult_gt;
253
255 {
256 m_log.WriteLine("WARNING: do_neg_mining is depreciated, use mining_type instead.");
257 m_bDoNegMining = m_param.multiboxloss_param.do_neg_mining.Value;
258 m_log.CHECK(m_bDoNegMining == (m_miningType != MultiBoxLossParameter.MiningType.NONE), "The mining type specified is inconsistent with do_neg_mining.");
259 }
260
261 m_bDoNegMining = (m_miningType != MultiBoxLossParameter.MiningType.NONE);
262
263 if (m_bDoNegMining)
264 m_log.CHECK(m_bShareLocation, "Currently only support negative mining if share_location is true.");
265
266 // Setup localization loss layer.
269 // fake shape
270 List<int> rgLocShape = Utility.Create<int>(1, 1);
271 rgLocShape.Add(4);
272 m_blobLocPred.Reshape(rgLocShape);
273 m_blobLocGt.Reshape(rgLocShape);
274 m_colLocBottom.Add(m_blobLocPred);
275 m_colLocBottom.Add(m_blobLocGt);
276
277 List<int> rgLossShape = Utility.Create<int>(1, 1);
278 m_blobLocLoss.Reshape(rgLossShape);
279 m_colLocTop.Add(m_blobLocLoss);
280
281 if (m_locLossType == MultiBoxLossParameter.LocLossType.L2)
282 {
284 p.name += "_l2_loc";
285 p.loss_weight.Add(m_fLocWeight);
286 m_locLossLayer = Layer<T>.Create(m_cuda, m_log, p, null);
287 m_locLossLayer.Setup(m_colLocBottom, m_colLocTop);
288 }
289 else if (m_locLossType == MultiBoxLossParameter.LocLossType.SMOOTH_L1)
290 {
292 p.name += "_smooth_l1_loc";
293 p.loss_weight.Add(m_fLocWeight);
294 m_locLossLayer = Layer<T>.Create(m_cuda, m_log, p, null);
295 m_locLossLayer.Setup(m_colLocBottom, m_colLocTop);
296 }
297 else
298 {
299 m_log.FAIL("Unknown localization loss type.");
300 }
301
302 // Setup confidence loss layer.
304 m_colConfBottom.Add(m_blobConfPred);
305 m_colConfBottom.Add(m_blobConfGt);
306 m_blobConfLoss.Reshape(rgLossShape);
307 m_colConfTop.Add(m_blobConfLoss);
308
309 List<int> rgConfShape = Utility.Create<int>(1, 1);
310
311 if (m_confLossType == MultiBoxLossParameter.ConfLossType.SOFTMAX)
312 {
313 m_log.CHECK_GE(m_nBackgroundLabelId, 0, "The background_label_id should be within [0, num_classes) for Softmax.");
314 m_log.CHECK_LT(m_nBackgroundLabelId, m_nNumClasses, "The background_label_id should be within [0, num_classes) for Softmax.");
315 LayerParameter p = new LayerParameter(LayerParameter.LayerType.SOFTMAXWITH_LOSS);
316 p.name += "_softmax_conf";
317 p.loss_weight.Add(1);
319 p.softmax_param.axis = 1;
320
321 // Fake shape.
322 m_blobConfGt.Reshape(rgConfShape);
323 rgConfShape.Add(m_nNumClasses);
324 m_blobConfPred.Reshape(rgConfShape);
325 m_confLossLayer = Layer<T>.Create(m_cuda, m_log, p, null);
326 m_confLossLayer.Setup(m_colConfBottom, m_colConfTop);
327 }
328 else if (m_confLossType == MultiBoxLossParameter.ConfLossType.LOGISTIC)
329 {
330 LayerParameter p = new LayerParameter(LayerParameter.LayerType.SIGMOIDCROSSENTROPY_LOSS);
331 p.name += "_logistic_conf";
332 p.loss_weight.Add(1);
333
334 // Fake shape
335 rgConfShape.Add(m_nNumClasses);
336 m_blobConfGt.Reshape(rgConfShape);
337 m_blobConfPred.Reshape(rgConfShape);
338 m_confLossLayer = Layer<T>.Create(m_cuda, m_log, p, null);
339 m_confLossLayer.Setup(m_colConfBottom, m_colConfTop);
340 }
341 else
342 {
343 m_log.FAIL("Unknown confidence loss type.");
344 }
345
346 // Create the low-level SSD support.
348 {
349 float? fNmsThreshold = null;
350 int? nNmsTopK = null;
351 float? fNmsEta = null;
352 bool bNmsParam = false;
353
355 {
356 bNmsParam = true;
360 }
361
362 m_hSsd = m_cuda.CreateSSD(m_nNumClasses,
363 m_bShareLocation,
364 m_nLocClasses,
365 m_nBackgroundLabelId,
366 m_bUseDifficultGt,
367 (SSD_MINING_TYPE)(int)m_miningType,
382 bNmsParam,
383 fNmsThreshold,
384 nNmsTopK,
385 fNmsEta);
386 if (m_hSsd == 0)
387 throw new Exception("Could not create the SSD!");
388 }
389 }
390
396 public override void Reshape(BlobCollection<T> colBottom, BlobCollection<T> colTop)
397 {
398 base.Reshape(colBottom, colTop);
399
400 m_nNum = colBottom[0].num;
401 m_nNumPriors = colBottom[2].height / 4;
402 m_nNumGt = colBottom[3].height;
403
405 m_cuda.SetupSSD(m_hSsd, m_nNum, m_nNumPriors, m_nNumGt);
406
407 m_log.CHECK_EQ(colBottom[0].num, colBottom[1].num, "The bottom[0] and bottom[1] num must be equal.");
408 m_log.CHECK_EQ(m_nNumPriors * m_nLocClasses * 4, colBottom[0].channels, "The number of priors must match the number of location predictions.");
409 m_log.CHECK_EQ(m_nNumPriors * m_nNumClasses, colBottom[1].channels, "The number of priors must match the number of confidence predictions.");
410 }
411
420 protected void forwardGpu(BlobCollection<T> colBottom, BlobCollection<T> colTop)
421 {
422 // Calculate the Loc and Conf predictions
423 int nLocDataCount = colBottom[0].count();
424 long hLocGpuData = colBottom[0].gpu_data;
425 int nConfDataCount = colBottom[1].count();
426 long hConfGpuData = colBottom[1].gpu_data;
427 int nPriorDataCount = colBottom[2].count();
428 long hPriorGpuData = colBottom[2].gpu_data;
429 int nGtDataCount = colBottom[3].count();
430 long hGtGpuData = colBottom[3].gpu_data;
431 int nNumNegs;
432
433 m_nNumMatches = m_cuda.SsdMultiBoxLossForward(m_hSsd, nLocDataCount, hLocGpuData, nConfDataCount, hConfGpuData, nPriorDataCount, hPriorGpuData, nGtDataCount, hGtGpuData, out m_rgAllMatchIndices, out m_rgrgAllNegIndices, out nNumNegs);
434
435 // Retrieve all ground truth.
436 // m_hostGt.CopyFrom(colBottom[3]);
437 // float[] rgfGtData = m_hostGt.GetHostDataAsFloat();
438 // DictionaryMap<List<NormalizedBBox>> rgAllGtBboxes = m_bboxUtil.GetGroundTruth(rgfGtData, m_nNumGt, m_nBackgroundLabelId, m_bUseDifficultGt);
439
440 // Retrieve all prior bboxes. It is the same within a batch since we assume all
441 // images in a batch are of the same dimension.
442 // List<List<float>> rgrgPriorVariances;
443 // m_hostPrio.CopyFrom(colBottom[2]);
444 // float[] rgfPriorData = m_hostPrio.GetHostDataAsFloat();
445 // List<NormalizedBBox> rgPriorBboxes = m_bboxUtil.GetPrior(rgfPriorData, m_nNumPriors, out rgrgPriorVariances);
446
447 // Retrieve all predictions.
448 // m_hostLoc.CopyFrom(colBottom[0]);
449 // float[] rgfLocData = m_hostLoc.GetHostDataAsFloat();
450 // List<LabelBBox> rgAllLocPreds = m_bboxUtil.GetLocPredictions(rgfLocData, m_nNum, m_nNumPriors, m_nLocClasses, m_bShareLocation);
451
452 // Find matches between source bboxes and ground truth bboxes.
453 // List<DictionaryMap<List<float>>> rgAllMatchOverlaps;
454 // m_bboxUtil.FindMatches(rgAllLocPreds, rgAllGtBboxes, rgPriorBboxes, rgrgPriorVariances, m_param.multiboxloss_param, out rgAllMatchOverlaps, out m_rgAllMatchIndices);
455
456 // Sample hard negative (and positive) examples based on mining type.
457 // int nNumNegs;
458 // m_nNumMatches = m_bboxUtil.MineHardExamples(colBottom[1], rgAllLocPreds, rgAllGtBboxes, rgPriorBboxes, rgrgPriorVariances, rgAllMatchOverlaps, m_param.multiboxloss_param, m_rgAllMatchIndices, m_rgrgAllNegIndices, out nNumNegs);
459
460 if (m_nNumMatches >= 1)
461 {
462 // Form data to pass on to loc_loss_layer.
463 List<int> rgLocShape = new List<int>() { 1, m_nNumMatches * 4 };
464 m_blobLocPred.Reshape(rgLocShape);
465 m_blobLocGt.Reshape(rgLocShape);
466
467 m_cuda.SsdEncodeLocPrediction(m_hSsd, m_blobLocPred.count(), m_blobLocPred.mutable_gpu_data, m_blobLocGt.count(), m_blobLocGt.mutable_gpu_data);
468
469 // m_bboxUtil.EncodeLocPrediction(rgAllLocPreds, rgAllGtBboxes, m_rgAllMatchIndices, rgPriorBboxes, rgrgPriorVariances, m_param.multiboxloss_param, m_blobLocPred, m_blobLocGt);
470
471 m_locLossLayer.Reshape(m_colLocBottom, m_colLocTop);
472 m_locLossLayer.Forward(m_colLocBottom, m_colLocTop);
473 }
474 else
475 {
476 m_blobLocLoss.SetData(0, 0);
477 }
478
479 // Form data to pass on to conf_loss_layer
480 if (m_bDoNegMining)
481 m_nNumConf = m_nNumMatches + nNumNegs;
482 else
483 m_nNumConf = m_nNum * m_nNumPriors;
484
485 if (m_nNumConf >= 1)
486 {
487 // Reshape the confidence data.
488 List<int> rgConfShape = new List<int>();
489
490 if (m_confLossType == MultiBoxLossParameter.ConfLossType.SOFTMAX)
491 {
492 rgConfShape.Add(m_nNumConf);
493 m_blobConfGt.Reshape(rgConfShape);
494 rgConfShape.Add(m_nNumClasses);
495 m_blobConfPred.Reshape(rgConfShape);
496 }
497 else if (m_confLossType == MultiBoxLossParameter.ConfLossType.LOGISTIC)
498 {
499 rgConfShape.Add(1);
500 rgConfShape.Add(m_nNumConf);
501 rgConfShape.Add(m_nNumClasses);
502 m_blobConfGt.Reshape(rgConfShape);
503 m_blobConfPred.Reshape(rgConfShape);
504 }
505 else
506 {
507 m_log.FAIL("Unknown confidence loss type.");
508 }
509
510 if (!m_bDoNegMining)
511 {
512 // Consider all scores.
513 // Share data and diff with bottom[1].
514 m_log.CHECK_EQ(m_blobConfPred.count(), colBottom[1].count(), "The conf pred and bottom[1] should have the same count.");
515 m_blobConfPred.ShareData(colBottom[1]);
516 }
517
518 m_blobConfGt.SetData(m_nBackgroundLabelId);
519
520 m_cuda.SsdEncodeConfPrediction(m_hSsd, m_blobConfPred.count(), m_blobConfPred.mutable_gpu_data, m_blobConfGt.count(), m_blobConfGt.mutable_gpu_data);
521
522 // m_hostConf.CopyFrom(colBottom[1]);
523 // float[] rgfConfData = m_hostConf.GetHostDataAsFloat();
524 // m_bboxUtil.EncodeConfPrediction(rgfConfData, m_nNum, m_nNumPriors, m_param.multiboxloss_param, m_rgAllMatchIndices, m_rgrgAllNegIndices, rgAllGtBboxes, m_blobConfPred, m_blobConfGt);
525 m_confLossLayer.Reshape(m_colConfBottom, m_colConfTop);
526 m_confLossLayer.Forward(m_colConfBottom, m_colConfTop);
527 }
528 else
529 {
530 m_blobConfLoss.SetData(0, 0);
531 }
532
533 double dfNormalizer = GetNormalizer(m_param.loss_param.normalization.Value, m_nNum, m_nNumPriors, m_nNumMatches);
534 double dfLoss = 0;
535
536 if (m_param.propagate_down[0])
537 {
538 double dfLocLoss = Utility.ConvertVal<T>(m_blobLocLoss.GetData(0));
539 dfLoss += m_fLocWeight * dfLocLoss / dfNormalizer;
540 }
541
542 if (m_param.propagate_down[1])
543 {
544 double dfConfLoss = Utility.ConvertVal<T>(m_blobConfLoss.GetData(0));
545 dfLoss += dfConfLoss / dfNormalizer;
546 }
547
548 colTop[0].SetData(dfLoss, 0);
549 }
550
551
552
560 protected void forwardCpu(BlobCollection<T> colBottom, BlobCollection<T> colTop)
561 {
562 // Retrieve all ground truth.
563 m_hostGt.CopyFrom(colBottom[3]);
564 float[] rgfGtData = m_hostGt.GetHostDataAsFloat();
565 DictionaryMap<List<NormalizedBBox>> rgAllGtBboxes = m_bboxUtil.GetGroundTruth(rgfGtData, m_nNumGt, m_nBackgroundLabelId, m_bUseDifficultGt);
566
567 // Retrieve all prior bboxes. It is the same within a batch since we assume all
568 // images in a batch are of the same dimension.
569 List<List<float>> rgrgPriorVariances;
570 m_hostPrio.CopyFrom(colBottom[2]);
571 float[] rgfPriorData = m_hostPrio.GetHostDataAsFloat();
572 List<NormalizedBBox> rgPriorBboxes = m_bboxUtil.GetPrior(rgfPriorData, m_nNumPriors, out rgrgPriorVariances);
573
574 // Retrieve all predictions.
575 m_hostLoc.CopyFrom(colBottom[0]);
576 float[] rgfLocData = m_hostLoc.GetHostDataAsFloat();
577 List<LabelBBox> rgAllLocPreds = m_bboxUtil.GetLocPredictions(rgfLocData, m_nNum, m_nNumPriors, m_nLocClasses, m_bShareLocation);
578
579 // Find matches between source bboxes and ground truth bboxes.
580 List<DictionaryMap<List<float>>> rgAllMatchOverlaps;
581 m_bboxUtil.FindMatches(rgAllLocPreds, rgAllGtBboxes, rgPriorBboxes, rgrgPriorVariances, m_param.multiboxloss_param, out rgAllMatchOverlaps, out m_rgAllMatchIndices);
582
583 // Sample hard negative (and positive) examples based on mining type.
584 int nNumNegs;
585 m_nNumMatches = m_bboxUtil.MineHardExamples(colBottom[1], rgAllLocPreds, rgAllGtBboxes, rgPriorBboxes, rgrgPriorVariances, rgAllMatchOverlaps, m_param.multiboxloss_param, m_rgAllMatchIndices, m_rgrgAllNegIndices, out nNumNegs);
586
587 if (m_nNumMatches >= 1)
588 {
589 // Form data to pass on to loc_loss_layer.
590 List<int> rgLocShape = new List<int>() { 1, m_nNumMatches * 4 };
591 m_blobLocPred.Reshape(rgLocShape);
592 m_blobLocGt.Reshape(rgLocShape);
593
594 m_bboxUtil.EncodeLocPrediction(rgAllLocPreds, rgAllGtBboxes, m_rgAllMatchIndices, rgPriorBboxes, rgrgPriorVariances, m_param.multiboxloss_param, m_blobLocPred, m_blobLocGt);
595
596 m_locLossLayer.Reshape(m_colLocBottom, m_colLocTop);
597 m_locLossLayer.Forward(m_colLocBottom, m_colLocTop);
598 }
599 else
600 {
601 m_blobLocLoss.SetData(0, 0);
602 }
603
604 // Form data to pass on to conf_loss_layer
605 if (m_bDoNegMining)
606 m_nNumConf = m_nNumMatches + nNumNegs;
607 else
608 m_nNumConf = m_nNum * m_nNumPriors;
609
610 if (m_nNumConf >= 1)
611 {
612 // Reshape the confidence data.
613 List<int> rgConfShape = new List<int>();
614
615 if (m_confLossType == MultiBoxLossParameter.ConfLossType.SOFTMAX)
616 {
617 rgConfShape.Add(m_nNumConf);
618 m_blobConfGt.Reshape(rgConfShape);
619 rgConfShape.Add(m_nNumClasses);
620 m_blobConfPred.Reshape(rgConfShape);
621 }
622 else if (m_confLossType == MultiBoxLossParameter.ConfLossType.LOGISTIC)
623 {
624 rgConfShape.Add(1);
625 rgConfShape.Add(m_nNumConf);
626 rgConfShape.Add(m_nNumClasses);
627 m_blobConfGt.Reshape(rgConfShape);
628 m_blobConfPred.Reshape(rgConfShape);
629 }
630 else
631 {
632 m_log.FAIL("Unknown confidence loss type.");
633 }
634
635 if (!m_bDoNegMining)
636 {
637 // Consider all scores.
638 // Share data and diff with bottom[1].
639 m_log.CHECK_EQ(m_blobConfPred.count(), colBottom[1].count(), "The conf pred and bottom[1] should have the same count.");
640 m_blobConfPred.ShareData(colBottom[1]);
641 }
642
643 m_blobConfGt.SetData(m_nBackgroundLabelId);
644
645 m_hostConf.CopyFrom(colBottom[1]);
646 float[] rgfConfData = m_hostConf.GetHostDataAsFloat();
647 m_bboxUtil.EncodeConfPrediction(rgfConfData, m_nNum, m_nNumPriors, m_param.multiboxloss_param, m_rgAllMatchIndices, m_rgrgAllNegIndices, rgAllGtBboxes, m_blobConfPred, m_blobConfGt);
648 m_confLossLayer.Reshape(m_colConfBottom, m_colConfTop);
649 m_confLossLayer.Forward(m_colConfBottom, m_colConfTop);
650 }
651 else
652 {
653 m_blobConfLoss.SetData(0, 0);
654 }
655
656 double dfNormalizer = GetNormalizer(m_param.loss_param.normalization.Value, m_nNum, m_nNumPriors, m_nNumMatches);
657 double dfLoss = 0;
658
659 if (m_param.propagate_down[0])
660 {
661 double dfLocLoss = Utility.ConvertVal<T>(m_blobLocLoss.GetData(0));
662 dfLoss += m_fLocWeight * dfLocLoss / dfNormalizer;
663 }
664
665 if (m_param.propagate_down[1])
666 {
667 double dfConfLoss = Utility.ConvertVal<T>(m_blobConfLoss.GetData(0));
668 dfLoss += dfConfLoss / dfNormalizer;
669 }
670
671 colTop[0].SetData(dfLoss, 0);
672 }
673
681 protected override void forward(BlobCollection<T> colBottom, BlobCollection<T> colTop)
682 {
684 forwardGpu(colBottom, colTop);
685 else
686 forwardCpu(colBottom, colTop);
687 }
688
704 protected override void backward(BlobCollection<T> colTop, List<bool> rgbPropagateDown, BlobCollection<T> colBottom)
705 {
706 if (rgbPropagateDown[2])
707 m_log.FAIL(m_type.ToString() + " Layer cannot backpropagate to prior inputs.");
708
709 if (rgbPropagateDown[3])
710 m_log.FAIL(m_type.ToString() + " Layer cannot backpropagate to label inputs.");
711
712 // Back propagate on location prediction.
713 if (rgbPropagateDown[0])
714 {
715 colBottom[0].SetDiff(0);
716
717 if (m_nNumMatches >= 1)
718 {
719 int nLocBottomDiffOffset = 0;
720 float[] rgfLocBottomDiff = Utility.ConvertVecF<T>(colBottom[0].mutable_cpu_diff);
721 List<bool> rgLocPropagateDown = new List<bool>();
722
723 // Only back propagate on prediction, not ground truth.
724 rgLocPropagateDown.Add(true);
725 rgLocPropagateDown.Add(false);
726 m_locLossLayer.Backward(m_colLocTop, rgLocPropagateDown, m_colLocBottom);
727
728 // Scale gradient.
729 double dfNormalizer = GetNormalizer(m_param.loss_param.normalization.Value, m_nNum, m_nNumPriors, m_nNumMatches);
730 double dfLossWeight = Utility.ConvertVal<T>(colTop[0].GetDiff(0)) / dfNormalizer;
731 m_cuda.scal(m_blobLocPred.count(), dfLossWeight, m_blobLocPred.mutable_gpu_diff);
732
733 // Copy gradient back to bottom[0];
734 float[] rgfLocPredDiff = Utility.ConvertVecF<T>(m_blobLocPred.mutable_cpu_diff);
735 int nCount = 0;
736
737 for (int i = 0; i < m_nNum; i++)
738 {
739 DictionaryMap<List<int>> rgMap = m_rgAllMatchIndices[i];
740
741 foreach (KeyValuePair<int, List<int>> kv in rgMap.Map)
742 {
743 int nLabel = (m_bShareLocation) ? 0 : kv.Key;
744 List<int> rgMatchIndex = kv.Value;
745
746 for (int j = 0; j < rgMatchIndex.Count; j++)
747 {
748 if (rgMatchIndex[j] <= -1)
749 continue;
750
751 // Copy the diff to the right place.
752 int nStartIdx = m_nLocClasses * 4 * j + nLabel * 4;
753 Array.Copy(rgfLocPredDiff, nCount * 4, rgfLocBottomDiff, nLocBottomDiffOffset + nStartIdx, 4);
754 nCount++;
755 }
756 }
757
758 nLocBottomDiffOffset += colBottom[0].offset(1);
759 }
760
761 colBottom[0].mutable_cpu_diff = Utility.ConvertVec<T>(rgfLocBottomDiff);
762 }
763 }
764
765 // Back propagate on confidence prediction
766 if (rgbPropagateDown[1])
767 {
768 colBottom[1].SetDiff(0);
769
770 if (m_nNumConf >= 1)
771 {
772 int nConfBottomDiffOffset = 0;
773 float[] rgfConfBottomDiff = Utility.ConvertVecF<T>(colBottom[1].mutable_cpu_diff);
774 List<bool> rgConfPropagateDown = new List<bool>();
775
776 // Only back propagate on prediction, not ground truth.
777 rgConfPropagateDown.Add(true);
778 rgConfPropagateDown.Add(false);
779 m_confLossLayer.Backward(m_colConfTop, rgConfPropagateDown, m_colConfBottom);
780
781 // Scale gradient.
782 double dfNormalizer = GetNormalizer(m_param.loss_param.normalization.Value, m_nNum, m_nNumPriors, m_nNumMatches);
783 double dfLossWeight = Utility.ConvertVal<T>(colTop[0].GetDiff(0)) / dfNormalizer;
784 m_cuda.scal(m_blobConfPred.count(), dfLossWeight, m_blobConfPred.mutable_gpu_diff);
785
786 // Copy gradient back to bottom[1];
787 float[] rgfConfPredDiff = Utility.ConvertVecF<T>(m_blobConfPred.mutable_cpu_diff);
788 if (m_bDoNegMining)
789 {
790 int nCount = 0;
791
792 for (int i = 0; i < m_nNum; i++)
793 {
794 // Copy matched (positive) bboxes scores' diff.
795 Dictionary<int, List<int>> rgMap = m_rgAllMatchIndices[i].Map;
796
797 foreach (KeyValuePair<int, List<int>> kv in rgMap)
798 {
799 List<int> rgMatchIndex = kv.Value;
800 m_log.CHECK_EQ(rgMatchIndex.Count, m_nNumPriors, "The match index count should equal the num priors!");
801
802 for (int j = 0; j < m_nNumPriors; j++)
803 {
804 if (rgMatchIndex[j] <= -1)
805 continue;
806
807 // Copy the diff to the right place.
808 Array.Copy(rgfConfPredDiff, nCount * m_nNumClasses, rgfConfBottomDiff, nConfBottomDiffOffset + j * m_nNumClasses, m_nNumClasses);
809 nCount++;
810 }
811 }
812
813 // Copy negative bboxes scores' diff
814 for (int n = 0; n < m_rgrgAllNegIndices[i].Count; n++)
815 {
816 int j = m_rgrgAllNegIndices[i][n];
817 m_log.CHECK_LT(j, m_nNumPriors, "The index must be less than the num priors!");
818
819 Array.Copy(rgfConfPredDiff, nCount * m_nNumClasses, rgfConfBottomDiff, nConfBottomDiffOffset + j * m_nNumClasses, m_nNumClasses);
820 nCount++;
821 }
822
823 nConfBottomDiffOffset += colBottom[1].offset(1);
824 }
825
826 colBottom[1].mutable_cpu_diff = Utility.ConvertVec<T>(rgfConfBottomDiff);
827 }
828 else
829 {
830 // The diff is already computed and stored.
831 m_cuda.copy(colBottom[1].count(), m_blobConfPred.gpu_diff, colBottom[1].mutable_gpu_diff);
832 }
833 }
834 }
835
836 // After backward, remove match statistics.
837 m_rgAllMatchIndices.Clear();
838 m_rgrgAllNegIndices.Clear();
839 }
840 }
841}
The Log class provides general output in text form.
Definition: Log.cs:13
void CHECK(bool b, string str)
Test a flag for true.
Definition: Log.cs:227
void WriteLine(string str, bool bOverrideEnabled=false, bool bHeader=false, bool bError=false, bool bDisable=false)
Write a line of output.
Definition: Log.cs:80
void FAIL(string str)
Causes a failure which throws an exception with the desciptive text.
Definition: Log.cs:394
void CHECK_EQ(double df1, double df2, string str)
Test whether one number is equal to another.
Definition: Log.cs:239
void CHECK_GE(double df1, double df2, string str)
Test whether one number is greater than or equal to another.
Definition: Log.cs:287
void CHECK_LT(double df1, double df2, string str)
Test whether one number is less than another.
Definition: Log.cs:275
The Utility class provides general utility funtions.
Definition: Utility.cs:35
static List< int > Create(int nCount, int nStart, int nInc)
Create a new List and fill it with values starting with start and incrementing by inc.
Definition: Utility.cs:721
static double[] ConvertVec(float[] rgf)
Convert an array of float to an array of generics.
Definition: Utility.cs:550
The BBox class processes the NormalizedBBox data used with SSD.
Definition: BBoxUtility.cs:22
The BlobCollection contains a list of Blobs.
void Add(Blob< T > b)
Add a new Blob to the collection.
void SetData(double df)
Set all blob data to the value specified.
void SetDiff(double df)
Set all blob diff to the value specified.
int Count
Returns the number of items in the collection.
The Blob is the main holder of data that moves through the Layers of the Net.
Definition: Blob.cs:25
void SetData(T[] rgData, int nCount=-1, bool bSetCount=true)
Sets a number of items within the Blob's data.
Definition: Blob.cs:1922
void ShareData(Blob< T > b)
Set the data to point to the data of the other blob – useful in Layers which simply perform a copy in...
Definition: Blob.cs:1813
long mutable_gpu_diff
Returns the diff GPU handle used by the CudaDnn connection.
Definition: Blob.cs:1555
T[] mutable_cpu_diff
Get diff from the GPU and bring it over to the host, or Set diff from the Host and send it over to th...
Definition: Blob.cs:1511
long mutable_gpu_data
Returns the data GPU handle used by the CudaDnn connection.
Definition: Blob.cs:1487
void Reshape(int nNum, int nChannels, int nHeight, int nWidth, bool? bUseHalfSize=null)
DEPRECIATED; use
Definition: Blob.cs:442
T GetData(int nIdx)
Returns the data at a given flat index within the Blob.
Definition: Blob.cs:1893
int count()
Returns the total number of items in the Blob.
Definition: Blob.cs:739
string Name
Get/set the name of the Blob.
Definition: Blob.cs:2184
long gpu_diff
Returns the diff GPU handle used by the CudaDnn connection.
Definition: Blob.cs:1541
The CudaDnn object is the main interface to the Low-Level Cuda C++ DLL.
Definition: CudaDnn.cs:969
The HostBuffer helps manage host memory, often used when implementing CPU versions of a function or l...
Definition: HostBuffer.cs:14
float[] GetHostDataAsFloat()
Returns the host buffer data as an array of floats.
Definition: HostBuffer.cs:136
void Dispose()
Release all resources used.
Definition: HostBuffer.cs:33
void CopyFrom(Blob< T > b, bool bFromDiff=false)
Copy the gpu data from the blob to the host buffer.
Definition: HostBuffer.cs:72
An interface for the units of computation which can be composed into a Net.
Definition: Layer.cs:31
Log m_log
Specifies the Log for output.
Definition: Layer.cs:43
LayerParameter m_param
Specifies the LayerParameter describing the Layer.
Definition: Layer.cs:47
void Backward(BlobCollection< T > colTop, List< bool > rgbPropagateDown, BlobCollection< T > colBottom)
Given the top Blob error gradients, compute the bottom Blob error gradients.
Definition: Layer.cs:815
double Forward(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Given the bottom (input) Blobs, this function computes the top (output) Blobs and the loss.
Definition: Layer.cs:728
abstract void Reshape(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Adjust the shapes of top blobs and internal buffers to accomodate the shapes of the bottom blobs.
void Dispose()
Releases all GPU and host resources used by the Layer.
Definition: Layer.cs:180
CudaDnn< T > m_cuda
Specifies the CudaDnn connection to Cuda.
Definition: Layer.cs:39
void Setup(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Implements common Layer setup functionality.
Definition: Layer.cs:439
static Layer< T > Create(CudaDnn< T > cuda, Log log, LayerParameter p, CancelEvent evtCancel, IXDatabaseBase db=null, TransferInput trxinput=null)
Create a new Layer based on the LayerParameter.
Definition: Layer.cs:1468
LayerParameter.LayerType m_type
Specifies the Layer type.
Definition: Layer.cs:35
The LossLayer provides an interface for Layer's that take two blobs as input – usually (1) prediction...
Definition: LossLayer.cs:23
double GetNormalizer(LossParameter.NormalizationMode normalization_mode, int nOuterNum, int nInnerNum, int nValidCount)
Returns the normalizer used to normalize the loss.
Definition: LossLayer.cs:106
The MultiBoxLossLayer performs multibox operations including the following:
override int ExactNumTopBlobs
Returns the exact number of top blobs required: argmax
void forwardGpu(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Forward GPU computation.
MultiBoxLossLayer(CudaDnn< T > cuda, Log log, LayerParameter p)
Constructor.
override void forward(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Forward computation.
override void backward(BlobCollection< T > colTop, List< bool > rgbPropagateDown, BlobCollection< T > colBottom)
Computes the multibox loss error gradient w.r.t the predictions.
override void LayerSetUp(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Setup the layer.
override void setup_internal_blobs(BlobCollection< T > col)
Derivative layers should add all internal blobws to the 'col' provided.
override void Reshape(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Reshape the bottom (input) and top (output) blobs.
void forwardCpu(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Forward computation.
override void dispose()
Release any resources used.
override int ExactNumBottomBlobs
Returns the exact number of bottom blobs required: input
Specifies the base parameter for all layers.
string name
Specifies the name of this LayerParameter.
List< double > loss_weight
Specifies the loss weight.
MultiBoxLossParameter multiboxloss_param
Returns the parameter set when initializing with LayerType.MULTIBOX_LOSS
SoftmaxParameter softmax_param
Returns the parameter set when initialized with LayerType.SOFTMAX
List< bool > propagate_down
Specifies whether or not the LayerParameter (or protions of) should be backpropagated.
LayerType
Specifies the layer type.
override string ToString()
Returns a string representation of the LayerParameter.
LossParameter loss_param
Returns the parameter set when initialized with LayerType.LOSS
Stores the parameters used by loss layers.
NormalizationMode
How to normalize the loss for loss layers that aggregate across batches, spatial dimensions,...
NormalizationMode? normalization
Specifies the normalization mode (default = VALID).
bool Active
When active, the parameter is used, otherwise it is ignored.
int axis
The axis along which to perform the softmax – may be negative to index from the end (e....
Specifies the parameters for the MultiBoxLossParameter.
float loc_weight
Get/set the weight for the localization loss (default = 1.0).
float overlap_threshold
Get/set the overlap threshold (default = 0.5).
bool use_difficult_gt
Get/set whether or not to consider the difficult ground truth (defalt = true).
bool use_gpu
Use the GPU version of the algorithm.
PriorBoxParameter.CodeType code_type
Get/set the coding method for the bounding box.
float neg_overlap
Get/set the negative overlap upperbound for the unmatched predictions (default = 0....
LocLossType
Defines the localization loss types.
int sample_size
Get/set the number of samples (default = 64).
float neg_pos_ratio
Get/set the negative/positive ratio (default = 3.0).
bool share_location
Get/sets whether or not the bounding box is shared among different classes (default = true).
MiningType
Defines the mining type used during training.
NonMaximumSuppressionParameter nms_param
Get/set the parameters used for the non maximum suppression during hard example training.
LocLossType loc_loss_type
Get/set the localization loss type (default = SMOOTH_L1).
uint background_label_id
Get/set the background label id.
ConfLossType
Defines the confidence loss types.
bool encode_variance_in_target
Get/set whether or not to encode the variance of the prior box in the loc loss target instead of in t...
bool ignore_cross_boundary_bbox
Get/set whether or not to ignore cross boundary bbox during matching (default = false)....
bool map_object_to_agnostic
Get/set whether or not to map all object classes to an agnostic class (default = false)....
bool? do_neg_mining
DEPRECIATED: Get/set whether or not to perform negative mining (default = false).
bool bp_inside
Get/set whether or not to only backpropagate on corners which are inside of the image region when enc...
ConfLossType conf_loss_type
Get/set the confidence loss type (default = SOFTMAX).
bool use_prior_for_matching
Get/set whether or not to use prior for matching.
uint num_classes
Get/set the number of classes to be predicted - required!
MiningType mining_type
Get/set the mining type used during training (default = MAX_NEGATIVE).
bool use_prior_for_nms
Get/set whether or not to use the prior bbox for nms.
MatchType match_type
Get/set the matching method used during training (default = PER_PREDICTION).
float eta
Get/set the parameter for adaptive nms.
int? top_k
Get/set the maximum number of results kept.
float nms_threshold
Get/set the threshold to be used in nms.
The MyCaffe.basecode contains all generic types used throughout MyCaffe.
Definition: Annotation.cs:12
The MyCaffe.common namespace contains common MyCaffe classes.
Definition: BatchInput.cs:8
SSD_CONF_LOSS_TYPE
Defines the confidence loss types used during SSD cuda training.
Definition: CudaDnn.cs:608
SSD_MATCH_TYPE
Defines the matching method used during SSD cuda training.
Definition: CudaDnn.cs:566
SSD_CODE_TYPE
Defines the encode/decode type used during SSD cuda training.
Definition: CudaDnn.cs:585
SSD_LOC_LOSS_TYPE
Defines the location loss types used during SSD cuda training.
Definition: CudaDnn.cs:627
SSD_MINING_TYPE
Defines the mining type used during SSD cuda training.
Definition: CudaDnn.cs:540
The MyCaffe.layers.ssd namespace contains all Single-Shot MultiBox (SSD) related layers.
Definition: LayerFactory.cs:19
The MyCaffe.param.ssd namespace contains all SSD related parameter objects that correspond to the nat...
The MyCaffe.param namespace contains parameters used to create models.
The MyCaffe namespace contains the main body of MyCaffe code that closesly tracks the C++ Caffe open-...
Definition: Annotation.cs:12