void NaiveBayesClassifier<MatType>::Classify(const MatType& data, arma::Row<size_t>& results) { // Check that the number of features in the test data is same as in the // training data. Log::Assert(data.n_rows == means.n_rows); arma::vec probs = arma::log(probabilities); arma::mat invVar = 1.0 / variances; arma::mat testProbs = arma::repmat(probs.t(), data.n_cols, 1); results.set_size(data.n_cols); // No need to fill with anything yet. Log::Info << "Running Naive Bayes classifier on " << data.n_cols << " data points with " << data.n_rows << " features each." << std::endl; // Calculate the joint probability for each of the data points for each of the // means.n_cols. // Loop over every class. for (size_t i = 0; i < means.n_cols; i++) { // This is an adaptation of gmm::phi() for the case where the covariance is // a diagonal matrix. arma::mat diffs = data - arma::repmat(means.col(i), 1, data.n_cols); arma::mat rhs = -0.5 * arma::diagmat(invVar.col(i)) * diffs; arma::vec exponents(diffs.n_cols); for (size_t j = 0; j < diffs.n_cols; ++j) // log(exp(value)) == value exponents(j) = arma::accu(diffs.col(j) % rhs.unsafe_col(j)); // Calculate probability as sum of logarithm to decrease floating point // errors. testProbs.col(i) += (data.n_rows / -2.0 * log(2 * M_PI) - 0.5 * log(arma::det(arma::diagmat(variances.col(i)))) + exponents); } // Now calculate the label. for (size_t i = 0; i < data.n_cols; ++i) { // Find the index of the class with maximum probability for this point. arma::uword maxIndex = 0; arma::vec pointProbs = testProbs.row(i).t(); pointProbs.max(maxIndex); results[i] = maxIndex; } return; }
/** * Calculates the multivariate Gaussian probability density function for each * data point (column) in the given matrix, with respect to the given mean and * variance. * * @param x List of observations. * @param mean Mean of multivariate Gaussian. * @param cov Covariance of multivariate Gaussian. * @param probabilities Output probabilities for each input observation. */ inline void phi(const arma::mat& x, const arma::vec& mean, const arma::mat& cov, arma::vec& probabilities) { // Column i of 'diffs' is the difference between x.col(i) and the mean. arma::mat diffs = x - (mean * arma::ones<arma::rowvec>(x.n_cols)); // Now, we only want to calculate the diagonal elements of (diffs' * cov^-1 * // diffs). We just don't need any of the other elements. We can calculate // the right hand part of the equation (instead of the left side) so that // later we are referencing columns, not rows -- that is faster. arma::mat rhs = -0.5 * inv(cov) * diffs; arma::vec exponents(diffs.n_cols); // We will now fill this. for (size_t i = 0; i < diffs.n_cols; i++) exponents(i) = exp(accu(diffs.unsafe_col(i) % rhs.unsafe_col(i))); probabilities = pow(2 * M_PI, (double) mean.n_elem / -2.0) * pow(det(cov), -0.5) * exponents; }
Eigen::MatrixXd build_exponents(size_t max_exponent,size_t xdimensions) { std::vector<size_t> current_exponent_scratch(xdimensions); std::vector<std::vector<size_t>> output_list; size_t maxtop=1; for(size_t k=0;k<xdimensions;k++) { maxtop*=max_exponent; } for(size_t ei=0;ei<maxtop;ei++) { current_exponent_scratch.resize(xdimensions,0); size_t cei=ei; size_t total=0; for(size_t k=0;k<xdimensions;k++) { size_t remainder=cei % max_exponent; current_exponent_scratch[k]=remainder; total+=remainder; cei/=max_exponent; if(cei == 0) break; } if(total <= max_exponent) { output_list.emplace_back(current_exponent_scratch); } } Eigen::MatrixXd exponents(xdimensions,output_list.size()); //exponent at dimension R for position col C for(size_t c=0;c<exponents.cols();c++) { const vector<double> srcrows&=output_list[c]; for(size_t r=0;r<exponents.rows();r++) { exponents(r,c)=srcrows[r]; } } return exponents; }
void SimultaneousMultiplication(Iterator result, const AbstractGroup<Element> &group, const Element &base, ConstIterator expBegin, ConstIterator expEnd) { unsigned int expCount = std::distance(expBegin, expEnd); std::vector<WindowSlider<Element> > exponents(expCount); unsigned int i; bool notDone = false; for (i=0; i<expCount; i++) notDone = exponents[i].FindFirstWindow(group, *expBegin++) || notDone; unsigned int expBitPosition = 0; Element g = base; while (notDone) { notDone = false; for (i=0; i<expCount; i++) { if (expBitPosition < exponents[i].expLen && expBitPosition == exponents[i].windowBegin) { Element &bucket = exponents[i].buckets[exponents[i].nextBucket]; group.Accumulate(bucket, g); exponents[i].FindNextWindow(); } notDone = notDone || exponents[i].windowBegin < exponents[i].expLen; } if (notDone) { g = group.Double(g); expBitPosition++; } } for (i=0; i<expCount; i++) { Element &r = *result++; std::vector<Element> &buckets = exponents[i].buckets; r = buckets[buckets.size()-1]; if (buckets.size() > 1) { for (int j = buckets.size()-2; j >= 1; j--) { group.Accumulate(buckets[j], buckets[j+1]); group.Accumulate(r, buckets[j]); } group.Accumulate(buckets[0], buckets[1]); r = group.Add(group.Double(r), buckets[0]); } } }