Armadillo, finding max index in each column
Asked Answered
C

3

5

I'm searching for a way to find the index corresponding to the maximum of each column. My goal is to avoid loops and find a Matlabic solution using vectorized armadillo functions.

This can easily be done in Matlab with the following command : [~, maxIndices] = max(A);

In armadillo you have the member function : A.max( row_of_max_val, col_of_max_val); that give the location of the maximum in the whole matrix.

And the standalone function vec M = max(A); that outputs the maximum values of each column but not their indices.

But none of them is doing the trick.

Having columns maximum's indices could be used to write numerous algorithms in a more vectorized way. For example, it could be used in a Viterbi Decoding, or in a k-means clustering.

Obviously, this question can be generalized considering minimums instead of maximums and rows instead of columns.

Is someone thinking of an alternative solution ?

Best.

Clyve answered 4/11, 2015 at 8:50 Comment(1)
side note: Armadillo already has k-means clustering. see the gmm_diag class. just interpret the gaussian means as centroids.Convincing
L
5

I typically go with the submatrix views. Something along these lines :

using idx_type = arma::uword;
using namespace std;
using namespace arma;

template<typename T>
vector<idx_type>
colwise_max_idx(const Mat<T>& A) {
    vector<idx_type> res;
    for (idx_type i = 0; i != A.n_cols; ++i) {
        idx_type row_idx;
        A.col(i).max(row_idx);
        res.push_back(row_idx);
    }
    return res;
}
Lazare answered 4/11, 2015 at 10:11 Comment(6)
should this be A.col(i).eval().max(row_dx) ? the subview doesn't currently have a.max() member functionConvincing
@Convincing It does. Tested with arma-6.200.2.Lazare
Thanks for your answer. I just forgot to mention i was trying to avoid loops and go for a "Matlab" style vectorized solution.Clyve
@Lazare - My bad -- you're right. The subview class is derived from Base, which has .min() and .max() defined.Convincing
@Clyve I don't understand. Matlab vectorized functions perform loops under the hood anyway. Vectorising there gives you enormous speed-up because the loops get done in the underlying compiled-languages (FORTRAN or C). The story, however, is very different in C++, which is not an interpreted language like Matlab.Lazare
Yes. You are right, my question was mainly a question of style. But i'm also wondering if using armadillo built in functions instead of my own loops could benefit from advanced optimizations techniques done by the library (i've heard about delayed operations...).Clyve
N
3

Armadillo now has, .index_max() and .index_min() methods to find these indices, as of version 7.2.

Neap answered 11/5, 2017 at 12:39 Comment(0)
C
1

A not perfect answer would be something like :

uvec indices = find((A.each_row()-max(A)) == 0);

Problems :

  1. Multiple indices can be returned for a unique column in case the max element is present more than one time.
  2. Indices are given relatively to the first element of the matrix and not the first element of each column.
Clyve answered 4/11, 2015 at 12:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.