MyCaffe  1.12.2.41
Deep learning software for Windows C# programmers.
BatchReindexLayer.cs
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using MyCaffe.basecode;
6using MyCaffe.common;
7using MyCaffe.param;
8
9namespace MyCaffe.layers
10{
20 public class BatchReindexLayer<T> : Layer<T>
21 {
22 Blob<T> m_blobCounts;
23 Blob<T> m_blobBegins;
24 Blob<T> m_blobTopIndexes;
25
34 : base(cuda, log, p)
35 {
36 m_type = LayerParameter.LayerType.BATCHREINDEX;
37 m_blobCounts = new common.Blob<T>(cuda, log);
38 m_blobCounts.Name = m_param.name + "counts";
39 m_blobBegins = new common.Blob<T>(cuda, log);
40 m_blobBegins.Name = m_param.name + "begins";
41 m_blobTopIndexes = new common.Blob<T>(cuda, log);
42 m_blobTopIndexes.Name = m_param.name + "topidx";
43 }
44
46 protected override void dispose()
47 {
48 if (m_blobCounts != null)
49 {
50 m_blobCounts.Dispose();
51 m_blobCounts = null;
52 }
53
54 if (m_blobBegins != null)
55 {
56 m_blobBegins.Dispose();
57 m_blobBegins = null;
58 }
59
60 if (m_blobTopIndexes != null)
61 {
62 m_blobTopIndexes.Dispose();
63 m_blobTopIndexes = null;
64 }
65
66 base.dispose();
67 }
68
70 protected override void setup_internal_blobs(BlobCollection<T> col)
71 {
72 if (col.Count > 0)
73 return;
74
75 col.Add(m_blobCounts);
76 col.Add(m_blobBegins);
77 col.Add(m_blobTopIndexes);
78 }
79
83 public override int ExactNumBottomBlobs
84 {
85 get { return 2; }
86 }
87
91 public override int ExactNumTopBlobs
92 {
93 get { return 1; }
94 }
95
101 public override void LayerSetUp(BlobCollection<T> colBottom, BlobCollection<T> colTop)
102 {
103 }
104
110 public override void Reshape(BlobCollection<T> colBottom, BlobCollection<T> colTop)
111 {
112 m_log.CHECK_EQ(1, colBottom[1].num_axes, "The bottom[1] should have num_axes = 1.");
113 List<int> rgNewShape = new List<int>();
114 rgNewShape.Add(colBottom[1].shape(0));
115
116 for (int i = 1; i < colBottom[0].shape().Count; i++)
117 {
118 rgNewShape.Add(colBottom[0].shape(i));
119 }
120
121 colTop[0].Reshape(rgNewShape);
122
123 List<int> rgShape = new List<int>();
124 rgShape.Add(colBottom[1].count());
125 m_blobTopIndexes.Reshape(rgShape);
126
127 rgShape[0] = colBottom[0].shape(0);
128 m_blobCounts.Reshape(rgShape);
129 m_blobBegins.Reshape(rgShape);
130 }
131
132 private void check_batch_reindex(int nInitialNum, int nFinalNum, Blob<T> b)
133 {
134 T[] rgData = b.update_cpu_data();
135
136 if (typeof(T) == typeof(double))
137 {
138 double[] rgidx_Data = (double[])Convert.ChangeType(rgData, typeof(double[]));
139 for (int i = 0; i < nFinalNum; i++)
140 {
141 m_log.CHECK_GE(rgidx_Data[i], 0, "Index specified for reindex layer was negative.");
142 m_log.CHECK_LT(rgidx_Data[i], nInitialNum, "Index specified for reindex layer was greater than batch size.");
143 }
144 }
145 else
146 {
147 float[] rgidx_Data = (float[])Convert.ChangeType(rgData, typeof(float[]));
148 for (int i = 0; i < nFinalNum; i++)
149 {
150 m_log.CHECK_GE(rgidx_Data[i], 0, "Index specified for reindex layer was negative.");
151 m_log.CHECK_LT(rgidx_Data[i], nInitialNum, "Index specified for reindex layer was greater than batch size.");
152 }
153 }
154 }
155
171 protected override void forward(BlobCollection<T> colBottom, BlobCollection<T> colTop)
172 {
173 check_batch_reindex(colBottom[0].shape(0), colBottom[1].count(), colBottom[1]);
174
175 int nCount = colTop[0].count();
176 if (nCount == 0)
177 return;
178
179 m_cuda.batchreidx_fwd(nCount, colBottom[0].count() / colBottom[0].shape(0), colBottom[0].gpu_data, colBottom[1].gpu_data, colTop[0].mutable_gpu_data);
180 }
181
196 protected override void backward(BlobCollection<T> colTop, List<bool> rgbPropagateDown, BlobCollection<T> colBottom)
197 {
198 m_log.CHECK(!rgbPropagateDown[1], "Cannot backprop to index.");
199
200 if (!rgbPropagateDown[0])
201 return;
202
203 List<KeyValuePair<int, int>> rgMapping = new List<KeyValuePair<int, int>>();
204 T[] rgData = colBottom[1].update_cpu_data();
205
206 if (typeof(T) == typeof(double))
207 {
208 double[] rgPerm = (double[])Convert.ChangeType(rgData, typeof(double[]));
209 for (int i = 0; i < colBottom[1].count(); i++)
210 {
211 rgMapping.Add(new KeyValuePair<int, int>((int)rgPerm[i], i));
212 }
213 }
214 else
215 {
216 float[] rgPerm = (float[])Convert.ChangeType(rgData, typeof(float[]));
217 for (int i = 0; i < colBottom[1].count(); i++)
218 {
219 rgMapping.Add(new KeyValuePair<int, int>((int)rgPerm[i], i));
220 }
221 }
222
223 rgMapping.Sort(new Comparison<KeyValuePair<int, int>>(sort));
224
225 // Each element of the bottom diff is potentially the sum of many top diffs.
226 // However, we'd like each CUDA thread to handle exactly one output. Hence,
227 // we first pre-compute a list of lists of indices that need to be summed for
228 // each output. 'top_indexes' holds the data of this list of lists. The
229 // k'th element of 'begins' points to the location in 'top_indexes' where the
230 // list for the k'th example begin, and the kth element of 'counts' is the
231 // length of that list.
232
233 m_blobBegins.SetData(-1);
234 m_blobCounts.SetData(0);
235
236 T[] rgTopIndexes = m_blobTopIndexes.mutable_cpu_data;
237 T[] rgCounts = m_blobCounts.mutable_cpu_data;
238 T[] rgBegins = m_blobBegins.mutable_cpu_data;
239
240 if (typeof(T) == typeof(double))
241 {
242 double[] t_i_data = (double[])Convert.ChangeType(rgTopIndexes, typeof(double[]));
243 double[] c_data = (double[])Convert.ChangeType(rgCounts, typeof(double[]));
244 double[] b_data = (double[])Convert.ChangeType(rgBegins, typeof(double[]));
245
246 for (int i = 0; i < rgMapping.Count; i++)
247 {
248 t_i_data[i] = rgMapping[i].Value;
249
250 if (b_data[rgMapping[i].Key] == -1)
251 b_data[rgMapping[i].Key] = i;
252
253 c_data[rgMapping[i].Key] += 1;
254 }
255 }
256 else
257 {
258 float[] t_i_data = (float[])Convert.ChangeType(rgTopIndexes, typeof(float[]));
259 float[] c_data = (float[])Convert.ChangeType(rgCounts, typeof(float[]));
260 float[] b_data = (float[])Convert.ChangeType(rgBegins, typeof(float[]));
261
262 for (int i = 0; i < rgMapping.Count; i++)
263 {
264 t_i_data[i] = rgMapping[i].Value;
265
266 if (b_data[rgMapping[i].Key] == -1)
267 b_data[rgMapping[i].Key] = i;
268
269 c_data[rgMapping[i].Key] += 1;
270 }
271 }
272
273 m_blobTopIndexes.mutable_cpu_data = rgTopIndexes;
274 m_blobCounts.mutable_cpu_data = rgCounts;
275 m_blobBegins.mutable_cpu_data = rgBegins;
276
277 int nCount = colBottom[0].count();
278
279 m_cuda.batchreidx_bwd(nCount, colBottom[0].count() / colBottom[0].shape(0), colTop[0].gpu_diff, m_blobTopIndexes.gpu_data, m_blobBegins.gpu_data, m_blobCounts.gpu_data, colBottom[0].mutable_gpu_diff);
280 }
281
282 private int sort(KeyValuePair<int, int> a, KeyValuePair<int, int> b)
283 {
284 if (a.Key < b.Key)
285 return -1;
286
287 if (a.Key > b.Key)
288 return 1;
289
290 return 0;
291 }
292 }
293}
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 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 BlobCollection contains a list of Blobs.
void Add(Blob< T > b)
Add a new Blob to the collection.
int Count
Returns the number of items in the collection.
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
void SetData(T[] rgData, int nCount=-1, bool bSetCount=true)
Sets a number of items within the Blob's data.
Definition: Blob.cs:1922
Blob(CudaDnn< T > cuda, Log log, bool bIncludeDiff=true, bool bUseHalfSize=false)
The Blob constructor.
Definition: Blob.cs:64
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
T[] update_cpu_data()
Update the CPU data by transferring the GPU data over to the Host.
Definition: Blob.cs:1470
string Name
Get/set the name of the Blob.
Definition: Blob.cs:2184
virtual void Dispose(bool bDisposing)
Releases all resources used by the Blob (including both GPU and Host).
Definition: Blob.cs:402
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 BatchReindexLayer provides an index into the input blob along its first axis.
override void backward(BlobCollection< T > colTop, List< bool > rgbPropagateDown, BlobCollection< T > colBottom)
Computes the error gradient w.r.t. the reordered input.
override int ExactNumBottomBlobs
Returns the exact number of bottom (input) Blobs required: input, axis
override void setup_internal_blobs(BlobCollection< T > col)
Derivative layers should add all internal blobws to the 'col' provided.
BatchReindexLayer(CudaDnn< T > cuda, Log log, LayerParameter p)
The BatchReindexLayer constructor.
override void dispose()
Releases all GPU and host resources used by the Layer.
override void LayerSetUp(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Setup the layer.
override void Reshape(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Reshape the bottom (input) and top (output) blobs.
override int ExactNumTopBlobs
Returns the exact number of top (output) Blobs required: batchreidx
override void forward(BlobCollection< T > colBottom, BlobCollection< T > colTop)
The Forward computation.
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
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
Specifies the base parameter for all layers.
string name
Specifies the name of this LayerParameter.
LayerType
Specifies the layer type.
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
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