MyCaffe  1.12.2.41
Deep learning software for Windows C# programmers.
DataLayer.cs
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Threading;
6using System.Diagnostics;
7using MyCaffe.basecode;
8using MyCaffe.db.image;
9using MyCaffe.param;
10using MyCaffe.common;
11using MyCaffe.data;
12using MyCaffe.fillers;
13using System.IO;
14using System.Drawing;
15
16namespace MyCaffe.layers
17{
24 {
28 protected DB<T> m_db;
33 UInt64 m_nOffset = 0;
37 protected Stopwatch m_swTimerBatch;
41 protected Stopwatch m_swTimerTransaction;
45 protected double m_dfReadTime;
49 protected double m_dfTransTime;
50 private T[] m_rgTopData = null;
51 private T[] m_rgTopLabel = null;
52 private T[] m_rgOneHotLabel = null;
53 private int[] m_rgTopShape = null;
54 private bool m_bMatchingCycle = true;
55 private Datum m_datumNoise = null;
56 private LabelCollection m_rgBatchLabels = null;
57 private Blob<T> m_blobMask1 = null;
58 private Blob<T> m_blobMask = null;
59 private Blob<T> m_blobDebug1 = null;
60 private int m_nIteration = 0;
61 private int m_nBatchCount = 0;
62 private SimpleDatum[] m_rgDatum = null;
63
67 public event EventHandler<LastBatchLoadedArgs> OnBatchLoad;
68
78 : base(cuda, log, p, db, evtCancel)
79 {
80 if (db.GetVersion() != DB_VERSION.IMG_V1 && db.GetVersion() != DB_VERSION.IMG_V2)
81 throw new Exception("Currently only image databases are supported by the DataLayer.");
82
84
86 m_rgBatchLabels = new LabelCollection();
87
88 Tuple<DB_LABEL_SELECTION_METHOD, DB_ITEM_SELECTION_METHOD> kvSel = db.GetSelectionMethod();
89 DB_ITEM_SELECTION_METHOD imgSel = kvSel.Item2;
90
92 {
94 imgSel |= DB_ITEM_SELECTION_METHOD.PAIR;
95 else
96 imgSel &= (~DB_ITEM_SELECTION_METHOD.PAIR);
97 }
98
100 {
102 imgSel |= DB_ITEM_SELECTION_METHOD.RANDOM;
103 else
104 imgSel &= (~DB_ITEM_SELECTION_METHOD.RANDOM);
105 }
106
107 db.SetSelectionMethod(null, imgSel);
108
109 m_db = new data.DB<T>((IXImageDatabaseBase)db);
110 m_db.Open(p.data_param.source);
111
113 {
114 m_swTimerBatch = new Stopwatch();
115 m_swTimerTransaction = new Stopwatch();
116 }
117
119 {
120 m_blobMask = new Blob<T>(cuda, log, false);
121 m_blobMask1 = new Blob<T>(cuda, log, false);
122 }
123
125 m_blobDebug1 = new Blob<T>(cuda, log, false);
126 }
127
131 protected override void preStop()
132 {
133 base.preStop();
134
135 if (m_rgBatchLabels != null)
136 m_rgBatchLabels.Cancel();
137 }
138
140 protected override void dispose()
141 {
142 base.dispose();
143
144 if (m_rgBatchLabels != null)
145 {
146 m_rgBatchLabels.Dispose();
147 m_rgBatchLabels = null;
148 }
149
150 if (m_blobMask != null)
151 {
152 m_blobMask.Dispose();
153 m_blobMask = null;
154 }
155
156 if (m_blobMask1 != null)
157 {
158 m_blobMask1.Dispose();
159 m_blobMask1 = null;
160 }
161
162 if (m_blobDebug1 != null)
163 {
164 m_blobDebug1.Dispose();
165 m_blobDebug1 = null;
166 }
167 }
168
172 protected override bool delayPrefetch
173 {
174 get
175 {
177 return true;
178
179 return false;
180 }
181 }
182
189 public void Connect(DataLayer<T> src)
190 {
191 src.OnBatchLoad += Src_OnBatchLoad;
192 m_log.WriteLine("DataLayer '" + m_param.name + "' is now connected to DataLayer '" + src.m_param.name + "'.");
193
195 src.statupPrefetch();
196 }
197
201 public void Disconnect()
202 {
203 m_rgBatchLabels.Cancel();
204 }
205
206 private void Src_OnBatchLoad(object sender, LastBatchLoadedArgs e)
207 {
208 int nWait = m_rgBatchLabels.WaitProcessing;
209 if (nWait == 0)
210 return;
211
212 m_rgBatchLabels.Set(e.Labels);
213 }
214
220 protected override void DataLayerSetUp(BlobCollection<T> colBottom, BlobCollection<T> colTop)
221 {
222 int nBatchSize = (int)m_param.data_param.batch_size;
223 bool bLoadDataCriteria = false;
224 m_bMatchingCycle = true;
225
227
229 bLoadDataCriteria = true;
230
231 // Read a data point, and use it to initialize the top blob.
232 SimpleDatum datum = m_cursor.GetValue(null, bLoadDataCriteria);
233
234 // Use data transformer to infer the expected blob shape from the datum.
235 m_rgTopShape = m_transformer.InferBlobShape(datum, m_rgTopShape);
236
237 // When using noise as the secondary image, fill it with noise.
239 m_datumNoise = createNoisyData(m_rgTopShape, datum);
240
241 // Double the channels when loading image pairs where the first image is loaded followed by the second on the channel.
243 {
244 m_log.CHECK_EQ(m_param.data_param.images_per_blob, 2, "Currently images_per_blob only supports 2 image pairing and must be set to 2 for image pairing.");
245 m_rgTopShape[1] *= m_param.data_param.images_per_blob;
246 }
247
248 // Reshape colTop[0] and prefetch data according to the batch size.
249 m_rgTopShape[0] = nBatchSize;
250 colTop[0].Reshape(m_rgTopShape);
251
252 for (int i = 0; i < m_rgPrefetch.Length; i++)
253 {
254 m_rgPrefetch[i].Data.Reshape(m_rgTopShape);
255 }
256
257 m_log.WriteLine("output data size: " + colTop[0].ToSizeString());
258
259 // Fill out the masks, if used.
261 createMasks(Utility.Clone<int>(m_rgTopShape));
262
263 // Reshape debug data, if used.
265 createDebug(Utility.Clone<int>(m_rgTopShape));
266
267 // Label
268 if (m_bOutputLabels)
269 {
270 List<int> rgLabelShape = new List<int>() { nBatchSize };
271
272 // When using multi-labels, resize to batch x the number of multiple
273 // labels per image.
275 {
277 {
279 m_log.FAIL("Image pairing per blob currently only supports the " + DataParameter.LABEL_TYPE.SINGLE.ToString() + " label type.");
280
281 if (datum.DataCriteria == null || datum.DataCriteria.Length == 0)
282 m_log.FAIL("Could not find the multi-label data. The data source '" + m_param.data_param.source + "' does not appear to have any Image Criteria data.");
283
284 if (datum.DataCriteriaFormat == SimpleDatum.DATA_FORMAT.LIST_DOUBLE)
285 {
286 List<double> rg = BinaryData.UnPackDoubleList(datum.DataCriteria, datum.DataCriteriaFormat);
287 int nLen = rg.Count;
288 rgLabelShape.Add(nLen);
289 rgLabelShape.Add(1);
290 rgLabelShape.Add(1);
291 }
292 else if (datum.DataCriteriaFormat == SimpleDatum.DATA_FORMAT.LIST_FLOAT)
293 {
294 List<float> rg = BinaryData.UnPackFloatList(datum.DataCriteria, datum.DataCriteriaFormat);
295 int nLen = rg.Count;
296 rgLabelShape.Add(nLen);
297 rgLabelShape.Add(1);
298 rgLabelShape.Add(1);
299 }
300 else
301 {
302 // Get the number of items and the item size from the end of the data.
303 int nLen = BitConverter.ToInt32(datum.DataCriteria, datum.DataCriteria.Length - (sizeof(int) * 4));
304 int nItemSize = BitConverter.ToInt32(datum.DataCriteria, datum.DataCriteria.Length - (sizeof(int) * 3));
305
306 rgLabelShape.Add(nLen);
307 m_log.CHECK_EQ(nItemSize, 1, "Currently only byte sized labels are supported in multi-label scenarios.");
308 }
309 }
310 else
311 {
312 rgLabelShape.Add(m_param.data_param.one_hot_label_size);
313 rgLabelShape.Add(1);
314 rgLabelShape.Add(1);
315 }
316 }
317 else
318 {
319 int nChannels = 1;
320
321 // 1 label comparison + each label in pair order to which they were added to the blob.
323 {
326 }
327
328 rgLabelShape.Add(nChannels);
329 }
330
331 colTop[1].Reshape(rgLabelShape);
332
333 for (int i = 0; i < m_rgPrefetch.Length; i++)
334 {
335 m_rgPrefetch[i].Label.Reshape(rgLabelShape);
336 }
337 }
338
339 m_nIteration = 0;
340 m_nBatchCount = 0;
341 }
342
343 private void createMasks(int[] rgTopShape)
344 {
345 int nImgPerBlob = m_param.data_param.images_per_blob;
346 m_blobMask.Reshape(rgTopShape);
347 rgTopShape[0] = 1;
348 rgTopShape[1] /= nImgPerBlob;
349 m_blobMask1.Reshape(rgTopShape);
350 m_blobMask1.SetData(1);
351 float[] rgData = convertF(m_blobMask1.update_cpu_data());
352 m_transformer.MaskData(rgTopShape, rgData);
353 m_blobMask1.mutable_cpu_data = convert(rgData);
354
355 int nDim = m_blobMask1.count();
356 int nOffset = 0;
357 for (int n = 0; n < m_blobMask.num; n++)
358 {
359 for (int j = 0; j < nImgPerBlob; j++)
360 {
361 m_cuda.copy(nDim, m_blobMask1.gpu_data, m_blobMask.mutable_gpu_data, 0, nOffset);
362 nOffset += nDim;
363 }
364 }
365 }
366
367 private void createDebug(int[] rgTopShape)
368 {
369 int nImgPerBlob = m_param.data_param.images_per_blob;
370 rgTopShape[0] = 1;
371 rgTopShape[1] /= nImgPerBlob;
372 m_blobDebug1.Reshape(rgTopShape);
373 }
374
375 private Datum createNoisyData(int[] rgTopShape, SimpleDatum datum)
376 {
377 Blob<T> blobNoise = new Blob<T>(m_cuda, m_log, rgTopShape);
378
379 try
380 {
382 filler.Fill(blobNoise);
383
385 {
386 SimpleDatum sdMean = m_transformer.ImageMean;
387 if (sdMean == null)
388 {
389 if (m_imgdb == null)
390 m_log.FAIL("No 'mean' image is loaded, yet the MyCaffe Image Database = null, and it is required to get the mean image.");
391
392 sdMean = m_imgdb.GetItemMean(m_src.ID);
393 }
394
395 if (sdMean == null)
396 m_log.FAIL("The data source '" + m_src.Name + "' does not have a mean image!");
397
398 if (sdMean.IsRealData)
399 {
400 blobNoise.mutable_cpu_diff = sdMean.GetData<T>();
401 }
402 else
403 {
404 double dfMin = blobNoise.min_data;
405 double dfMax = blobNoise.max_data;
406
407 if (dfMin < -1.0 || dfMax > 1.0)
408 m_log.WriteLine("WARNING! The noise filler is producing numbers outside of the range [-1,1] which may cause a saturated final noise data image.");
409
410 blobNoise.mutable_cpu_diff = sdMean.GetData<T>();
411 }
412
413 m_cuda.mul(blobNoise.count(), blobNoise.gpu_diff, blobNoise.gpu_data, blobNoise.mutable_gpu_data);
414 }
415
416 Datum datumNoise;
417 if (typeof(T) == typeof(double))
418 {
419 double[] rgdf = convertD(blobNoise.update_cpu_data());
420
421 if (datum.IsRealData)
422 {
423 List<double> rgdf1 = new List<double>(rgdf);
424 datumNoise = new Datum(datum.IsRealData, datum.Channels, datum.Width, datum.Height, m_param.data_param.data_noise_param.noise_data_label, DateTime.MinValue, rgdf1, 1, false, -1);
425 }
426 else
427 {
428 List<byte> rgb = rgdf.Select(p => Math.Min((byte)p, (byte)255)).ToList();
429 datumNoise = new Datum(datum.IsRealData, datum.Channels, datum.Width, datum.Height, m_param.data_param.data_noise_param.noise_data_label, DateTime.MinValue, rgb, 1, false, -1);
430 }
431 }
432 else
433 {
434 float[] rgf = convertF(blobNoise.update_cpu_data());
435
436 if (datum.IsRealData)
437 {
438 List<float> rgf1 = new List<float>(rgf);
439 datumNoise = new Datum(datum.IsRealData, datum.Channels, datum.Width, datum.Height, m_param.data_param.data_noise_param.noise_data_label, DateTime.MinValue, rgf1, 1, false, -1);
440 }
441 else
442 {
443 List<byte> rgb = rgf.Select(p => Math.Min((byte)p, (byte)255)).ToList();
444 datumNoise = new Datum(datum.IsRealData, datum.Channels, datum.Width, datum.Height, m_param.data_param.data_noise_param.noise_data_label, DateTime.MinValue, rgb, 1, false, -1);
445 }
446 }
447
448 if (!string.IsNullOrEmpty(m_param.data_param.data_noise_param.noisy_save_path))
449 {
450 if (!Directory.Exists(m_param.data_param.data_noise_param.noisy_save_path))
451 m_log.FAIL("The noisy save path '" + m_param.data_param.data_noise_param.noisy_save_path + "' does not exist!");
452
453 string strPath = m_param.data_param.data_noise_param.noisy_save_path.TrimEnd('\\');
454 Bitmap bmp = ImageData.GetImage(datumNoise);
455 bmp.Save(m_param.data_param.data_noise_param.noisy_save_path + "\\noisy_data.png");
456 bmp.Dispose();
457 }
458
459 return datumNoise;
460 }
461 finally
462 {
463 blobNoise.Dispose();
464 }
465 }
466
470 public override int ExactNumBottomBlobs
471 {
472 get { return 0; }
473 }
474
478 public override int MinTopBlobs
479 {
480 get { return 1; }
481 }
482
486 public override int MaxTopBlobs
487 {
488 get { return 2; }
489 }
490
495 protected void Next()
496 {
497 m_cursor.Next();
498
499 if (!m_cursor.IsValid)
500 {
501 m_log.WriteLine("Restarting data prefetching to start of " + m_cursor.Count.ToString() + " items.");
502 m_cursor.SeekToFirst();
503 }
504
505 m_nOffset++;
506 }
507
512 protected bool Skip()
513 {
514 UInt64 nSize = (UInt64)m_param.solver_count;
515 UInt64 nRank = (UInt64)m_param.solver_rank;
516 // In test mode, only rank 0 runs, so avoid skipping.
517 bool bKeep = (m_nOffset % nSize) == nRank || m_param.phase == Phase.TEST;
518
519 return !bKeep;
520 }
521
526 protected override void final_process(Blob<T> blobTop)
527 {
529 {
530 int nCount = blobTop.count();
531 m_log.CHECK_EQ(m_blobMask.count(), nCount, "The mask must be the same size as the top!");
532 m_cuda.mul(nCount, m_blobMask.gpu_data, blobTop.gpu_data, blobTop.mutable_gpu_data);
533 }
534
536 {
538 {
539 int nImgPerBlob = m_param.data_param.images_per_blob;
540 int nChannels = blobTop.channels / nImgPerBlob;
541
542 if (blobTop.num_axes < 4)
543 {
544 m_log.WriteLine("WARNING! debug output only supported blobs with 4 or more axes.");
545 return;
546 }
547
549 if (!Directory.Exists(strPath))
550 Directory.CreateDirectory(strPath);
551
552 strPath = strPath.TrimEnd('\\');
553 int nDim = nChannels * blobTop.height * blobTop.width;
554 int nCount = m_blobDebug1.count();
555 int nOffset = 0;
556
557 m_log.CHECK_EQ(nDim, nCount, "The debug data is not sized properly.");
558
559 for (int n = 0; n < blobTop.num; n++)
560 {
561 for (int j = 0; j < nImgPerBlob; j++)
562 {
563 m_cuda.copy(nCount, blobTop.gpu_data, m_blobDebug1.mutable_gpu_data, nOffset, 0);
564 nOffset += nCount;
565
567 {
568 double dfUnScale = 1.0 / m_param.transform_param.scale;
569 m_blobDebug1.scale_data(dfUnScale);
570 }
571
572 float[] rgData = convertF(m_blobDebug1.mutable_cpu_data);
573
574 string strFile = strPath + "\\dbgimg_iter_" + m_nIteration.ToString() + "_num_" + n.ToString() + "_img_" + j.ToString();
575 SimpleDatum sd = new SimpleDatum(nChannels, blobTop.width, blobTop.height, rgData, 0, nDim, false);
576
577 if (nChannels == 1 || nChannels == 3)
578 {
579 Bitmap bmp = ImageData.GetImage(sd);
580 bmp.Save(strFile + ".png");
581 bmp.Dispose();
582 }
583 }
584 }
585 }
586 }
587
588 m_nIteration++;
589 }
590
595 protected override void load_batch(Batch<T> batch)
596 {
597 m_log.CHECK(batch.Data.count() > 0, "There is no space allocated for data!");
598 int nBatchSize = (int)m_param.data_param.batch_size;
599 bool bLoadDataCriteria = false;
600
602 bLoadDataCriteria = true;
603
604 if (m_bOutputLabels)
605 {
607 {
609
610 if (m_rgOneHotLabel == null || m_rgOneHotLabel.Length != nCount)
611 m_rgOneHotLabel = new T[nCount];
612
613 nCount = batch.Label.count();
614
615 if (m_rgTopLabel == null || m_rgTopLabel.Length != nCount)
616 m_rgTopLabel = new T[nCount];
617 }
618 else
619 {
620 int nCount = batch.Label.count();
621 m_log.CHECK_GT(nCount, 0, "The label count cannot be zero!");
622
623 if (m_rgTopLabel == null || m_rgTopLabel.Length < nCount)
624 m_rgTopLabel = new T[nCount];
625 }
626 }
627
629 {
630 m_swTimerBatch.Restart();
631 m_dfReadTime = 0;
632 m_dfTransTime = 0;
633 }
634
635 SimpleDatum datum;
636 int nDim = 0;
637 List<int> rgLabels = null;
638 List<int> rgTargetLabels = null;
639
640 if (OnBatchLoad != null)
641 rgLabels = new List<int>();
642
643 // If we are synced with another dataset, wait for it to load the initial data set.
645 {
646 m_log.CHECK_EQ(m_param.data_param.images_per_blob, 1, "DataLayer synchronize targets are not supported when loading more than 1 image per blob.");
647
648 int nWait = m_rgBatchLabels.WaitReady;
649 if (nWait == 0)
650 return;
651
652 rgTargetLabels = m_rgBatchLabels.Get();
653 m_log.CHECK_EQ(nBatchSize, m_rgBatchLabels.Count, "The batch label count (previously loaded by the primary dataset) does not match the batch size '" + m_param.data_param.batch_size.ToString() + "' of this layer!");
654 }
655
656 for (int i = 0; i < nBatchSize; i++)
657 {
659 m_swTimerTransaction.Restart();
660
661 while (Skip())
662 {
663 if (m_evtCancel.WaitOne(0))
664 return;
665 Next();
666 }
667
668 if (rgTargetLabels == null)
669 {
670 datum = m_cursor.GetValue(null, bLoadDataCriteria);
671
673 {
674 if (m_rgDatum == null || m_rgDatum.Length != m_param.data_param.images_per_blob - 1)
675 m_rgDatum = new SimpleDatum[m_param.data_param.images_per_blob - 1];
676
677 for (int j = 0; j < m_param.data_param.images_per_blob - 1; j++)
678 {
679 Next();
680
681 while (Skip())
682 {
683 if (m_evtCancel.WaitOne(0))
684 return;
685 Next();
686 }
687
689 {
690 if (m_bMatchingCycle)
691 {
692 m_rgDatum[j] = getNextPair(true, datum, bLoadDataCriteria);
693 }
694 else
695 {
697 m_rgDatum[j] = m_datumNoise;
698 else
699 m_rgDatum[j] = getNextPair(false, datum, bLoadDataCriteria);
700 }
701 }
702 else
703 {
705 m_rgDatum[j] = m_datumNoise;
706 else
707 m_rgDatum[j] = m_cursor.GetValue(null, bLoadDataCriteria);
708 }
709 }
710
711 m_bMatchingCycle = !m_bMatchingCycle;
712 }
713 }
714 else
715 {
716 datum = m_cursor.GetValue(rgTargetLabels[i], bLoadDataCriteria);
717 }
718
719 // When debug output is enabled, output information each image loaded.
721 {
722 saveImageInfo(m_param.data_param.data_debug_param, datum, i, 0);
723
724 if (m_rgDatum != null)
725 {
726 for (int n = 0; n < m_rgDatum.Length; n++)
727 {
728 saveImageInfo(m_param.data_param.data_debug_param, m_rgDatum[n], i, n + 1);
729 }
730 }
731 }
732
734 {
735 m_dfReadTime += m_swTimerTransaction.Elapsed.TotalMilliseconds;
736 m_swTimerTransaction.Restart();
737 }
738
739 if (i == 0)
740 {
741 // Reshape according to the first datum of each batch
742 // on single input batches allows for inputs of varying dimension.
743 // Use data transformer to infer the expected blob shape for datum.
744 m_rgTopShape = m_transformer.InferBlobShape(datum, m_rgTopShape);
745
746 // Double the channels when loading image pairs where the first image is loaded followed by the second on the channel.
747 if (m_rgDatum != null)
748 m_rgTopShape[1] *= (m_rgDatum.Length + 1);
749
750 // Reshape batch according to the batch size.
751 m_rgTopShape[0] = nBatchSize;
752 batch.Data.Reshape(m_rgTopShape);
753
754 nDim = 1;
755 for (int k = 1; k < m_rgTopShape.Length; k++)
756 {
757 nDim *= m_rgTopShape[k];
758 }
759
760 int nTopLen = nDim * nBatchSize;
761 if (m_rgTopData == null || m_rgTopData.Length != nTopLen)
762 m_rgTopData = new T[nTopLen];
763 }
764
765 // Apply data transformations (mirrow, scaling, crop, etc)
766 int nDimCount = nDim;
767
768 if (m_rgDatum != null)
769 nDimCount /= (m_rgDatum.Length + 1);
770
771 T[] rgTrans = m_transformer.Transform(datum);
772 Array.Copy(rgTrans, 0, m_rgTopData, nDim * i, nDimCount);
773
774 // When using load_image_pairs, stack the additional images right after the first.
775 if (m_rgDatum != null)
776 {
777 for (int j = 0; j < m_rgDatum.Length; j++)
778 {
779 rgTrans = m_transformer.Transform(m_rgDatum[j]);
780 int nOffset = (nDim * i) + (nDimCount * (j + 1));
781 Array.Copy(rgTrans, 0, m_rgTopData, nOffset, nDimCount);
782 }
783 }
784
785 // Copy label.
786 if (m_bOutputLabels)
787 {
789 {
791 {
792 int nMask = 0x1;
793
794 for (int j = 0; j < m_rgOneHotLabel.Length; j++)
795 {
796 if ((datum.Label & nMask) == 0)
797 m_rgOneHotLabel[j] = m_tZero;
798 else
799 m_rgOneHotLabel[j] = m_tOne;
800
801 nMask <<= 1;
802 }
803
804 Array.Copy(m_rgOneHotLabel, 0, m_rgTopLabel, i * m_rgOneHotLabel.Length, m_rgOneHotLabel.Length);
805 }
806 else
807 {
809 m_log.FAIL("Loading image pairs (images_per_blob > 1) currently only supports the " + DataParameter.LABEL_TYPE.SINGLE.ToString() + " label type.");
810
812 m_log.FAIL("Label mapping is not supported on labels of type 'MULTIPLE'.");
813
814 if (datum.DataCriteria == null || datum.DataCriteria.Length == 0)
815 m_log.FAIL("Could not find the multi-label data. The data source '" + m_param.data_param.source + "' does not appear to have any Image Criteria data.");
816
817 // Get the number of items and the item size from the end of the data.
818 int nLen = BitConverter.ToInt32(datum.DataCriteria, datum.DataCriteria.Length - (sizeof(int) * 4));
819 int nItemSize = BitConverter.ToInt32(datum.DataCriteria, datum.DataCriteria.Length - (sizeof(int) * 3));
820 int nDstIdx = i * nLen;
821
822 m_log.CHECK_EQ(nItemSize, 1, "Currently only byte sized labels are supported in multi-label scenarios.");
823 Array.Copy(datum.DataCriteria, 0, m_rgTopLabel, nDstIdx, nLen);
824 }
825 }
826 else
827 {
828 // When using image pairs, the label is set to 1 when the labels are the same and 0 when they are different.
829 if (m_rgDatum != null)
830 {
831 if (m_rgDatum.Length == 1)
832 {
833 int nLabelDim = 1;
834
837
839 {
840 int nLabel = datum.Label;
843
844 m_rgTopLabel[i * nLabelDim] = (T)Convert.ChangeType(nLabel, typeof(T));
845
846 for (int j = 0; j < m_rgDatum.Length; j++)
847 {
848 m_rgTopLabel[i * nLabelDim + 1 + j] = (T)Convert.ChangeType(m_rgDatum[j].Label, typeof(T));
849 }
850 }
851 else
852 {
853 if (datum.Label == m_rgDatum[0].Label)
854 m_rgTopLabel[i * nLabelDim] = m_tOne;
855 else
856 m_rgTopLabel[i * nLabelDim] = m_tZero;
857 }
858 }
859 else
860 m_log.FAIL("Currently image pairing only supports up to 2 images per blob.");
861 }
862 else
863 {
864 m_rgTopLabel[i] = (T)Convert.ChangeType(datum.Label, typeof(T));
865 }
866 }
867 }
868
870 m_dfTransTime += m_swTimerTransaction.Elapsed.TotalMilliseconds;
871
872 if (rgLabels != null)
873 rgLabels.Add(datum.Label);
874
875 Next();
876
877 if (m_evtCancel.WaitOne(0))
878 return;
879 }
880
881 m_nBatchCount++;
882 batch.Data.SetCPUData(m_rgTopData);
883
884 if (m_bOutputLabels)
885 batch.Label.SetCPUData(m_rgTopLabel);
886
888 {
889 m_swTimerBatch.Stop();
891 m_log.WriteLine("Prefetch batch: " + m_swTimerBatch.ElapsedMilliseconds.ToString() + " ms.", true);
892 m_log.WriteLine(" Read time: " + m_dfReadTime.ToString() + " ms.", true);
893 m_log.WriteLine("Transform time: " + m_dfTransTime.ToString() + " ms.", true);
894 }
895
897 {
898 if (m_rgBatchLabels != null)
899 m_rgBatchLabels.Done();
900 }
901
902 if (OnBatchLoad != null)
903 OnBatchLoad(this, new LastBatchLoadedArgs(rgLabels));
904 }
905
906 private SimpleDatum getNextPair(bool bMatching, SimpleDatum d, bool bLoadDataCriteria)
907 {
908 int nRetries = 10;
909 int nIdx = 0;
910 SimpleDatum dNew = null;
911 string strType = null;
912
913 if (bMatching)
914 {
915 int? nLabel = null;
916
917 if (d.Label == d.OriginalLabel)
918 nLabel = d.Label;
919
920 dNew = m_cursor.GetValue(nLabel, bLoadDataCriteria);
921
922 while (dNew.Label != d.Label && nIdx < nRetries)
923 {
924 Next();
925 dNew = m_cursor.GetValue(nLabel, bLoadDataCriteria);
926 nIdx++;
927 }
928
929 if (dNew.Label != d.Label)
930 strType = "match";
931 }
932 else
933 {
934 dNew = m_cursor.GetValue(null, bLoadDataCriteria);
935
936 while (dNew.Label == d.Label && nIdx < nRetries)
937 {
938 Next();
939 dNew = m_cursor.GetValue(null, bLoadDataCriteria);
940 nIdx++;
941 }
942
943 if (dNew.Label == d.Label)
944 strType = "non-match";
945 }
946
947 if (strType != null)
948 m_log.WriteLine("WARNING: The secondary pairing " + strType + " could not be found after " + nRetries.ToString() + " retries!");
949
950 return dNew;
951 }
952
953 private void saveImageInfo(DataDebugParameter p, SimpleDatum d, int nNum, int nImg)
954 {
955 string strFile = p.debug_save_path.TrimEnd('\\') + "\\dbgimg_iter_" + m_nBatchCount.ToString() + "_num_" + nNum.ToString() + "_img_" + nImg.ToString();
956 d.SaveInfo(strFile + ".txt");
957 }
958 }
959
960 class LabelCollection : IDisposable
961 {
962 ManualResetEvent m_evtReady = new ManualResetEvent(false);
963 ManualResetEvent m_evtDone = new ManualResetEvent(true);
964 AutoResetEvent m_evtCancel = new AutoResetEvent(false);
965 List<int> m_rgLabels = new List<int>();
966 object m_sync = new object();
967
968 public LabelCollection()
969 {
970 }
971
972 public void Dispose()
973 {
974 if (m_evtReady != null)
975 {
976 m_evtReady.Dispose();
977 m_evtReady = null;
978 }
979
980 if (m_evtDone != null)
981 {
982 m_evtDone.Dispose();
983 m_evtDone = null;
984 }
985
986 if (m_evtCancel != null)
987 {
988 m_evtCancel.Dispose();
989 m_evtCancel = null;
990 }
991 }
992
993 public void Cancel()
994 {
995 m_evtCancel.Set();
996 }
997
998 public int WaitReady
999 {
1000 get
1001 {
1002 List<WaitHandle> rgWait = new List<WaitHandle>() { m_evtCancel, m_evtReady };
1003 return WaitHandle.WaitAny(rgWait.ToArray());
1004 }
1005 }
1006
1007 public int WaitProcessing
1008 {
1009 get
1010 {
1011 List<WaitHandle> rgWait = new List<WaitHandle>() { m_evtCancel, m_evtDone };
1012 return WaitHandle.WaitAny(rgWait.ToArray());
1013 }
1014 }
1015
1016 public void Done()
1017 {
1018 m_evtDone.Set();
1019 }
1020
1021 public void Set(List<int> rg)
1022 {
1023 lock (m_sync)
1024 {
1025 m_rgLabels = new List<int>(rg);
1026 m_evtReady.Set();
1027 }
1028 }
1029
1030 public int Count
1031 {
1032 get
1033 {
1034 lock (m_sync)
1035 {
1036 return m_rgLabels.Count;
1037 }
1038 }
1039 }
1040
1041 public List<int> Get()
1042 {
1043 lock (m_sync)
1044 {
1045 List<int> rg = new List<int>(m_rgLabels);
1046 m_evtReady.Reset();
1047 m_evtDone.Reset();
1048 return rg;
1049 }
1050 }
1051 }
1052
1053
1057 public class LastBatchLoadedArgs : EventArgs
1058 {
1059 List<int> m_rgLabels;
1060
1065 public LastBatchLoadedArgs(List<int> rgLabels)
1066 {
1067 m_rgLabels = new List<int>(rgLabels);
1068 }
1069
1073 public List<int> Labels
1074 {
1075 get { return m_rgLabels; }
1076 }
1077 }
1078}
The BinaryData class is used to pack and unpack DataCriteria binary data, optionally stored within ea...
Definition: BinaryData.cs:15
static List< double > UnPackDoubleList(byte[] rg, DATA_FORMAT fmtExpected)
Unpack the byte array into a list of double values.
Definition: BinaryData.cs:75
static List< float > UnPackFloatList(byte[] rg, DATA_FORMAT fmtExpected)
Unpack the byte array into a list of float values.
Definition: BinaryData.cs:132
The CancelEvent provides an extension to the manual cancel event that allows for overriding the manua...
Definition: CancelEvent.cs:17
bool WaitOne(int nMs=int.MaxValue)
Waits for the signal state to occur.
Definition: CancelEvent.cs:290
The Datum class is a simple wrapper to the SimpleDatum class to ensure compatibility with the origina...
Definition: Datum.cs:12
The ImageData class is a helper class used to convert between Datum, other raw data,...
Definition: ImageData.cs:14
static Bitmap GetImage(SimpleDatum d, ColorMapper clrMap=null, List< int > rgClrOrder=null)
Converts a SimplDatum (or Datum) into an image, optionally using a ColorMapper.
Definition: ImageData.cs:506
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_GT(double df1, double df2, string str)
Test whether one number is greater than another.
Definition: Log.cs:299
The SimpleDatum class holds a data input within host memory.
Definition: SimpleDatum.cs:161
int OriginalLabel
Get/set the original known label of the data.
int Channels
Return the number of channels of the data.
bool IsRealData
Returns whether or not the data contains real numbers or byte data.
byte[] DataCriteria
Get/set data criteria associated with the data.
DATA_FORMAT
Defines the data format of the DebugData and DataCriteria when specified.
Definition: SimpleDatum.cs:223
int Width
Return the width of the data.
int Height
Return the height of the data.
DATA_FORMAT DataCriteriaFormat
Get/set the data format of the data criteria.
int Label
Return the known label of the data.
void SaveInfo(string strFile)
Save the SimpleDatum information to a text file.
The Utility class provides general utility funtions.
Definition: Utility.cs:35
The BlobCollection contains a list of Blobs.
void Reshape(int[] rgShape)
Reshapes all blobs in the collection to the given shape.
The Blob is the main holder of data that moves through the Layers of the Net.
Definition: Blob.cs:25
int channels
DEPRECIATED; legacy shape accessor channels: use shape(1) instead.
Definition: Blob.cs:800
void SetData(T[] rgData, int nCount=-1, bool bSetCount=true)
Sets a number of items within the Blob's data.
Definition: Blob.cs:1922
double min_data
Returns the minimum value in the data of the Blob.
Definition: Blob.cs:2499
double max_data
Returns the maximum value in the data of the Blob.
Definition: Blob.cs:2525
int height
DEPRECIATED; legacy shape accessor height: use shape(2) instead.
Definition: Blob.cs:808
int num_axes
Returns the number of axes in the Blob.
Definition: Blob.cs:705
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
T[] mutable_cpu_data
Get data from the GPU and bring it over to the host, or Set data from the Host and send it over to th...
Definition: Blob.cs:1461
void Reshape(int nNum, int nChannels, int nHeight, int nWidth, bool? bUseHalfSize=null)
DEPRECIATED; use
Definition: Blob.cs:442
void scale_data(double df)
Scale the data by a scaling factor.
Definition: Blob.cs:1754
int width
DEPRECIATED; legacy shape accessor width: use shape(3) instead.
Definition: Blob.cs:816
T[] update_cpu_data()
Update the CPU data by transferring the GPU data over to the Host.
Definition: Blob.cs:1470
int count()
Returns the total number of items in the Blob.
Definition: Blob.cs:739
long gpu_diff
Returns the diff GPU handle used by the CudaDnn connection.
Definition: Blob.cs:1541
virtual void Dispose(bool bDisposing)
Releases all resources used by the Blob (including both GPU and Host).
Definition: Blob.cs:402
int num
DEPRECIATED; legacy shape accessor num: use shape(0) instead.
Definition: Blob.cs:792
long gpu_data
Returns the data GPU handle used by the CudaDnn connection.
Definition: Blob.cs:1479
The CudaDnn object is the main interface to the Low-Level Cuda C++ DLL.
Definition: CudaDnn.cs:969
The Cursor is used to traverse through a given data source within the database.
Definition: DB.cs:63
A generic database class used to connect to the underlying database and create a Cursor that traverse...
Definition: DB.cs:15
Abstract Filler class used to fill blobs with values.
Definition: Filler.cs:19
void Fill(Blob< T > b)
Fill the blob with values based on the actual filler used.
Definition: Filler.cs:50
static Filler< T > Create(CudaDnn< T > cuda, Log log, FillerParameter p)
Create a new Filler instance.
Definition: Filler.cs:79
bool m_bOutputLabels
Specifies whether or not the Layer should output labels.
SourceDescriptor m_src
Specifies the SourceDescriptor of the data source.
IXImageDatabaseBase m_imgdb
Specifies the MyCaffeImageDatabase.
DataTransformer< T > m_transformer
Specifies the DataTransformer used to transform each data item as it loaded.
The BasePrefetchingDataLayer is the base class for data Layers that pre-fetch data before feeding the...
CancelEvent m_evtCancel
Specifies the cancellation event for the internal thread.
void statupPrefetch()
Starts the prefetch thread.
Batch< T >[] m_rgPrefetch
Specifies the pre-fetch cache.
The Batch contains both the data and label Blobs of the batch.
Blob< T > Label
Returns the label Blob of the batch.
Blob< T > Data
Returns the data Blob of the batch.
The DataLayer loads data from the IXImageDatabase database. This layer is initialized with the MyCaff...
Definition: DataLayer.cs:24
override int MaxTopBlobs
Specifies the maximum number of required top (output) Blobs: data, label
Definition: DataLayer.cs:487
void Next()
Retrieves the next item from the database and rolls the cursor over once the end of the dataset is re...
Definition: DataLayer.cs:495
override int ExactNumBottomBlobs
No bottom blobs are used by this layer.
Definition: DataLayer.cs:471
EventHandler< LastBatchLoadedArgs > OnBatchLoad
This event fires (only when set) each time a batch is loaded form this dataset.
Definition: DataLayer.cs:67
override void dispose()
Releases all GPU and host resources used by the Layer.
Definition: DataLayer.cs:140
void Connect(DataLayer< T > src)
The Connect method connects one Data Layer to another so that they can synchronize.
Definition: DataLayer.cs:189
override void final_process(Blob< T > blobTop)
Provides a final processing step that takes place at the end of the base class forward = this is wher...
Definition: DataLayer.cs:526
Stopwatch m_swTimerBatch
Specifies a first timer used to calcualte the batch time.
Definition: DataLayer.cs:37
DB< T > m_db
Specifies the database.
Definition: DataLayer.cs:28
DataLayer(CudaDnn< T > cuda, Log log, LayerParameter p, IXDatabaseBase db, CancelEvent evtCancel)
The DataLayer constructor.
Definition: DataLayer.cs:77
Stopwatch m_swTimerTransaction
Specfies a second timer used to calculate the transaction time.
Definition: DataLayer.cs:41
override int MinTopBlobs
Specifies the minimum number of required top (output) Blobs: data
Definition: DataLayer.cs:479
override bool delayPrefetch
Specifies to delay the prefetch when using a synchronized Data Layer.
Definition: DataLayer.cs:173
double m_dfTransTime
Specifies the transaction time.
Definition: DataLayer.cs:49
double m_dfReadTime
Specifies the read time.
Definition: DataLayer.cs:45
override void load_batch(Batch< T > batch)
Load a batch of data in the background (this is run on an internal thread within the BasePrefetchingD...
Definition: DataLayer.cs:595
override void DataLayerSetUp(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Setup the DataLayer by starting up the pre-fetching.
Definition: DataLayer.cs:220
Cursor< T > m_cursor
Specifies the database used to traverse through the database.
Definition: DataLayer.cs:32
bool Skip()
Skip to the next value - used when training in a multi-GPU scenario.
Definition: DataLayer.cs:512
void Disconnect()
Disconnect any previously connected Data Layers.
Definition: DataLayer.cs:201
override void preStop()
The preStop override is called just before stopping the internal thread managed by the base class.
Definition: DataLayer.cs:131
Specifies the arguments sent to the OnBatchLoad event used when synchronizing between Data Layers.
Definition: DataLayer.cs:1058
List< int > Labels
Returns the labels loaded.
Definition: DataLayer.cs:1074
LastBatchLoadedArgs(List< int > rgLabels)
The constructor.
Definition: DataLayer.cs:1065
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 convert(BlobCollection< T > col)
Convert a collection of blobs from / to half size.
Definition: Layer.cs:535
T m_tZero
Specifies a generic type equal to 0.0.
Definition: Layer.cs:76
T m_tOne
Specifies a generic type equal to 1.0.
Definition: Layer.cs:72
float convertF(T df)
Converts a generic to a float value.
Definition: Layer.cs:1359
double convertD(T df)
Converts a generic to a double value.
Definition: Layer.cs:1349
CudaDnn< T > m_cuda
Specifies the CudaDnn connection to Cuda.
Definition: Layer.cs:39
LayerParameter.LayerType m_type
Specifies the Layer type.
Definition: Layer.cs:35
The DataDebugParameter is used by the DataParameter when the 'enable_debugging' = True.
string debug_save_path
(/b optional, default = null) Specifies the path where the debug data images are saved,...
int iterations
(/b optional, default = 1) Specifies the number of iterations to output debug information.
string noisy_save_path
(/b optional, default = null) Specifies the path where the noisy data image is saved,...
bool use_noisy_mean
(optional, default = true) When true the noise is applied to the mean and used as the noisy data....
int noise_data_label
(optional, default = -1) Specifies the label used with each noise filled data used when 'use_noise_fo...
FillerParameter noise_filler
Specifies the noise filler used when 'use_noise_for_nonmatch' = true. By default the 'noise_filter' i...
Specifies the parameter for the data layer.
virtual uint batch_size
Specifies the batch size.
LABEL_TYPE label_type
(optional, default = SINGLE) Specifies the label type: SINGLE - the default which uses the 'Label' fi...
bool synchronize_target
(optional, default = false) Specifies whether or not this is a to be synchronized with another data l...
bool display_timing
(optional, default = false) Specifies whether or not to display the timing of each image read.
bool? enable_random_selection
(optional, default = null) Specifies whether or not to randomly query images from the data source....
int images_per_blob
(optional, default = 1) Specifies the number of images to load into each blob channel....
string synchronize_with
(optional, default = null) Specifies a secondary (target) dataset to syncrhonize with.
DataNoiseParameter data_noise_param
Specifies the DataNoiseParameter used when 'enable_noise_for_nonmatch' = True.
bool enable_noise_for_nonmatch
(optional, default = false) When true an image consisting of noise initialized with noise filler.
int one_hot_label_size
When greater than 0 (default = 0), labels are one-hot encoded to a vector of the one-hot label size (...
bool? enable_pair_selection
(optional, default = null) Specifies whether or not to select images in a pair sequence....
int forced_primary_label
(optional, default = -1) When >= 0, this label is used as the primary image label when 'images_per_bl...
DataDebugParameter data_debug_param
Specifies the DataDebugParameter used when 'enable_debug_output' = True.
string source
When used with the DATA parameter, specifies the data 'source' within the database....
bool output_all_labels
(optional, default = false) When using images_per_blob > 1, 'output_all_labels' specifies to output a...
bool enable_debug_output
(optional, default = false) When true the data sent out through the top are saved as images into the ...
bool output_image_information
(optional, default = false) When true image information such as index and label are output....
bool balance_matches
(optional, default = true) When using images_per_blob > 1, 'balance_matches' specifies to query image...
LABEL_TYPE
Defines the label type.
Specifies the base parameter for all layers.
string name
Specifies the name of this LayerParameter.
int solver_count
Returns the number of Solvers participating in a multi-GPU session for which the Solver using this La...
int solver_rank
Returns the SolverRank of the Solver using this LayerParameter (if any).
TransformationParameter transform_param
Returns the parameter set when initialized with LayerType.TRANSFORM
DataParameter data_param
Returns the parameter set when initialized with LayerType.DATA
Phase phase
Specifies the Phase for which this LayerParameter is run.
LayerType
Specifies the layer type.
bool Active
When active, the parameter is used, otherwise it is ignored.
DataLabelMappingParameter label_mapping
Optionally, specifies the label mapping which defines how to map lables when calling the DataTransfor...
MaskParameter mask_param
Optionally, specifies the image mask which defines the boundary area that is set to black on the imag...
double scale
For data pre-processing, we can do simple scaling and subtracting the data mean, if provided....
The IXDatabaseBase interface defines the general interface to the in-memory database.
Definition: Interfaces.cs:444
SimpleDatum GetItemMean(int nSrcId)
Returns the item (e.g., image or temporal item) mean for a data source.
Tuple< DB_LABEL_SELECTION_METHOD, DB_ITEM_SELECTION_METHOD > GetSelectionMethod()
Returns the label and image selection method used.
void SetSelectionMethod(DB_LABEL_SELECTION_METHOD? lbl, DB_ITEM_SELECTION_METHOD? img)
Sets the label and image selection methods.
DB_VERSION GetVersion()
Returns the version of the MyCaffe Image Database being used.
The IXImageDatabaseBase interface defines the general interface to the in-memory image database.
Definition: Interfaces.cs:878
The MyCaffe.basecode contains all generic types used throughout MyCaffe.
Definition: Annotation.cs:12
DB_ITEM_SELECTION_METHOD
Defines the item (e.g., image or temporal item) selection method.
Definition: Interfaces.cs:278
Phase
Defines the Phase under which to run a Net.
Definition: Interfaces.cs:61
DB_VERSION
Defines the image database version to use.
Definition: Interfaces.cs:397
The MyCaffe.common namespace contains common MyCaffe classes.
Definition: BatchInput.cs:8
The MyCaffe.data namespace contains dataset creators used to create common testing datasets such as M...
Definition: BinaryFile.cs:16
The MyCaffe.db.image namespace contains all image database related classes.
Definition: Database.cs:18
The MyCaffe.fillers namespace contains all fillers including the Filler class.
The MyCaffe.layers namespace contains all layers that have a solidified code base,...
Definition: LayerFactory.cs:15
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