2using System.Collections.Generic;
26 List<int> m_rgIgnoreLabels =
new List<int>();
27 int m_nCentroidOutputIteration = 300;
28 int m_nCacheSize = 100;
30 int m_nEncodingDim = 0;
35 int m_nLabelCount = 0;
39 double m_dfPreGenAlpha = 0;
40 bool m_bInitializePreGenTargets =
true;
52 m_blobDistSq =
new Blob<T>(cuda, log,
false);
54 m_blobSummerVec =
new Blob<T>(cuda, log,
false);
56 m_blobData =
new Blob<T>(cuda, log);
61 m_blobWork =
new Blob<T>(cuda, log);
62 m_blobWork.
Name =
"work";
82 col.
Add(m_blobDistSq);
83 col.
Add(m_blobSummerVec);
127 m_nEncodingDim = colBottom[0].count(1);
134 if (m_nCentroidOutputIteration < 10)
135 m_log.
WriteLine(
"WARNING: Centroid output iteration is set at " + m_nCentroidOutputIteration.ToString() +
", a value above 10 is recommended.");
140 m_nCentroidOutputIteration = 0;
144 m_log.
CHECK_GT(m_nCacheSize, 0,
"The cache size must be > 0.");
154 List<int> rgCentroidShape =
new List<int>() { 0 };
157 blobCentroids.
Reshape(2, m_nEncodingDim, 1, 1);
167 List<int> rgStatusShape =
new List<int>() { 0 };
170 blobStatus.
Reshape(1, 1, 1, 1);
180 List<int> rgEncCountShape =
new List<int>() { 0 };
183 blobEncodingCounts.
Reshape(1, 1, 1, 1);
195 List<int> rgEncShape =
new List<int>() { 0 };
198 blobEncodings.
Reshape(1, 1, m_nEncodingDim, 1);
216 int nNum = colBottom[0].num;
217 bool bFirstReshape = (nNum != m_nNum) ?
true :
false;
220 m_log.
CHECK_EQ(m_nEncodingDim, colBottom[0].count(1),
"The encoding dim changed!");
222 if (colBottom.
Count > 1)
223 m_log.
CHECK_EQ(colBottom[1].num, m_nNum,
"The number of labels does not match the number of items at bottom[0].");
234 Random rand =
new Random();
237 int nDim = b.
count(1);
242 List<List<double>> rgDist =
new List<List<double>>();
244 double dfAbsMinDist =
double.MaxValue;
246 for (
int i = 0; i < nNum; i++)
248 rgDist.Add(
new List<double>());
250 for (
int j = 0; j < nNum; j++)
257 for (
int k = 0; k < nDim; k++)
259 dfDiff = rgData[i * nDim + k] - rgData[j * nDim + k];
260 dfDist += (dfDiff * dfDiff);
263 rgDist[i].Add(dfDist);
264 dfAbsMinDist = Math.Min(dfAbsMinDist, dfDist);
266 if (dfDist < dfMinDist)
268 for (
int k = 0; k < nDim; k++)
270 rgData[j * nDim + k] += (float)(rand.NextDouble() * (dfMinDist / 4));
277 if (dfAbsMinDist > dfMinDist)
306 int nItemNum = colBottom[0].num;
307 int nItemCount = nItemNum * m_nCacheSize;
309 double dfAlpha = 1.0 / (double)nItemCount;
310 double[] rgBottomLabel =
null;
314 nLabelDim = colBottom[1].count(1);
315 m_log.
CHECK(colBottom[1].count() % nLabelDim == 0,
"The bottom[1] count must be a factor of 2 for {lbl1, lbl2}, or 3 for {anc, pos, neg}.");
317 rgBottomLabel =
convertD(colBottom[1].update_cpu_data());
319 int nMaxLabel = rgBottomLabel.Max(p => (
int)p);
320 if (nMaxLabel > m_nLabelCount)
322 int nNumLabels = nMaxLabel + 1;
327 if (
m_colBlobs[0].count() != nNumLabels * m_nEncodingDim)
329 m_colBlobs[0].Reshape(nNumLabels, m_nEncodingDim, 1, 1);
347 if (
m_colBlobs[3].count() != nNumLabels * nItemCount * m_nEncodingDim)
349 m_colBlobs[3].Reshape(nNumLabels, nItemCount, m_nEncodingDim, 1);
354 m_nLabelCount = nNumLabels;
359 if (m_bInitializePreGenTargets)
363 m_bInitializePreGenTargets =
false;
368 int nActiveLabels =
m_colBlobs[1].num - m_rgIgnoreLabels.Count;
380 m_blobSummerVec.
Reshape(m_blobData.
num, 1, 1, 1);
385 if (nActiveLabels <= 0)
390 for (
int i = 0; i < colBottom[0].num; i++)
393 if (rgBottomLabel !=
null)
399 int nLabel = (int)rgBottomLabel[i * nLabelDim];
409 if (nLabelItemCount == 0)
412 m_cuda.copy(m_nEncodingDim, colBottom[0].gpu_data,
m_colBlobs[0].mutable_gpu_data, i * m_nEncodingDim, nLabel * m_nEncodingDim);
415 else if (nLabelItemCount < nItemCount)
417 dfAlpha = 1.0 / (nLabelItemCount + 1);
419 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);
424 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);
426 if (nReady == 0 && !m_rgIgnoreLabels.Contains(nLabel))
439 int nSrcOff = i * m_nEncodingDim;
440 int nDstOff = (nLabel * nItemCount * m_nEncodingDim) + ((nLabelItemCount % nItemCount) * m_nEncodingDim);
441 m_cuda.copy(m_nEncodingDim, colBottom[0].gpu_data,
m_colBlobs[3].mutable_gpu_data, nSrcOff, nDstOff);
444 m_colBlobs[2].SetData(nLabelItemCount + 1, nLabel);
449 if (nCompletedTargets == nActiveLabels)
458 int nCount = m_blobData.
count();
459 int nItems = m_blobData.
num;
464 m_cuda.fill(nItems, m_nEncodingDim, colBottom[0].gpu_data, i * m_nEncodingDim, nCount, m_blobData.
mutable_gpu_data);
469 if (nCompletedTargets == nActiveLabels)
484 int nDim = m_blobData.
count(1);
485 float[] rgMinDist =
new float[m_blobData.
num];
486 for (
int j = 0; j < m_blobData.
num; j++)
502 double[] rgMinD =
m_cuda.GetHostMemoryDouble(m_hMin);
503 m_blobWork.
Reshape((
int)rgMinD[0], 1, 1, 1);
506 float[] rgMin =
m_cuda.GetHostMemoryFloat(m_hMin);
507 List<float> rgMin1 = rgMin.Where(p => p <
float.MaxValue).Take(
m_param.
decode_param.k).ToList();
509 rgMinDist[j] = rgMin1.Average();
512 m_blobDistSq.
Reshape(rgMinDist.Length, 1, 1, 1);
517 m_blobDistSq.
Reshape(m_blobData.
num, 1, 1, 1);
548 foreach (
int nIgnoreLabel
in m_rgIgnoreLabels)
550 m_blobDistSq.
SetData(
float.MaxValue, nIgnoreLabel);
554 m_cuda.copy(m_blobDistSq.
num, m_blobDistSq.
gpu_data, colTop[0].mutable_gpu_data, 0, i * m_blobDistSq.
num);
558 if (colTop.
Count > 1)
563 if (m_nIteration >= m_nCentroidOutputIteration && nCompletedCentroids == nActiveLabels)
570 m_log.
WriteLine(
"WARNING: The centroids for the decode layer are not completed! You must train the model first to calculate the centroids.");
The Log class provides general output in text form.
void CHECK(bool b, string str)
Test a flag for true.
void WriteLine(string str, bool bOverrideEnabled=false, bool bHeader=false, bool bError=false, bool bDisable=false)
Write a line of output.
void CHECK_EQ(double df1, double df2, string str)
Test whether one number is equal to another.
void CHECK_GT(double df1, double df2, string str)
Test whether one number is greater than another.
void CHECK_GE(double df1, double df2, string str)
Test whether one number is greater than or equal to another.
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 ReshapeLike(BlobCollection< T > src)
Reshapes all blobs in the collection to the sizes of the source.
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.
int channels
DEPRECIATED; legacy shape accessor channels: use shape(1) instead.
void SetData(T[] rgData, int nCount=-1, bool bSetCount=true)
Sets a number of items within the Blob's data.
int height
DEPRECIATED; legacy shape accessor height: use shape(2) instead.
long mutable_gpu_diff
Returns the diff GPU handle used by the CudaDnn connection.
long mutable_gpu_data
Returns the data GPU handle used by the CudaDnn connection.
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...
void Reshape(int nNum, int nChannels, int nHeight, int nWidth, bool? bUseHalfSize=null)
DEPRECIATED; use
bool reshape_when_sharing
When true, this Blob is reshaped to the source when sharing the source data (default = false).
int count()
Returns the total number of items in the Blob.
void ReshapeLike(Blob< T > b, bool? bUseHalfSize=null)
Reshape this Blob to have the same shape as another Blob.
string Name
Get/set the name of the Blob.
long gpu_diff
Returns the diff GPU handle used by the CudaDnn connection.
int num
DEPRECIATED; legacy shape accessor num: use shape(0) instead.
long gpu_data
Returns the data GPU handle used by the CudaDnn connection.
The CudaDnn object is the main interface to the Low-Level Cuda C++ DLL.
long AllocHostBuffer(long lCapacity)
Allocate a block of host memory with a specified capacity.
An interface for the units of computation which can be composed into a Net.
Log m_log
Specifies the Log for output.
LayerParameter m_param
Specifies the LayerParameter describing the Layer.
void convert(BlobCollection< T > col)
Convert a collection of blobs from / to half size.
T m_tZero
Specifies a generic type equal to 0.0.
T m_tOne
Specifies a generic type equal to 1.0.
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...
float convertF(T df)
Converts a generic to a float value.
double convertD(T df)
Converts a generic to a double value.
Phase m_phase
Specifies the Phase under which the Layer is run.
CudaDnn< T > m_cuda
Specifies the CudaDnn connection to Cuda.
LayerParameter.LayerType m_type
Specifies the Layer type.
BlobCollection< T > m_colBlobs
Specifies the learnable parameter Blobs of the Layer.
The DecodeLayer decodes the label of a classification for an encoding produced by a Siamese Network o...
override void LayerSetUp(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Setup the layer.
void createPreGenTargets(Blob< T > b, double dfMinDist)
Creates the pre-distanced pre-generated targets, only made public for testing.
override void forward(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Forward compuation.
override void backward(BlobCollection< T > colTop, List< bool > rgbPropagateDown, BlobCollection< T > colBottom)
Not implemented – DecodeLayer cannot be used as a loss.
override int MaxTopBlobs
Returns the min number of top blobs: distances, centroids
override void dispose()
Releases all GPU and host resources used by the Layer.
DecodeLayer(CudaDnn< T > cuda, Log log, LayerParameter p)
Constructor.
override int MinTopBlobs
Returns the min number of top blobs: distances
override void setup_internal_blobs(BlobCollection< T > col)
Derivative layers should add all internal blobws to the 'col' provided.
override int MinBottomBlobs
Returns the minimum number of bottom blobs used: predicted (RUN phase)
override void Reshape(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Reshape the bottom (input) and top (output) blobs.
override int MaxBottomBlobs
Returns the maximum number of bottom blobs used: predicted, label (TRAIN and TEST phase)
Specifies the base parameter for all layers.
string name
Specifies the name of this LayerParameter.
Phase phase
Specifies the Phase for which this LayerParameter is run.
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.
Phase
Defines the Phase under which to run a Net.
The MyCaffe.common namespace contains common MyCaffe classes.
The MyCaffe.layers.beta namespace contains all beta stage layers.
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-...