MyCaffe  1.12.2.41
Deep learning software for Windows C# programmers.
MVNLayer.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{
21 public class MVNLayer<T> : Layer<T>
22 {
23 Blob<T> m_blobMean;
24 Blob<T> m_blobVariance;
25 Blob<T> m_blobTemp;
26 // Sum_multiplier is used to carry out sum using BLAS
27 Blob<T> m_blobSumMultiplier;
28 double m_dfEps;
29
43 : base(cuda, log, p)
44 {
46 m_blobMean = new common.Blob<T>(cuda, log);
47 m_blobMean.Name = m_param.name + " mean";
48 m_blobVariance = new common.Blob<T>(cuda, log);
49 m_blobVariance.Name = m_param.name + " variance";
50 m_blobTemp = new Blob<T>(cuda, log);
51 m_blobTemp.Name = m_param.name + " temp";
52 m_blobSumMultiplier = new Blob<T>(cuda, log);
53 m_blobSumMultiplier.Name = m_param.name + " summult";
54 }
55
57 protected override void dispose()
58 {
59 if (m_blobMean != null)
60 {
61 m_blobMean.Dispose();
62 m_blobMean = null;
63 }
64
65 if (m_blobVariance != null)
66 {
67 m_blobVariance.Dispose();
68 m_blobVariance = null;
69 }
70
71 if (m_blobTemp != null)
72 {
73 m_blobTemp.Dispose();
74 m_blobTemp = null;
75 }
76
77 if (m_blobSumMultiplier != null)
78 {
79 m_blobSumMultiplier.Dispose();
80 m_blobSumMultiplier = null;
81 }
82
83 base.dispose();
84 }
85
87 protected override void setup_internal_blobs(BlobCollection<T> col)
88 {
89 if (col.Count > 0)
90 return;
91
92 col.Add(m_blobMean);
93 col.Add(m_blobVariance);
94 col.Add(m_blobTemp);
95 col.Add(m_blobSumMultiplier);
96 }
97
101 public override int ExactNumBottomBlobs
102 {
103 get { return 1; }
104 }
105
109 public override int ExactNumTopBlobs
110 {
111 get { return 1; }
112 }
113
119 public override void LayerSetUp(BlobCollection<T> colBottom, BlobCollection<T> colTop)
120 {
121 }
122
128 public override void Reshape(BlobCollection<T> colBottom, BlobCollection<T> colTop)
129 {
130 colTop[0].ReshapeLike(colBottom[0]);
131
132 m_blobMean.Reshape(colBottom[0].num, colBottom[0].channels, 1, 1);
133 m_blobVariance.Reshape(colBottom[0].num, colBottom[0].channels, 1, 1);
134 m_blobTemp.Reshape(colBottom[0].num, colBottom[0].channels, colBottom[0].height, colBottom[0].width);
135
137 m_blobSumMultiplier.Reshape(1, colBottom[0].channels, colBottom[0].height, colBottom[0].width);
138 else
139 m_blobSumMultiplier.Reshape(1, 1, colBottom[0].height, colBottom[0].width);
140
141 m_blobSumMultiplier.SetData(1.0);
142 m_dfEps = m_param.mvn_param.eps;
143 }
144
156 protected override void forward(BlobCollection<T> colBottom, BlobCollection<T> colTop)
157 {
158 long hBottomData = colBottom[0].gpu_data;
159 long hTopData = colTop[0].mutable_gpu_data;
160 int nNum = colBottom[0].num;
161
163 nNum *= colBottom[0].channels;
164
165 int nDim = colBottom[0].count() / nNum;
166
167 // subtract mean
168 m_cuda.gemv(false, nNum, nDim, 1.0 / nDim, hBottomData, m_blobSumMultiplier.gpu_data, 0.0, m_blobMean.mutable_gpu_data); //EX
169 m_cuda.gemm(false, false, nNum, nDim, 1, -1.0, m_blobMean.gpu_data, m_blobSumMultiplier.gpu_data, 0.0, m_blobTemp.mutable_gpu_data);
170 m_cuda.add(m_blobTemp.count(), hBottomData, m_blobTemp.gpu_data, hTopData); // X-EX
171
173 {
174 // compute variance using var(X) = E((X-EX)^2)
175 m_cuda.powx(colBottom[0].count(), hTopData, 2.0, m_blobTemp.mutable_gpu_data); // (X-EX)^2
176 m_cuda.gemv(false, nNum, nDim, 1.0 / nDim, m_blobTemp.gpu_data, m_blobSumMultiplier.gpu_data, 0.0, m_blobVariance.mutable_gpu_data); // E((X-EX)^2)
177
178 // normalize variance
179 m_cuda.powx(m_blobVariance.count(), m_blobVariance.gpu_data, 0.5, m_blobVariance.mutable_gpu_data);
180 m_cuda.add_scalar(m_blobVariance.count(), m_dfEps, m_blobVariance.mutable_gpu_data);
181 m_cuda.gemm(false, false, nNum, nDim, 1, 1.0, m_blobVariance.gpu_data, m_blobSumMultiplier.gpu_data, 0.0, m_blobTemp.mutable_gpu_data);
182 m_cuda.div(m_blobTemp.count(), hTopData, m_blobTemp.gpu_data, hTopData);
183 }
184 }
185
197 protected override void backward(BlobCollection<T> colTop, List<bool> rgbPropagateDown, BlobCollection<T> colBottom)
198 {
199 if (!rgbPropagateDown[0])
200 return;
201
202 long hTopDiff = colTop[0].gpu_diff;
203 long hTopData = colTop[0].gpu_data;
204 long hBottomData = colBottom[0].gpu_data;
205 long hBottomDiff = colBottom[0].mutable_gpu_diff;
206 int nNum = colBottom[0].num;
207
209 nNum *= colBottom[0].channels;
210
211 int nDim = colBottom[0].count() / nNum;
212
214 {
215 m_cuda.mul(m_blobTemp.count(), hTopData, hTopDiff, hBottomDiff);
216 m_cuda.gemv(false, nNum, nDim, 1.0, hBottomDiff, m_blobSumMultiplier.gpu_data, 0.0, m_blobMean.mutable_gpu_data);
217 m_cuda.gemm(false, false, nNum, nDim, 1, 1.0, m_blobMean.gpu_data, m_blobSumMultiplier.gpu_data, 0.0, hBottomDiff);
218 m_cuda.mul(m_blobTemp.count(), hTopData, hBottomDiff, hBottomDiff);
219
220 m_cuda.gemv(false, nNum, nDim, 1.0, hTopDiff, m_blobSumMultiplier.gpu_data, 0.0, m_blobMean.mutable_gpu_data);
221 m_cuda.gemm(false, false, nNum, nDim, 1, 1.0, m_blobMean.gpu_data, m_blobSumMultiplier.gpu_data, 1.0, hBottomDiff);
222
223 m_cuda.axpby(m_blobTemp.count(), 1.0, hTopDiff, -1.0 / nDim, hBottomDiff);
224
225 // put the squares of bottom into temp_
226 m_cuda.powx(m_blobTemp.count(), hBottomData, 2.0, m_blobTemp.mutable_gpu_data);
227 m_cuda.gemm(false, false, nNum, nDim, 1, 1.0, m_blobVariance.gpu_data, m_blobSumMultiplier.gpu_data, 0.0, m_blobTemp.mutable_gpu_data);
228 m_cuda.div(m_blobTemp.count(), hBottomDiff, m_blobTemp.gpu_data, hBottomDiff);
229 }
230 else
231 {
232 m_cuda.gemv(false, nNum, nDim, 1.0 / nDim, hTopDiff, m_blobSumMultiplier.gpu_data, 0.0, m_blobMean.mutable_gpu_data);
233 m_cuda.gemm(false, false, nNum, nDim, 1, -1.0, m_blobMean.gpu_data, m_blobSumMultiplier.gpu_data, 0.0, m_blobTemp.mutable_gpu_data);
234 m_cuda.add(m_blobTemp.count(), hTopDiff, m_blobTemp.gpu_data, hBottomDiff);
235 }
236 }
237 }
238}
The Log class provides general output in text form.
Definition: Log.cs:13
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 ReshapeLike(BlobCollection< T > src)
Reshapes all blobs in the collection to the sizes of the source.
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
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
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
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
An interface for the units of computation which can be composed into a Net.
Definition: Layer.cs:31
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
The "Mean-Variance Normalization" MVNLayer normalizes the input to have 0-mean and/or unit (1) varian...
Definition: MVNLayer.cs:22
override void Reshape(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Reshape the bottom (input) and top (output) blobs.
Definition: MVNLayer.cs:128
override void forward(BlobCollection< T > colBottom, BlobCollection< T > colTop)
The forward computation that computes the normalization.
Definition: MVNLayer.cs:156
override void dispose()
Releases all GPU and host resources used by the Layer.
Definition: MVNLayer.cs:57
override void setup_internal_blobs(BlobCollection< T > col)
Derivative layers should add all internal blobws to the 'col' provided.
Definition: MVNLayer.cs:87
MVNLayer(CudaDnn< T > cuda, Log log, LayerParameter p)
The MVNLayer constructor.
Definition: MVNLayer.cs:42
override void backward(BlobCollection< T > colTop, List< bool > rgbPropagateDown, BlobCollection< T > colBottom)
Computes the mvn error gradient w.r.t the output.
Definition: MVNLayer.cs:197
override int ExactNumBottomBlobs
Returns the exact number of required bottom (input) Blobs: input.
Definition: MVNLayer.cs:102
override void LayerSetUp(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Setup the layer.
Definition: MVNLayer.cs:119
override int ExactNumTopBlobs
Returns the exact number of required top (output) Blobs: mvn
Definition: MVNLayer.cs:110
Specifies the base parameter for all layers.
string name
Specifies the name of this LayerParameter.
MVNParameter mvn_param
Returns the parameter set when initialized with LayerType.MVN
LayerType
Specifies the layer type.
double eps
Specifies a small value to avoid divide by zero.
Definition: MVNParameter.cs:57
bool across_channels
Specifies whether or not to normalize accross channels.
Definition: MVNParameter.cs:46
bool normalize_variance
Specifies whether or not to normalize the variance.
Definition: MVNParameter.cs:36
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