MyCaffe  1.12.2.41
Deep learning software for Windows C# programmers.
AccuracyEncodingLayer.cs
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using MyCaffe.basecode;
6using MyCaffe.common;
7using MyCaffe.param;
8
10{
18 public class AccuracyEncodingLayer<T> : Layer<T>
19 {
20 int m_nCacheSize = 100;
21 int m_nNum = 0;
22 int m_nEncodingDim = 0;
23 Blob<T> m_blobEncodings;
24 Blob<T> m_blobData;
25 Blob<T> m_blobDistSq;
26 Blob<T> m_blobSummerVec;
27 Dictionary<int, int> m_rgLabelCounts = new Dictionary<int, int>();
28
41 : base(cuda, log, p)
42 {
43 m_type = LayerParameter.LayerType.ACCURACY_ENCODING;
44 m_blobEncodings = new Blob<T>(cuda, log);
45 m_blobEncodings.Name = m_param.name + " encodings";
46 m_blobDistSq = new Blob<T>(cuda, log, false);
47 m_blobDistSq.Name = m_param.name + " distsq";
48 m_blobSummerVec = new Blob<T>(cuda, log, false);
49 m_blobSummerVec.Name = m_param.name + " sum";
50 m_blobData = new Blob<T>(cuda, log);
51 m_blobData.Name = m_param.name + " data";
52 }
53
55 protected override void dispose()
56 {
57 dispose(ref m_blobEncodings);
58 dispose(ref m_blobDistSq);
59 dispose(ref m_blobSummerVec);
60 dispose(ref m_blobData);
61
62 base.dispose();
63 }
64
66 protected override void setup_internal_blobs(BlobCollection<T> col)
67 {
68 if (col.Count > 0)
69 return;
70
71 col.Add(m_blobEncodings);
72 col.Add(m_blobDistSq);
73 col.Add(m_blobSummerVec);
74 col.Add(m_blobData);
75 }
76
80 public override int ExactNumBottomBlobs
81 {
82 get { return 2; }
83 }
84
88 public override int ExactNumTopBlobs
89 {
90 get { return 1; }
91 }
92
98 public override void LayerSetUp(BlobCollection<T> colBottom, BlobCollection<T> colTop)
99 {
100 m_log.CHECK_EQ((int)m_param.accuracy_param.top_k, 1, "Accuracy Encoding Layer only supports a topk = 1.");
101 m_log.CHECK_EQ((int)m_param.accuracy_param.axis, 1, "Accuracy Encoding Layer expects axis to = 1.");
102
104 m_log.WriteLine("WARNING: The Accuracy Encoding Layer does not use the 'ignore_label' parameter.");
105
106 m_nCacheSize = m_param.decode_param.cache_size;
107 m_log.CHECK_GT(m_nCacheSize, 0, "The cache size must be > 0.");
108
109 if (m_colBlobs.Count == 0)
110 {
111 Blob<T> blobCentroids = new Blob<T>(m_cuda, m_log, false);
112 blobCentroids.Name = m_param.name + " centroids";
113 blobCentroids.reshape_when_sharing = true;
114
115 List<int> rgCentroidShape = new List<int>() { 0 }; // skip size check.
116 if (!shareParameter(blobCentroids, rgCentroidShape))
117 {
118 blobCentroids.Reshape(2, m_nEncodingDim, 1, 1); // set to at least two labels initially (may get expanded in forward).
119 blobCentroids.SetData(0);
120 }
121
122 m_colBlobs.Add(blobCentroids);
123 }
124 }
125
131 public override void Reshape(BlobCollection<T> colBottom, BlobCollection<T> colTop)
132 {
133 int nNum = colBottom[0].num;
134 bool bFirstReshape = (nNum != m_nNum) ? true : false;
135 m_nNum = nNum;
136 m_nEncodingDim = colBottom[0].channels;
137
138 m_log.CHECK_EQ(colBottom[1].num, m_nNum, "The number of labels does not match the number of items at bottom[0].");
139
140 List<int> rgTopShape = new List<int>(); // Accuracy is a scalar; 0 axes.
141 colTop[0].Reshape(rgTopShape);
142 colTop[0].type = BLOB_TYPE.ACCURACY;
143
144 // vector of ones used to sum along channels.
145 m_blobSummerVec.Reshape(colBottom[0].channels, 1, 1, 1);
146 m_blobSummerVec.SetData(1.0);
147 }
148
168 protected override void forward(BlobCollection<T> colBottom, BlobCollection<T> colTop)
169 {
170 m_log.CHECK_EQ(colBottom[1].count() % 2, 0, "The bottom[1] count must be a factor of 2 for {lbl1, lbl2}.");
171 int nItemNum = colBottom[0].num;
172 int nItemCount = nItemNum * m_param.decode_param.cache_size;
173 double dfAlpha = 1.0 / (double)nItemCount;
174
175 double dfAccuracy = 0;
176 double[] rgBottomLabel = convertD(colBottom[1].update_cpu_data());
177 int nCorrectCount = 0;
178 int nComparedCount = 0;
179
180 int nMaxLabel = rgBottomLabel.Max(p => (int)p);
181 int nMaxKey = (m_rgLabelCounts.Count == 0) ? 0 : m_rgLabelCounts.Max(p => p.Key);
182 if (nMaxLabel > nMaxKey)
183 {
184 int nNumLabels = nMaxLabel + 1;
185
186 m_colBlobs[0].Reshape(nNumLabels, m_nEncodingDim, 1, 1);
187 m_colBlobs[0].SetData(0);
188 m_blobData.Reshape(nNumLabels, m_nEncodingDim, 1, 1);
189 m_blobDistSq.Reshape(nNumLabels, 1, 1, 1);
190 m_rgLabelCounts.Clear();
191 }
192
193 for (int i = 0; i < colBottom[0].num; i++)
194 {
195 int nLabel = (int)rgBottomLabel[i * 2]; // Only the first embedding and first label are used (second is ignored).
196 int nLabelItemCount = 0;
197
198 if (m_rgLabelCounts.ContainsKey(nLabel))
199 nLabelItemCount = m_rgLabelCounts[nLabel];
200
201 // Create the centroid when counts fall between Centroid Start and Centroid End by
202 // averaging all items within these counts together to create the centroid.
203 if (nLabelItemCount == 0)
204 {
205 // Add initial centroid portion for the label.
206 m_cuda.copy(m_nEncodingDim, colBottom[0].gpu_data, m_colBlobs[0].mutable_gpu_data, i * m_nEncodingDim, nLabel * m_nEncodingDim);
207 m_cuda.scale(m_nEncodingDim, convert(dfAlpha), m_colBlobs[0].gpu_data, m_colBlobs[0].mutable_gpu_data, nLabel * m_nEncodingDim, nLabel * m_nEncodingDim);
208 }
209 else if (nLabelItemCount < nItemCount)
210 {
211 dfAlpha = 1.0 / (nLabelItemCount + 1);
212 // Add portion of current item to centroids for the label.
213 m_cuda.add(m_nEncodingDim, colBottom[0].gpu_data, m_colBlobs[0].gpu_data, m_colBlobs[0].mutable_gpu_data, dfAlpha, 1.0 - dfAlpha, i * m_nEncodingDim, nLabel * m_nEncodingDim, nLabel * m_nEncodingDim);
214 }
215 else
216 {
217 // Add portion of current item to centroids for the label.
218 m_cuda.add(m_nEncodingDim, colBottom[0].gpu_data, m_colBlobs[0].gpu_data, m_colBlobs[0].mutable_gpu_data, dfAlpha, 1.0 - dfAlpha, i * m_nEncodingDim, nLabel * m_nEncodingDim, nLabel * m_nEncodingDim);
219 }
220
221 m_colBlobs[0].snapshot_requested = true;
222
223 if (!m_rgLabelCounts.ContainsKey(nLabel))
224 m_rgLabelCounts.Add(nLabel, 1);
225 else
226 m_rgLabelCounts[nLabel]++;
227
228 // Load data with the current data embedding across each label 'slot' in blobData.
229 int nCount = m_blobData.count();
230 int nItems = m_blobData.num;
231 m_cuda.fill(nItems, m_nEncodingDim, colBottom[0].gpu_data, i * m_nEncodingDim, nCount, m_blobData.mutable_gpu_data);
232
233 m_cuda.sub(nCount,
234 m_blobData.gpu_data, // a
235 m_colBlobs[0].gpu_data, // b (centroid)
236 m_blobData.mutable_gpu_diff); // a_i - b_i
237
238 m_cuda.powx(nCount,
239 m_blobData.gpu_diff, // a_i - b_i
240 2.0,
241 m_blobData.mutable_gpu_diff); // (a_i - b_i)^2
242
243 m_cuda.gemv(false,
244 m_blobData.num, // label count.
245 m_blobData.channels, // encoding size.
246 1.0,
247 m_blobData.gpu_diff, // (a_i - b_i)^2
248 m_blobSummerVec.gpu_data,
249 0.0,
250 m_blobDistSq.mutable_gpu_data); // \Sum (a_i - b_i)^2
251
252 // The label with the smallest distance is the detected label.
253 double[] rgLabelDist = convertD(m_blobDistSq.mutable_cpu_data);
254 int nDetectedLabel = -1;
255 double dfMin = double.MaxValue;
256
257 for (int l = 0; l < rgLabelDist.Length; l++)
258 {
259 if (rgLabelDist[l] < dfMin)
260 {
261 dfMin = rgLabelDist[l];
262 nDetectedLabel = l;
263 }
264 }
265
266 if (nDetectedLabel == nLabel)
267 nCorrectCount++;
268
269 nComparedCount++;
270 }
271
272 dfAccuracy = (nComparedCount == 0) ? 0 : (double)nCorrectCount / nComparedCount;
273
274 colTop[0].SetData(dfAccuracy, 0);
275 colTop[0].Tag = m_param.accuracy_param.top_k;
276 }
277
279 protected override void backward(BlobCollection<T> colTop, List<bool> rgbPropagateDown, BlobCollection<T> colBottom)
280 {
281 // do nothing.
282 }
283 }
284}
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_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 Add(Blob< T > b)
Add a new Blob to the collection.
void SetData(double df)
Set all blob data to the value specified.
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
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
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
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
bool reshape_when_sharing
When true, this Blob is reshaped to the source when sharing the source data (default = false).
Definition: Blob.cs:1803
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
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
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
void convert(BlobCollection< T > col)
Convert a collection of blobs from / to half size.
Definition: Layer.cs:535
bool shareParameter(Blob< T > b, List< int > rgMinShape, bool bAllowEndsWithComparison=false)
Attempts to share a parameter Blob if another parameter Blob with the same name and accpetable size i...
Definition: Layer.cs:1152
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
BlobCollection< T > m_colBlobs
Specifies the learnable parameter Blobs of the Layer.
Definition: Layer.cs:55
The AccuracyEncodingLayer computes the classification accuracy for an encoding used in a classificati...
override void forward(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Forward compuation.
override void Reshape(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Reshape the bottom (input) and top (output) blobs.
AccuracyEncodingLayer(CudaDnn< T > cuda, Log log, LayerParameter p)
Constructor.
override int ExactNumTopBlobs
Returns the number of top blobs: accuracy
override void dispose()
Releases all GPU and host resources used by the Layer.
override void setup_internal_blobs(BlobCollection< T > col)
Derivative layers should add all internal blobws to the 'col' provided.
override void backward(BlobCollection< T > colTop, List< bool > rgbPropagateDown, BlobCollection< T > colBottom)
Not implemented – EncodingAccuracyLayer cannot be used as a loss.
override int ExactNumBottomBlobs
Returns the number of bottom blobs used: predicted, label
override void LayerSetUp(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Setup the layer.
uint top_k
When computing accuracy, count as correct by comparing the true label to the top_k scoring classes....
List< int > ignore_labels
If specified, ignore instances with the given label(s).
int axis
The 'label' axis of the prediction blob, whos argmax corresponds to the predicted label – may be nega...
Specifies the base parameter for all layers.
string name
Specifies the name of this LayerParameter.
AccuracyParameter accuracy_param
Returns the parameter set when initialized with LayerType.ACCURACY
DecodeParameter decode_param
Returns the parameter set when initializing with LayerType.DECODE or LayerType.ACCURACY_ENCODING;
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
BLOB_TYPE
Defines the tpe of data held by a given Blob.
Definition: Interfaces.cs:62
The MyCaffe.layers.beta namespace contains all beta stage layers.
Definition: LayerFactory.cs:9
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