Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TM anomaly #406

Merged
merged 42 commits into from
May 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
ad718f1
TM::anomalyScore moved to TM directly
breznak Apr 15, 2019
02a2364
Merge branch 'master_community' into tm_anomaly
breznak Apr 17, 2019
e2f21cc
Merge branch 'master_community' into tm_anomaly
breznak Apr 25, 2019
16a3461
TM: move anomalyScore computation to activateCells
breznak Apr 25, 2019
af467a5
TM: anomalyScore implemented
breznak Apr 25, 2019
f6d3730
Anomaly: rm Anomaly class tests
breznak Apr 25, 2019
52e8ab5
AnomalyLikelihood: moved tests to separate file
breznak Apr 25, 2019
0a9ba95
Merge branch 'master_community' into tm_anomaly
breznak May 1, 2019
372cc57
TM: anomaly computation updates
breznak May 1, 2019
8556107
TM: small test update
breznak May 1, 2019
f3c5157
TM: fix anomaly compute
breznak May 1, 2019
dbf7f73
TM: anomaly computation uses TMAnomaly struct
breznak May 1, 2019
3a34e6c
TM: fix serialization TMAnomaly
breznak May 1, 2019
affb657
Anomaly: remove Anomaly class
breznak May 1, 2019
fea3d2c
Hotgym: update anomaly scores check for TM.anomaly.score
breznak May 1, 2019
a3557eb
cleanup TM test
breznak May 1, 2019
187e5c9
TM: tiny doc
breznak May 1, 2019
43f52c5
TM anomaly: split update & getScore()
breznak May 1, 2019
96e8211
TM: implement getAnomalyScore()
breznak May 2, 2019
1072e63
AnomalyLikelihood: disabled broken tests
breznak May 2, 2019
6e48cff
TMRegion: cleanup includes
breznak May 2, 2019
90c4985
TMRegion: simplify compute()
breznak May 2, 2019
a47c145
SDR: fix debug msg
breznak May 2, 2019
eab394b
TM: fix anomaly: match TM dimensions
breznak May 2, 2019
367f682
TM: debug msg 2
breznak May 2, 2019
d75b87f
API_Changelog about Anomaly removal
breznak May 2, 2019
f1c1810
Anomaly: computeRawAnomalyScore: keep only SDR version
breznak May 3, 2019
2d96289
Merge branch 'master_community' into tm_anomaly
breznak May 3, 2019
9f9e013
update for merge changes
breznak May 3, 2019
9cba16e
TM: add check that extra Winners are subset of extra active
breznak May 3, 2019
a1dac2e
tiny cast
breznak May 3, 2019
047f0e4
Merge branch 'master_community' into tm_anomaly
breznak May 3, 2019
df42923
TM anomaly: skip case when extra_ external inputs are used
breznak May 3, 2019
c53a255
TM::getAnomalyScore() fix
breznak May 3, 2019
8a05797
fix typo
breznak May 3, 2019
d7cae2b
Merge branch 'master_community' into tm_anomaly
breznak May 5, 2019
759cf29
TM.anomaly add python binding
breznak May 5, 2019
5f8bd08
TM: fix operator==, !=, add test
breznak May 5, 2019
da7ccea
TM fix serialization for new anomaly
breznak May 5, 2019
01675a2
Hotgym: remove timer for anomaly
breznak May 5, 2019
7d172b1
TM add test for correct constructor used
breznak May 5, 2019
e73b54b
TM: activateDendrites now uses SDR
breznak May 5, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion API_CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,12 @@ longer accept a synapse permanence threshold argument. PR #305

* SDRClassifier class is replaced by `Classifier` and `Predictor` classes.

* Anomaly class removed as obsolete, use `TM.anomaly` which is simpler to use, and `MovingAverage` when you need to emulate
running averages. Internaly the code still uses `computeRawAnomalyScore()` but there's no need to call it directly. `AnomalyLikelihood`
is still available and can be used in addition to TM.getAnomalyScore(). PR #406

