MyCaffe  1.12.2.41
Deep learning software for Windows C# programmers.
DataNormalizerLayer.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{
15 public class DataNormalizerLayer<T> : Layer<T>
16 {
17 BlobCollection<T> m_colWork1;
18 BlobCollection<T> m_colWork2;
19
61 : base(cuda, log, p)
62 {
63 m_type = LayerParameter.LayerType.DATA_NORMALIZER;
64 m_colWork1 = new BlobCollection<T>();
65 m_colWork2 = new BlobCollection<T>();
66 }
67
71 protected override void dispose()
72 {
73 if (m_colWork1 != null)
74 {
75 m_colWork1.Dispose();
76 m_colWork1 = null;
77 }
78
79 if (m_colWork2 != null)
80 {
81 m_colWork2.Dispose();
82 m_colWork2 = null;
83 }
84
85 base.dispose();
86 }
87
91 public override int MinBottomBlobs
92 {
93 get { return 1; }
94 }
95
99 public override int MaxBottomBlobs
100 {
101 get { return 2; }
102 }
103
107 public override int MinTopBlobs
108 {
109 get { return 1; }
110 }
111
115 public override int MaxTopBlobs
116 {
117 get { return 2; }
118 }
119
125 public override void LayerSetUp(BlobCollection<T> colBottom, BlobCollection<T> colTop)
126 {
128
129 if (p.steps.Count == 0)
130 m_log.WriteLine("WARNING: No normalization steps are specified, data will just pass through in its normal form.");
131
133 {
134 double dfRange = p.output_max - p.output_min;
135 m_log.CHECK_GT(dfRange, 0, "The output data range must be greater than 0!");
136 }
137
139 {
140 if (p.input_stdev.HasValue)
141 m_log.CHECK_NE(p.input_stdev.Value, 0, "The standard deviation cannot be zero!");
142 }
143
144 for (int i = 0; i < colBottom.Count; i++)
145 {
146 m_colWork1.Add(new Blob<T>(m_cuda, m_log, colBottom[i]));
147 m_colWork2.Add(new Blob<T>(m_cuda, m_log, colBottom[i]));
148 }
149 }
150
156 public override void Reshape(BlobCollection<T> colBottom, BlobCollection<T> colTop)
157 {
158 m_log.CHECK_EQ(colBottom.Count, colTop.Count, "The top and bottom must have the same number of blobs.");
159
160 for (int i = 0; i < colBottom.Count; i++)
161 {
162 colTop[i].ReshapeLike(colBottom[i]);
163 m_colWork1[i].ReshapeLike(colBottom[i]);
164 m_colWork2[i].ReshapeLike(colBottom[i]);
165 }
166 }
167
183 protected override void forward(BlobCollection<T> colBottom, BlobCollection<T> colTop)
184 {
185 for (int i = 0; i < colBottom.Count; i++)
186 {
187 m_colWork1[i].CopyFrom(colBottom[i]);
188 m_colWork2[i].CopyFrom(colBottom[i]);
189 }
190
192 {
193 switch (step)
194 {
196 run_step_log(m_colWork1);
197 break;
198
200 run_step_center(m_colWork1, m_colWork2);
201 break;
202
204 run_step_stdev(m_colWork1, m_colWork2);
205 break;
206 }
207 }
208
209 for (int i = 0; i < colTop.Count; i++)
210 {
211 colTop[i].CopyFrom(m_colWork1[i]);
212 }
213 }
214
215 private void run_step_log(BlobCollection<T> col)
216 {
217 foreach (Blob<T> b in col)
218 {
219 m_cuda.log(b.count(), b.gpu_data, b.mutable_gpu_data);
220 }
221 }
222
223 private void run_step_center(BlobCollection<T> col1, BlobCollection<T> col2)
224 {
226 {
227 double dfMean = m_param.data_normalizer_param.input_mean.GetValueOrDefault(0);
228
229 if (dfMean != 0)
230 {
231 for (int i = 0; i < col1.Count; i++)
232 {
233 col1[i].add_scalar(-dfMean);
234 }
235 }
236 }
237 else
238 {
239 for (int i = 0; i < col1.Count; i++)
240 {
241 Blob<T> b1 = col1[i];
242 Blob<T> b2 = col2[i];
243 int nNum = b1.num;
244 int nSpatialCount = b1.count(2);
245
246 if (nSpatialCount > 1)
247 {
248 m_cuda.channel_max(b1.count(), b1.num, b1.channels, nSpatialCount, b1.gpu_data, b1.mutable_gpu_diff); // b1 = max
249 m_cuda.channel_min(b1.count(), b1.num, b1.channels, nSpatialCount, b1.gpu_data, b2.mutable_gpu_diff); // b2 = min
250 m_cuda.channel_sub(b1.count(), b1.num, b1.channels, nSpatialCount, b2.gpu_diff, b1.mutable_gpu_diff); // b1 = b1 - b2
251 m_cuda.mul_scalar(b1.count(), 1.0 / (double)nSpatialCount, b1.mutable_gpu_diff); // channel mean.
252 m_cuda.channel_sub(b1.count(), b1.num, b1.channels, nSpatialCount, b1.gpu_diff, b1.mutable_gpu_data); // centered by channel
253 }
254 }
255 }
256 }
257
258 private void run_step_stdev(BlobCollection<T> col1, BlobCollection<T> col2)
259 {
261 {
262 double dfStdev = m_param.data_normalizer_param.input_stdev.GetValueOrDefault(0);
263
264 if (dfStdev != 0 && dfStdev != 1)
265 {
266 for (int i = 0; i < col1.Count; i++)
267 {
268 m_cuda.mul_scalar(col1[i].count(), 1.0 / dfStdev, col1[i].mutable_gpu_data);
269 }
270 }
271 }
272 else
273 {
274 for (int i = 0; i < col1.Count; i++)
275 {
276 Blob<T> b1 = col1[i];
277 Blob<T> b2 = col2[i];
278 int nNum = b1.num;
279 int nSpatialCount = b1.count(2);
280
281 if (nSpatialCount > 1)
282 {
283 m_cuda.channel_max(b1.count(), b1.num, b1.channels, nSpatialCount, b1.gpu_data, b1.mutable_gpu_diff); // b1 = max
284 m_cuda.channel_min(b1.count(), b1.num, b1.channels, nSpatialCount, b1.gpu_data, b2.mutable_gpu_diff); // b2 = min
285 m_cuda.channel_sub(b1.count(), b1.num, b1.channels, nSpatialCount, b2.gpu_diff, b1.mutable_gpu_diff); // b1 = b1 - b2
286 m_cuda.mul_scalar(b1.count(), 1.0 / (double)nSpatialCount, b1.mutable_gpu_diff); // xbar = channel mean.
287 m_cuda.channel_sub(b1.count(), b1.num, b1.channels, nSpatialCount, b1.gpu_diff, b2.mutable_gpu_data); // x - xbar
288 m_cuda.channel_mul(b1.count(), b1.num, b1.channels, nSpatialCount, b2.gpu_data, b2.mutable_gpu_data); // (x - xbar)^2
289 m_cuda.channel_sum(b1.count(), b1.num, b1.channels, nSpatialCount, b2.gpu_data, b2.mutable_gpu_diff); // Sum(x - xbar)^2
290 m_cuda.mul_scalar(b1.count(), 1.0 / (double)nSpatialCount, b2.mutable_gpu_diff);
291 m_cuda.sqrt(b1.count(), b2.gpu_diff, b2.mutable_gpu_data); // Std-dev.
292
293 m_cuda.channel_div(b1.count(), b1.num, b1.channels, nSpatialCount, b2.gpu_data, b1.mutable_gpu_data);
294 }
295 }
296 }
297 }
298
300 protected override void backward(BlobCollection<T> colTop, List<bool> rgbPropagateDown, BlobCollection<T> colBottom)
301 {
302 new NotImplementedException();
303 }
304 }
305}
The Log class provides general output in text form.
Definition: Log.cs:13
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 CHECK_EQ(double df1, double df2, string str)
Test whether one number is equal to another.
Definition: Log.cs:239
void CHECK_NE(double df1, double df2, string str)
Test whether one number is not-equal to another.
Definition: Log.cs:251
void CHECK_GT(double df1, double df2, string str)
Test whether one number is greater than another.
Definition: Log.cs:299
The BlobCollection contains a list of Blobs.
void Dispose()
Release all resource used by the collection and its Blobs.
void Add(Blob< T > b)
Add a new Blob to the collection.
int Count
Returns the number of items in the collection.
void ReshapeLike(BlobCollection< T > src)
Reshapes all blobs in the collection to the sizes of the source.
void CopyFrom(BlobCollection< T > bSrc, bool bCopyDiff=false)
Copy the data or diff from another BlobCollection into this one.
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
long mutable_gpu_diff
Returns the diff GPU handle used by the CudaDnn connection.
Definition: Blob.cs:1555
long mutable_gpu_data
Returns the data GPU handle used by the CudaDnn connection.
Definition: Blob.cs:1487
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
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 DataNormalizerLayer normalizes the input data (and optionally label) based on the normalization o...
override int MaxBottomBlobs
Returns the maximum number of bottom blobs required: data, label
override void forward(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Forward computation.
override void dispose()
Clean up any resources used.
DataNormalizerLayer(CudaDnn< T > cuda, Log log, LayerParameter p)
Constructor.
override int MaxTopBlobs
Returns the maximum number of top blobs required: data, label
override int MinBottomBlobs
Returns the minimum number of bottom blobs required: data
override int MinTopBlobs
Returns the minimum number of top blobs required: data
override void backward(BlobCollection< T > colTop, List< bool > rgbPropagateDown, BlobCollection< T > colBottom)
Not implemented.
override void Reshape(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Reshape the bottom (input) and top (output) blobs.
override void LayerSetUp(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Setup the layer.
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 parameter for the data normalizer layer.
double output_max
Specifies the maximum data range of the output.
double output_min
Specifies the minimum data range of the output.
List< NORMALIZATION_STEP > steps
Specifies the normalization steps which are performed in the order for which they are listed.
NORMALIZATION_STEP
Specifies the normalization step to run.
double? input_mean
Specifies the input mean, if known. When not specified the input_mean is determined dynamically from ...
double? input_stdev
Specifies the input standard deviation, if known. When not specified input_stdev is determined dynami...
Specifies the base parameter for all layers.
DataNormalizerParameter data_normalizer_param
Returns the parameter set when initialized with LayerType.DATA_NORMALIZER
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