// Predict the rating for a group of user/item combinations. void CF::Predict(const arma::Mat<size_t>& combinations, arma::vec& predictions) const { // First, for nearest neighbor search, stretch the H matrix. arma::mat l = arma::chol(w.t() * w); arma::mat stretchedH = l * h; // Due to the Armadillo API, l is L^T. // Now, we must determine those query indices we need to find the nearest // neighbors for. This is easiest if we just sort the combinations matrix. arma::Mat<size_t> sortedCombinations(combinations.n_rows, combinations.n_cols); arma::uvec ordering = arma::sort_index(combinations.row(0).t()); for (size_t i = 0; i < ordering.n_elem; ++i) sortedCombinations.col(i) = combinations.col(ordering[i]); // Now, we have to get the list of unique users we will be searching for. arma::Col<size_t> users = arma::unique(combinations.row(0).t()); // Assemble our query matrix from the stretchedH matrix. arma::mat queries(stretchedH.n_rows, users.n_elem); for (size_t i = 0; i < queries.n_cols; ++i) queries.col(i) = stretchedH.col(users[i]); // Now calculate the neighborhood of these users. neighbor::KNN a(stretchedH); arma::mat distances; arma::Mat<size_t> neighborhood; a.Search(queries, numUsersForSimilarity, neighborhood, distances); // Now that we have the neighborhoods we need, calculate the predictions. predictions.set_size(combinations.n_cols); size_t user = 0; // Cumulative user count, because we are doing it in order. for (size_t i = 0; i < sortedCombinations.n_cols; ++i) { // Could this be made faster by calculating dot products for multiple items // at once? double rating = 0.0; // Map the combination's user to the user ID used for kNN. while (users[user] < sortedCombinations(0, i)) ++user; for (size_t j = 0; j < neighborhood.n_rows; ++j) rating += arma::as_scalar(w.row(sortedCombinations(1, i)) * h.col(neighborhood(j, user))); rating /= neighborhood.n_rows; predictions(ordering[i]) = rating; } }
std::vector<double> extract_row_vector(const arma::Mat<double>& data, long index) { if (index<0 || index >= long(data.n_rows)) throw std::range_error(join("Index out of range: ", index)); const arma::Row<double> row(data.row(index)); const double* memptr = row.memptr(); std::vector<double> result(memptr, memptr + row.n_elem); return std::move(result); }
//This function is specific to a single problem void calculateDependentVariables(const arma::Mat<std::complex<double> >& myOffsets, const arma::Col<std::complex<double> >& myCurrentGuess, arma::Col<std::complex<double> >& targetsCalculated) { //Evaluate a dependent variable for each iteration //The arma::Col allows this to be expressed as a vector operation for(int i = 0; i < NUMDIMENSIONS; i++) { targetsCalculated[i] = arma::sum(pow(myCurrentGuess.subvec(0,1) - myOffsets.row(i).subvec(0,1).t(),2.0)); targetsCalculated[i] = targetsCalculated[i] + myCurrentGuess[2]*pow(-1.0, i) - myOffsets.row(i)[2]; //std::cout << targetsCalculated[i] << std::endl; } //std::cout << "model evaluated *************************" << std::endl; //std::cout << targetsCalculated << std::endl; //std::cout << myOffsets << std::endl; }
/** * Given a Reber string, return a Reber string with all reachable next symbols. * * @param transitions The Reber transistion matrix. * @param reber The Reber string used to generate all reachable next symbols. * @param nextReber All reachable next symbols. */ void GenerateNextReber(const arma::Mat<char>& transitions, const std::string& reber, std::string& nextReber) { size_t idx = 0; for (size_t grammer = 1; grammer < reber.length(); grammer++) { const int grammerIdx = arma::as_scalar(arma::find( transitions.row(idx) == reber[grammer], 1, "first")); idx = arma::as_scalar(transitions.submat(idx, grammerIdx + 2, idx, grammerIdx + 2)) - '0'; } nextReber = arma::as_scalar(transitions.submat(idx, 0, idx, 0)); nextReber += arma::as_scalar(transitions.submat(idx, 1, idx, 1)); }