* TemporalMemory::getPredictiveCells() now returns a SDR. This ensures more convenient API and that the SDR object has correct
dimensions matching TM. use TM.getPredictiveCells().getSparse() to obtain the sparse vector as before.
dimensions matching TM. use TM.getPredictiveCells().getSparse() to obtain the sparse vector as before. PR #437, #442

* TemporalMemory `compute()` and `activateCells()` now use only SDR variants, old overloads with C-style arrays removed. Bindings and
tests also updated.
3 changes: 3 additions & 0 deletions bindings/py/cpp_src/bindings/algorithms/py_TemporalMemory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,9 @@ using namespace nupic::algorithms::connections;

py_HTM.def_property_readonly("extra", [](const HTM_t &self) { return self.extra; } );

py_HTM.def_property_readonly("anomaly", [](const HTM_t &self) { return self.anomaly; },
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TM.anomaly py binding

"Anomaly score updated with each TM::compute() call. "
);
}

} // namespace nupic_ext
32 changes: 12 additions & 20 deletions src/examples/hotgym/HelloSPTP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@

#include "HelloSPTP.hpp"

#include "nupic/algorithms/Anomaly.hpp"
#include "nupic/algorithms/TemporalMemory.hpp"
#include "nupic/algorithms/SpatialPooler.hpp"
#include "nupic/encoders/RandomDistributedScalarEncoder.hpp"
#include "nupic/algorithms/AnomalyLikelihood.hpp"

#include "nupic/types/Sdr.hpp"
#include "nupic/utils/Random.hpp"
Expand All @@ -44,8 +44,7 @@ using Encoder = nupic::encoders::RandomDistributedScalarEncoder;
using EncoderParameters = nupic::encoders::RDSE_Parameters;
using nupic::algorithms::spatial_pooler::SpatialPooler;
using TM = nupic::algorithms::temporal_memory::TemporalMemory;
using nupic::algorithms::anomaly::Anomaly;
using nupic::algorithms::anomaly::AnomalyMode;
using nupic::algorithms::anomaly::AnomalyLikelihood;


