PetaVision  Alpha
L2NormProbe.cpp
1 /*
2  * L2NormProbe.cpp
3  *
4  * Created on: Aug 11, 2015
5  * Author: pschultz
6  */
7 
8 #include "L2NormProbe.hpp"
9 #include "columns/HyPerCol.hpp"
10 #include "layers/HyPerLayer.hpp"
11 
12 namespace PV {
13 
14 L2NormProbe::L2NormProbe() : AbstractNormProbe() { initialize_base(); }
15 
16 L2NormProbe::L2NormProbe(const char *name, HyPerCol *hc) : AbstractNormProbe() {
17  initialize_base();
18  initialize(name, hc);
19 }
20 
21 L2NormProbe::~L2NormProbe() {}
22 
23 int L2NormProbe::initialize_base() {
24  exponent = 1.0;
25  return PV_SUCCESS;
26 }
27 
28 int L2NormProbe::initialize(const char *name, HyPerCol *hc) {
29  return AbstractNormProbe::initialize(name, hc);
30 }
31 
32 int L2NormProbe::ioParamsFillGroup(enum ParamsIOFlag ioFlag) {
33  int status = AbstractNormProbe::ioParamsFillGroup(ioFlag);
34  ioParam_exponent(ioFlag);
35  return status;
36 }
37 
38 void L2NormProbe::ioParam_exponent(enum ParamsIOFlag ioFlag) {
39  parent->parameters()->ioParamValue(
40  ioFlag, name, "exponent", &exponent, 1.0 /*default*/, true /*warnIfAbsent*/);
41 }
42 
44  assert(!parent->parameters()->presentAndNotBeenRead(name, "exponent"));
45  int status = PV_SUCCESS;
46  if (exponent == 1.0) {
47  status = setNormDescriptionToString("L2-norm");
48  }
49  else if (exponent == 2.0) {
50  status = setNormDescriptionToString("L2-norm squared");
51  }
52  else {
53  std::stringstream desc("(L2-norm)^");
54  desc << exponent;
55  status = setNormDescriptionToString(desc.str().c_str());
56  };
57  return status;
58 };
59 
60 double L2NormProbe::getValueInternal(double timevalue, int index) {
61  if (index < 0 || index >= parent->getNBatch()) {
62  return PV_FAILURE;
63  }
64  PVLayerLoc const *loc = getTargetLayer()->getLayerLoc();
65  int const nx = loc->nx;
66  int const ny = loc->ny;
67  int const nf = loc->nf;
68  PVHalo const *halo = &loc->halo;
69  int const lt = halo->lt;
70  int const rt = halo->rt;
71  int const dn = halo->dn;
72  int const up = halo->up;
73  double l2normsq = 0.0;
74  float const *aBuffer =
75  getTargetLayer()->getLayerData() + index * getTargetLayer()->getNumExtended();
76 
77  if (getMaskLayer()) {
78  PVLayerLoc const *maskLoc = getMaskLayer()->getLayerLoc();
79  PVHalo const *maskHalo = &maskLoc->halo;
80  float const *maskLayerData =
81  getMaskLayer()->getLayerData()
82  + index * getMaskLayer()->getNumExtended(); // Is there a DataStore method to return the
83  // part of the layer data for a given batch
84  // index?
85  int const maskLt = maskHalo->lt;
86  int const maskRt = maskHalo->rt;
87  int const maskDn = maskHalo->dn;
88  int const maskUp = maskHalo->up;
89  if (maskHasSingleFeature()) {
90  assert(getTargetLayer()->getNumNeurons() == nx * ny * nf);
91  int nxy = nx * ny;
92 #ifdef PV_USE_OPENMP_THREADS
93 #pragma omp parallel for reduction(+ : l2normsq)
94 #endif // PV_USE_OPENMP_THREADS
95  for (int kxy = 0; kxy < nxy; kxy++) {
96  int kexMask = kIndexExtended(kxy, nx, ny, 1, maskLt, maskRt, maskDn, maskUp);
97  if (maskLayerData[kexMask]) {
98  int featureBase = kxy * nf;
99  for (int f = 0; f < nf; f++) {
100  int kex = kIndexExtended(featureBase++, nx, ny, nf, lt, rt, dn, up);
101  l2normsq += pow((double)aBuffer[kex], 2.0);
102  }
103  }
104  }
105  }
106  else {
107 #ifdef PV_USE_OPENMP_THREADS
108 #pragma omp parallel for reduction(+ : l2normsq)
109 #endif // PV_USE_OPENMP_THREADS
110  for (int k = 0; k < getTargetLayer()->getNumNeurons(); k++) {
111  int kex = kIndexExtended(k, nx, ny, nf, lt, rt, dn, up);
112  int kexMask = kIndexExtended(k, nx, ny, nf, maskLt, maskRt, maskDn, maskUp);
113  double val = aBuffer[kex];
114  l2normsq += (double)maskLayerData[kexMask] * val * val;
115  }
116  }
117  }
118  else {
119  if (getTargetLayer()->getSparseFlag()) {
120  PVLayerCube cube = getTargetLayer()->getPublisher()->createCube();
121  long int numActive = cube.numActive[index];
122  int numItems = cube.numItems / cube.loc.nbatch;
123  SparseList<float>::Entry const *activeList =
124  &((SparseList<float>::Entry *)cube.activeIndices)[index * numItems];
125 #ifdef PV_USE_OPENMP_THREADS
126 #pragma omp parallel for reduction(+ : l2normsq)
127 #endif // PV_USE_OPENMP_THREADS
128  for (int k = 0; k < numActive; k++) {
129  int extIndex = activeList[k].index;
130  int inRestricted = !extendedIndexInBorderRegion(
131  extIndex, nx, ny, nf, halo->lt, halo->rt, halo->dn, halo->up);
132  double val = inRestricted * fabs((double)aBuffer[extIndex]);
133  l2normsq += pow(val, 2.0);
134  }
135  }
136  else {
137 #ifdef PV_USE_OPENMP_THREADS
138 #pragma omp parallel for reduction(+ : l2normsq)
139 #endif // PV_USE_OPENMP_THREADS
140  for (int k = 0; k < getTargetLayer()->getNumNeurons(); k++) {
141  int kex = kIndexExtended(k, nx, ny, nf, lt, rt, dn, up);
142  l2normsq += pow((double)aBuffer[kex], 2.0);
143  }
144  }
145  }
146 
147  return l2normsq;
148 }
149 
150 void L2NormProbe::calcValues(double timevalue) {
152  if (exponent != 2.0) {
153  double *valBuf = getValuesBuffer();
154  int numVals = this->getNumValues();
155  for (int b = 0; b < numVals; b++) {
156  double v = valBuf[b];
157  valBuf[b] = pow(v, exponent / 2.0);
158  }
159  }
160 }
161 
162 } // end namespace PV
virtual void calcValues(double timeValue) override
virtual int ioParamsFillGroup(enum ParamsIOFlag ioFlag) override
Definition: L2NormProbe.cpp:32
virtual double getValueInternal(double timevalue, int index) override
Definition: L2NormProbe.cpp:60
virtual int ioParamsFillGroup(enum ParamsIOFlag ioFlag) override
virtual int setNormDescription() override
Definition: L2NormProbe.cpp:43
double * getValuesBuffer()
Definition: BaseProbe.hpp:319
virtual void ioParam_exponent(enum ParamsIOFlag ioFlag)
exponent: The exponent on the L2-norm. getValue(t, index) returns (L2-Norm)^exponent.
Definition: L2NormProbe.cpp:38
virtual void calcValues(double timevalue) override
int getNumValues()
Definition: BaseProbe.hpp:61