Search code examples
pythonnumpyscikit-learnnumpy-ndarrayarray-broadcasting

Mismatch of shapes when using advanced indexing


I am developing a custom classifier that acts like an ensemble, combining minor classifiers together and the output of the ensemble is actually a majority voting. One important thing to mention is that every classifier has a "weight" associated with it for each sample.

Here is the predict method:

def predict(self, X):        
    
    G = self._compute_g(X) # G comes from a softmax distribution
    pred = np.zeros( (len(self._estimators), X.shape[0]), dtype=int ) 
    
    for i, estimator in enumerate(self._estimators): #loop each minor classifier
        y_est = estimator.predict(X)    
        pred[i] = y_est

    pred = pred.T # Prediction matrix (samples x classifiers)
    C = len(self._classes) # number of classes of the dataset
    M, N = pred.shape

    row, col = np.indices((M,N))
    P3d = np.zeros(shape=(M,N,C))
    P3d[row, col, pred-1] = G
    P = P3d.sum(axis=1)
    return np.argmax(P, axis=1)

For the majority voting, i create a P matrix (samples x n_classes) that sums the classifier weights that voted in a given class. For instance: supposing we have 3 classifiers trying to predict sample k for a 3-class problem. Classifier weights are [0.3, 0.4, 0.6], and predictions are [1,1,2]. The k-th row of matrix P will be [0.7, 0.6, 0] and the output of the ensemble classifier will be 1.

The problem is that i am trying to use advanced indexing to build matrix P3d (used to build matrix P), and i'm getting the following error when trying to predict Iris dataset:

ValueError: shape mismatch: value array of shape (150,6) could not be broadcast to indexing result of shape (150,3)

This error comes from this line: P3d[row, col, pred-1] = G, but i have no clue what's causing this issue.

Shapes of matrices involved

  • G: n_samples x n_classifiers
  • pred (M,N): n_samples x n_classifiers
  • P: n_samples x n_classes
  • return of function (last line): n_samples x 1

Solution

  • Without seeing fully reproducible code, it's a bit hard to tell what G = self._compute_g(X) is doing. However, the returned value G seems to have shape (150, 6), not (150, 3) as expected. Hence you get the shape mismatch error.

    I would suggest some careful inspection of G to confirm that self._compute_g(X) is doing what you expect.

    As a side note, judicious use of assert to confirm the shape of various arrays can help catch many of these sort of errors. i.e. assert G.shape == (M, N)