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_classifierspred (M,N)
: n_samples x n_classifiersP
: n_samples x n_classesWithout 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)