// work-load
Expand All @@ -63,7 +62,7 @@ Real64 BenchmarkHotgym::run(UInt EPOCHS, bool useSPlocal, bool useSPglobal, bool
std::cout << "EPOCHS = " << EPOCHS << std::endl;


// initialize SP, TM, Anomaly, AnomalyLikelihood
// initialize SP, TM, AnomalyLikelihood
tInit.start();
EncoderParameters encParams;
encParams.sparsity = 0.2f; //20% of the encoding are active bits (1's)
Expand All @@ -80,8 +79,7 @@ Real64 BenchmarkHotgym::run(UInt EPOCHS, bool useSPlocal, bool useSPglobal, bool

TM tm(vector<UInt>{COLS}, CELLS);

Anomaly an(5, AnomalyMode::PURE);
Anomaly anLikelihood(5, AnomalyMode::LIKELIHOOD);
AnomalyLikelihood anLikelihood;
tInit.stop();

// data for processing input
Expand All @@ -90,8 +88,7 @@ Real64 BenchmarkHotgym::run(UInt EPOCHS, bool useSPlocal, bool useSPglobal, bool
SDR outSPlocal(spLocal.getColumnDimensions()); //for SPlocal
SDR outSP(vector<UInt>{COLS});
SDR outTM(spGlobal.getColumnDimensions());
Real res = 0.0; //for anomaly:
SDR prevPred_(outTM.dimensions); //holds T-1 TM.predictive cells
Real an = 0.0f, anLikely = 0.0f; //for anomaly:

// Start a stopwatch timer
printf("starting: %d iterations.", EPOCHS);
Expand Down Expand Up @@ -125,7 +122,6 @@ Real64 BenchmarkHotgym::run(UInt EPOCHS, bool useSPlocal, bool useSPglobal, bool
tSPglob.stop();
}
outSP = outSPglobal; //toggle if local/global SP is used further down the chain (TM, Anomaly)
NTA_CHECK(outSP == outSPglobal);

// TM
if(useTM) {
Expand All @@ -138,22 +134,19 @@ Real64 BenchmarkHotgym::run(UInt EPOCHS, bool useSPlocal, bool useSPglobal, bool


//Anomaly (pure x likelihood)
tAn.start();
res = an.compute(outSP /*active*/, prevPred_ /*prev predicted*/);
tAn.stop();

an = tm.anomaly;
tAnLikelihood.start();
anLikelihood.compute(outSP /*active*/, prevPred_ /*prev predicted*/);
anLikelihood.anomalyProbability(an); //FIXME AnLikelihood is 0.0, probably not working correctly
tAnLikelihood.stop();

prevPred_ = outTM; //to be used as predicted T-1

// print
if (e == EPOCHS - 1) {
tAll.stop();

cout << "Epoch = " << e << endl;
cout << "Anomaly = " << res << endl;
cout << "Anomaly = " << an << endl;
cout << "Anomaly (Likelihood) = " << anLikely << endl;
cout << "SP (g)= " << outSP << endl;
cout << "SP (l)= " << outSPlocal <<endl;
cout << "TM= " << outTM << endl;
Expand All @@ -164,7 +157,6 @@ Real64 BenchmarkHotgym::run(UInt EPOCHS, bool useSPlocal, bool useSPglobal, bool
if(useSPlocal) cout << "SP (l):\t" << tSPloc.getElapsed()*1.0f << endl;
if(useSPglobal) cout << "SP (g):\t" << tSPglob.getElapsed() << endl;
if(useTM) cout << "TM:\t" << tTM.getElapsed() << endl;
cout << "AN:\t" << tAn.getElapsed() << endl;
cout << "AN:\t" << tAnLikelihood.getElapsed() << endl;

// check deterministic SP, TM output
Expand Down Expand Up @@ -192,16 +184,16 @@ Real64 BenchmarkHotgym::run(UInt EPOCHS, bool useSPlocal, bool useSPglobal, bool
};
goldTM.setSparse(deterministicTM);

const float goldAn = 0.920001f;
const float goldAn = 0.8f;

if(EPOCHS == 5000) { //these hand-written values are only valid for EPOCHS = 5000 (default), but not for debug and custom runs.
NTA_CHECK(input == goldEnc) << "Deterministic output of Encoder failed!\n" << input << "should be:\n" << goldEnc;
NTA_CHECK(outSPglobal == goldSP) << "Deterministic output of SP (g) failed!\n" << outSP << "should be:\n" << goldSP;
NTA_CHECK(outSPlocal == goldSPlocal) << "Deterministic output of SP (l) failed!\n" << outSPlocal << "should be:\n" << goldSPlocal;
#ifndef _MSC_VER //FIXME deterministic checks fail on Windows
NTA_CHECK(outTM == goldTM) << "Deterministic output of TM failed!\n" << outTM << "should be:\n" << goldTM;
NTA_CHECK(static_cast<UInt>(res *10000) == static_cast<UInt>(goldAn *10000)) //compare to 4 decimal places
<< "Deterministic output of Anomaly failed! " << res << "should be: " << goldAn;
NTA_CHECK(static_cast<UInt>(an *10000.0f) == static_cast<UInt>(goldAn *10000.0f)) //compare to 4 decimal places
<< "Deterministic output of Anomaly failed! " << an << "should be: " << goldAn;
#endif
}

Expand Down
4 changes: 1 addition & 3 deletions src/examples/hotgym/HelloSPTP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ class BenchmarkHotgym {
);

//timers
Timer tInit, tAll, tRng, tEnc, tSPloc, tSPglob, tTM,
tAn, tAnLikelihood;

Timer tInit, tAll, tRng, tEnc, tSPloc, tSPglob, tTM, tAnLikelihood;
};

} //-ns
Expand Down
85 changes: 2 additions & 83 deletions src/nupic/algorithms/Anomaly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,8 @@
* ---------------------------------------------------------------------
*/

#include <algorithm>
#include <iterator>
#include <numeric>
#include <set>
#include <vector>

#include "nupic/algorithms/Anomaly.hpp"
#include "nupic/utils/Log.hpp"
#include "nupic/types/Sdr.hpp"

using namespace std;
using namespace nupic;
Expand All @@ -42,92 +35,18 @@ namespace anomaly {
Real computeRawAnomalyScore(const SDR& active,
const SDR& predicted) {

NTA_ASSERT(active.dimensions == predicted.dimensions);

// Return 0 if no active columns are present
if (active.getSum() == 0) {
return 0.0f;
}

NTA_CHECK(active.dimensions == predicted.dimensions);

// Calculate and return percent of active columns that were not predicted.
SDR both(active.dimensions);
both.intersection(active, predicted);

return (active.getSum() - both.getSum()) / Real(active.getSum());
}

Real computeRawAnomalyScore(vector<UInt>& active,
vector<UInt>& predicted)
Copy link
Collaborator

@ctrl-z-9000-times ctrl-z-9000-times May 4, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we keep this overload?
This is where I keep my notes about how the SDR class should be doing set intersections.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is where I keep my notes about how the SDR class should be doing set intersections.

We could keep it,
or keep the code just as a commet, if you're not actively developing on that?
And ideally move the comment to SDR.intersection() ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I we can drop this method, but the rest of my criticism stands.

  • Friend classes are confusing and usually not necessary.
  • This doesn't include anomaly likelihood.
  • External predictive inputs don't work? I read through the code and it looks like they should just work, if you remove the checks that disable it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of removing the anomaly class and adding a different class, just reuse the existing anomaly class.

I thought you wanted me to get rid of the old Anomaly class and replace it with as simple as possibleimplementation in TM (?), which I ended up liking.

  1. I'm OK to revive the old Anomaly class, with a few changes *).
  2. Or I can just move the code TMAnomaly to Anomaly.hpp and be done with it.
    Which of those would you prefer?

Friend classes are confusing and usually not necessary.

I'll avoid 'friend access' when moving to a separate new/old file.

This doesn't include anomaly likelihood.

Yes, and it is intended. And about other refactoring in Anomaly class *):

  • I've implemented Anomaly class in the past to simplify various options with anomaly (thresholds, likelihood, moving average,...)
  • now with later usage experience, I don;t think it's a good design, and as those features can be implemented as "one liners" with current code, I don't think it should be provided with anomaly class. "Let TM.getAnomalyScore() be the simple raw anomaly" (#A), just conveniently computed. And let the user do what they need later with it.
    • thereshold: simple if(score > XXX) return 1 else return 0;
    • likelihood:
      • (probably even does not truly work)
      • in Anomaly had a FIXME note that it's not truly configurable. And should be separated.
      • I could use the approach with abstract class AbstractAnomaly::compute(SDR, SDR), but it's complicating things, see argument #A
      • AnomalyLikelihood is not even a true anomaly (computed from 2 SDRs), but a likelihood of anomalies, thus computed AFTER and from anomaly score. So score = TM.getAnomalyScore(); Likelihood::anomalyProbability(score, timestep);
    • moving average: again, simple MovingAverage ma(5); ma.add(score); ma.get();

TL;DR: the proper configuration and ordering is too complicated in a wrapper Anomaly class, while relatively easy hand-tailored by user (with tools we provide).

External predictive inputs don't work? I read through the code and it looks like they should just work, if you remove the checks that disable it.

Externals break it in the way the they add "cell indices out of scope of the current TM" (idx in <numberOfCells() , numOfCells + extra>).
See for yourself in SDR::setSparseInplace(), you must use Debug build to trigger, that's why it's failing only on the OSX CI. I'm proposing to proceed as is, and discuss the fixes on external inputs in a separate issue or #442

Copy link
Collaborator

@ctrl-z-9000-times ctrl-z-9000-times May 5, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would you prefer?

My goal is to have convenient way to print out everything interesting about the TM to a human readable string, and from it to determine if the TM is working. I see the anomaly metric as a diagnostic tool.

  • I want to know the mean & standard deviation of the anomaly. The anomaly likelihood also uses this info.
  • It should be enabled by default.

The proper configuration and ordering is too complicated.

Agreed,

  • The user should be responsible for discarding anomaly readings when they haven't finished training the network.
  • The user should be responsible for applying the threshold.
  • I'm skeptical that the WEIGHTED mode can outperform the likelyhood mode. I don't understand the reasoning behind it, and it's not mentioned in the published literature. Maybe we could drop this too.
  • AnomalyLikelihood needs 1 parameter to do what it does, and it has 4 or 5.

{
// Don't divide by zero. Return 0 if no active columns are present.
if (active.size() == 0) {
return 0.0f;
}

vector<UInt> correctPredictions;
sort( active.begin(), active.end());
sort( predicted.begin(), predicted.end());
set_intersection(active.begin(), active.end(),
predicted.begin(), predicted.end(),
back_inserter( correctPredictions ));

return (Real) (active.size() - correctPredictions.size()) / active.size();
}

}}} // End namespace

Anomaly::Anomaly(UInt slidingWindowSize, AnomalyMode mode, Real binaryAnomalyThreshold)
: binaryThreshold_(binaryAnomalyThreshold)
{
NTA_CHECK(binaryAnomalyThreshold >= 0 && binaryAnomalyThreshold <= 1) << "binaryAnomalyThreshold must be within [0.0,1.0]";
mode_ = mode;
if (slidingWindowSize > 0) {
movingAverage_.reset(new nupic::util::MovingAverage(slidingWindowSize));
}
}


Real Anomaly::compute(const SDR& active, const SDR& predicted, int timestamp)
{ return compute(active.getSparse(), predicted.getSparse(), timestamp); }

Real Anomaly::compute(vector<UInt>& active, vector<UInt>& predicted, int timestamp)
{
Real anomalyScore = computeRawAnomalyScore(active, predicted);
Real likelihood = 0.5;
Real score = anomalyScore;
switch(mode_)
{
case AnomalyMode::PURE:
score = anomalyScore;
break;
case AnomalyMode::LIKELIHOOD:
likelihood = likelihood_.anomalyProbability(anomalyScore, timestamp);
score = 1 - likelihood;
break;
case AnomalyMode::WEIGHTED:
likelihood = likelihood_.anomalyProbability(anomalyScore, timestamp);
score = anomalyScore * (1 - likelihood);
break;
}

if (movingAverage_) {
score = movingAverage_->compute(score);
}

if (binaryThreshold_) {
score = (score >= binaryThreshold_) ? 1.0f : 0.0f;
}

return score;
}

bool Anomaly::operator==(const Anomaly &a) const {
if (mode_ != a.mode_) return false;
if (binaryThreshold_ != a.binaryThreshold_) return false;
if (movingAverage_ != nullptr && a.movingAverage_ == nullptr) return false;
if (movingAverage_ == nullptr && a.movingAverage_ != nullptr) return false;
if (movingAverage_ != nullptr && *(movingAverage_.get()) != *(a.movingAverage_.get())) return false;
if (likelihood_ != a.likelihood_) return false;
return true;
}

105 changes: 6 additions & 99 deletions src/nupic/algorithms/Anomaly.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,7 @@
#ifndef NUPIC_ALGORITHMS_ANOMALY_HPP
#define NUPIC_ALGORITHMS_ANOMALY_HPP

#include <memory> // Needed for smart pointer templates
#include <vector>
#include <nupic/types/Serializable.hpp>
#include <nupic/algorithms/AnomalyLikelihood.hpp>
#include <nupic/types/Types.hpp>
#include <nupic/utils/MovingAverage.hpp> // Needed for for smart pointer templates
#include <nupic/types/Sdr.hpp> // sdr::SDR

namespace nupic {
Expand All @@ -40,104 +35,16 @@ namespace anomaly {
* Computes the raw anomaly score.
*
* The raw anomaly score is the fraction of active columns not predicted.
* Do not use these methods directly, these are for testing and internal implementation.
* Use `TM.anomaly` (+AnomalyLikelihood, MovingAverage for more specific needs).
*
* @param activeColumns: array of active column indices
* @param prevPredictedColumns: array of columns indices predicted in
* prev step
* @param activeColumns: SDR with active columns (not cells) from current step (T)
* @param prevPredictedColumns: SDR of predictive columns indices from prev step (T-1)
* @return anomaly score 0..1 (Real32)
*/
Real32 computeRawAnomalyScore(std::vector<UInt> &active,
std::vector<UInt> &predicted);
Real32 computeRawAnomalyScore(const sdr::SDR& active,
const sdr::SDR& predicted);

Real32 computeRawAnomalyScore(const sdr::SDR& active, const sdr::SDR& predicted);

enum class AnomalyMode { PURE, LIKELIHOOD, WEIGHTED };

class Anomaly : public Serializable {
public:
/**
* Utility class for generating anomaly scores in different ways.
*
* Supported modes:
* PURE - the raw anomaly score as computed by computeRawAnomalyScore
* LIKELIHOOD - uses the AnomalyLikelihood class on top of the raw
* anomaly scores (not implemented in C++)
* WEIGHTED - multiplies the likelihood result with the raw anomaly
* score that was used to generate the likelihood (not
* implemented in C++)
*
* @param slidingWindowSize (optional) - how many elements are
* summed up; enables moving average on final anomaly score;
* int >= 0
* @param mode (optional) - (enum) how to compute anomaly;
* possible values are AnomalyMode::
* - PURE - the default, how much anomal the value is;
* Real32 0..1 where 1=totally unexpected
* - LIKELIHOOD - uses the anomaly_likelihood code;
* models probability of receiving this value and
* anomalyScore
* - WEIGHTED - "pure" anomaly weighted by "likelihood"
* (anomaly * likelihood)
* @param binaryAnomalyThreshold (optional) - if set [0,1] anomaly
* score will be discretized to 1/0
* (1 iff >= binaryAnomalyThreshold). The transformation is
* applied after moving average is computed.
*/
Anomaly(UInt slidingWindowSize = 0, AnomalyMode mode = AnomalyMode::PURE,
Real32 binaryAnomalyThreshold = 0);

/**
* Compute the anomaly score as the percent of active columns not
* predicted.
*
* @param active: array of active column indices
* @param predicted: array of columns indices predicted in prev step (T-1)
* @param timestamp: (optional) date timestamp when the sample occured
* (used in anomaly-likelihood), -1 defaults to using iteration step
* @return the computed anomaly score; Real32 0..1
*/
Real compute(std::vector<UInt> &active,
std::vector<UInt> &predicted,
int timestamp = -1);

Real compute(const sdr::SDR &active,
const sdr::SDR &predicted,
int timestamp = -1);


CerealAdapter;

template<class Archive>
void save_ar(Archive & ar) const {
std::string name("Anomaly");
ar(CEREAL_NVP(name),
CEREAL_NVP(mode_),
CEREAL_NVP(binaryThreshold_),
CEREAL_NVP(likelihood_),
CEREAL_NVP(movingAverage_));
}
template<class Archive>
void load_ar(Archive & ar) {
std::string name;
ar(CEREAL_NVP(name),
CEREAL_NVP(mode_),
CEREAL_NVP(binaryThreshold_));
ar(CEREAL_NVP(likelihood_));
ar(CEREAL_NVP(movingAverage_));
}



bool operator==(const Anomaly &a) const;
inline bool operator!=(const Anomaly &a) const
{ return not ((*this) == a); }

private:
AnomalyMode mode_;
Real32 binaryThreshold_;
std::unique_ptr<nupic::util::MovingAverage> movingAverage_;
AnomalyLikelihood likelihood_; //TODO which params/how pass them to constructor?
};
}}} //end-ns

#endif // NUPIC_ALGORITHMS_ANOMALY_HPP
3 changes: 2 additions & 1 deletion src/nupic/algorithms/AnomalyLikelihood.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,13 @@ There are 3 ways to use the code:
- using the raw individual functions.
**/

using namespace std;

namespace nupic {
namespace algorithms {
namespace anomaly {

using namespace std;

struct DistributionParams {
DistributionParams(std::string name, Real mean, Real variance, Real stdev) :
name(name),mean(mean), variance(variance), stdev(stdev) {}
Expand Down
Loading