MyCaffe  1.12.2.41
Deep learning software for Windows C# programmers.
FilterLayer.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{
18 public class FilterLayer<T> : Layer<T>
19 {
20 bool m_bFirstShape;
21 List<int> m_rgIndicesToForward = new List<int>();
22
31 : base(cuda, log, p)
32 {
34 }
35
39 public override int MinBottomBlobs
40 {
41 get { return 2; }
42 }
43
47 public override int MinTopBlobs
48 {
49 get { return 1; }
50 }
51
57 public override void LayerSetUp(BlobCollection<T> colBottom, BlobCollection<T> colTop)
58 {
59 m_log.CHECK_EQ(colTop.Count, colBottom.Count - 1, "The top size must be equal to the bottom size - 1.");
60 m_bFirstShape = true;
61 }
62
68 public override void Reshape(BlobCollection<T> colBottom, BlobCollection<T> colTop)
69 {
70 // bottom[0...k-1] are the blobs to filter
71 // bottom[last] is the 'selector_blob'
72 int nSelectorIdx = colBottom.Count - 1;
73 for (int i = 1; i < colBottom[nSelectorIdx].num_axes; i++)
74 {
75 m_log.CHECK_EQ(colBottom[nSelectorIdx].shape(i), 1, "Selector blob dimensions must be singletons (1), except the first");
76 }
77
78 for (int i = 0; i < colBottom.Count - 1; i++)
79 {
80 m_log.CHECK_EQ(colBottom[nSelectorIdx].shape(0), colBottom[i].shape(0), "Each bottom should have the same 0th dimension as the selector blob.");
81 }
82
83 T[] rgBottomDataSelector = colBottom[nSelectorIdx].update_cpu_data();
84 m_rgIndicesToForward = new List<int>();
85
86 // look for non-zero elements in bottom[0]. Items of each bottom that
87 // have the same index as the items in bottom[0] with value == non-zero
88 // will be forwarded.
89 if (typeof(T) == typeof(double))
90 {
91 double[] rgBottomDataSelectorD = (double[])Convert.ChangeType(rgBottomDataSelector, typeof(double[]));
92
93 for (int i = 0; i < colBottom[nSelectorIdx].shape(0); i++)
94 {
95 if (rgBottomDataSelectorD[i] != 0.0)
96 m_rgIndicesToForward.Add(i);
97 }
98 }
99 else
100 {
101 float[] rgBottomDataSelectorF = (float[])Convert.ChangeType(rgBottomDataSelector, typeof(float[]));
102
103 for (int i = 0; i < colBottom[nSelectorIdx].shape(0); i++)
104 {
105 if (rgBottomDataSelectorF[i] != 0.0)
106 m_rgIndicesToForward.Add(i);
107 }
108 }
109
110 // only filtered items will be forwarded
111 int nNewTopsNum = m_rgIndicesToForward.Count;
112
113 // init
114 if (m_bFirstShape)
115 {
116 nNewTopsNum = colBottom[0].shape(0);
117 m_bFirstShape = false;
118 }
119
120 for (int t = 0; t < colTop.Count; t++)
121 {
122 int nNumAxes = colBottom[t].num_axes;
123 List<int> rgShape = new List<int>();
124 rgShape.Add(nNewTopsNum);
125
126 for (int ts = 1; ts < nNumAxes; ts++)
127 {
128 rgShape.Add(colBottom[t].shape(ts));
129 }
130
131 colTop[t].Reshape(rgShape);
132 }
133 }
134
154 protected override void forward(BlobCollection<T> colBottom, BlobCollection<T> colTop)
155 {
156 int nNewTopsNum = m_rgIndicesToForward.Count;
157
158 // forward all filtered items for all bottoms but the Selector (bottom[last])
159 for (int t = 0; t < colTop.Count; t++)
160 {
161 long hBottomData = colBottom[t].gpu_data;
162 long hTopData = colTop[t].mutable_gpu_data;
163 int nDim = colBottom[t].count() / colBottom[t].shape(0);
164
165 for (int n = 0; n < nNewTopsNum; n++)
166 {
167 int nDataOffsetTop = n * nDim;
168 int nDataOffsetBottom = m_rgIndicesToForward[n] * nDim;
169 m_cuda.copy(nDim, hBottomData, hTopData, nDataOffsetBottom, nDataOffsetTop);
170 }
171 }
172 }
173
182 protected override void backward(BlobCollection<T> colTop, List<bool> rgbPropagateDown, BlobCollection<T> colBottom)
183 {
184 if (rgbPropagateDown[colBottom.Count - 1])
185 m_log.FAIL("Layer cannot backpropagate to filter index inputs.");
186
187 for (int i = 0; i < colTop.Count; i++)
188 {
189 // bottom[last] is the selector and never needs backpropagation
190 // so we can iterate over top vecotr because top.size() == bottom.size() - 1
191
192 if (rgbPropagateDown[i])
193 {
194 int nDim = colTop[i].count() / colTop[i].shape(0);
195 int nNextToBackwardOffset = 0;
196 int nBatchOffset = 0;
197 int nDataOffsetBottom = 0;
198 int nDataOffsetTop = 0;
199
200 for (int n = 0; n < colBottom[i].shape(0); n++)
201 {
202 if (nNextToBackwardOffset >= m_rgIndicesToForward.Count)
203 {
204 // we already visited all items that have been forwarded, so
205 // just set to zero remaining ones.
206 nDataOffsetBottom = n * nDim;
207 m_cuda.set(nDim, colBottom[i].mutable_gpu_diff, m_tZero, -1, nDataOffsetBottom);
208 }
209 else
210 {
211 nBatchOffset = m_rgIndicesToForward[nNextToBackwardOffset];
212 nDataOffsetBottom = n * nDim;
213
214 if (n != nBatchOffset) // this data has not been forwarded
215 {
216 m_cuda.set(nDim, colBottom[i].mutable_gpu_diff, m_tZero, -1, nDataOffsetBottom);
217 }
218 else // this data has been forwarded
219 {
220 nDataOffsetTop = nNextToBackwardOffset * nDim;
221 nNextToBackwardOffset++; // point to next forwarded item index
222 m_cuda.copy(nDim, colTop[i].mutable_gpu_diff, colBottom[i].mutable_gpu_diff, nDataOffsetTop, nDataOffsetBottom);
223 }
224 }
225 }
226 }
227 }
228 }
229 }
230}
The Log class provides general output in text form.
Definition: Log.cs:13
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
The BlobCollection contains a list of Blobs.
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 CudaDnn object is the main interface to the Low-Level Cuda C++ DLL.
Definition: CudaDnn.cs:969
The FilterLayer takes two+ Blobs, interprets last Blob as a selector and filters remaining Blobs acco...
Definition: FilterLayer.cs:19
override void forward(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Forward computation.
Definition: FilterLayer.cs:154
override int MinBottomBlobs
Returns the minimum number of required bottom (intput) Blobs: input, selector
Definition: FilterLayer.cs:40
override void Reshape(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Reshape the bottom (input) and top (output) blobs.
Definition: FilterLayer.cs:68
override void LayerSetUp(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Setup the layer.
Definition: FilterLayer.cs:57
override void backward(BlobCollection< T > colTop, List< bool > rgbPropagateDown, BlobCollection< T > colBottom)
Computes the error gradient w.r.t. the forwarded inputs.
Definition: FilterLayer.cs:182
FilterLayer(CudaDnn< T > cuda, Log log, LayerParameter p)
The FilterLayer constructor.
Definition: FilterLayer.cs:30
override int MinTopBlobs
Returns the minimum number of required top (output) Blobs: filter
Definition: FilterLayer.cs:48
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
T m_tZero
Specifies a generic type equal to 0.0.
Definition: Layer.cs:76
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.
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