Generalized Scores for Multi-Class Imbalanced Classification

### Describe the workflow you want to enable

We wish to extend Matthew coefficient and F1 to multi- class problems.

### Describe your proposed solution

We already generated a pypi package
https://pypi.org/project/matthew-Coef-MultiClass/  which supports this. 

We created a unique function that follows the signature pf metrics._classification.py  current solution for the binary case
I will be glad to add this solution 

### Describe alternatives you've considered, if relevant

The following functions performs the required  (as an alternative to use our own package):

```python
class AVERAG_TYPE(Enum):
    MATTHEW_GEN = 2
    F1_GEN = 3

def generalized_matthew(y_true,y_pred,labels,ave_type=AVERAG_TYPE.MATTHEW_GEN.value):

    # A utitliy function which normalizes the confusion and perfroms the relevant average
    def norm_confusion_mat(conf_mat, average, dimension_size):
        m1 = conf_mat / np.sum(conf_mat, axis=1)
        m2 = conf_mat / np.sum(conf_mat, axis=0)

        return [[average([m1[i, j], m2[j][i]])
                 for i in range(dimension_size)] for j in range(dimension_size)]

    # A utitliy function that perfroms the generaized score of F1 . it calculates the hamonic average
    # over the trace of the normalized confusion matrix
    def gen_f1_scalar_op(h_conf_mat):
        l_mat = len(h_conf_mat)
        return st.mstats.hmean([h_conf_mat[i][i] for i in range(l_mat)])

    dimension_size =len(labels)
    conf_mat=confusion_matrix(y_true=y_true,y_pred=y_pred ,labels=labels)
    if ave_type == AVERAG_TYPE.MATTHEW_GEN.value:
        av_func =st.mstats.gmean
        scalar_op =np.linalg.det
    elif ave_type ==AVERAG_TYPE.F1_GEN.value:
        av_func = st.mstats.hmean
        scalar_op =gen_f1_scalar_op

    G_mat= norm_confusion_mat(conf_mat, av_func, dimension_size)
    return scalar_op(G_mat)
```


### Additional context

I wish to stress that there is a sound mathematical work behind this generalization which is soon to be published . The paper will be gladly provided by either myself or Uri Itai

COMMENT:
We can add to _classification.py
from scipy import stats as st
from enum import Enum
and then the function becomes similar to the current (binary one)

class AVERAG_TYPE(Enum):
    MATTHEW_GEN = 2
    F1_GEN = 3

def generalized_matthew(y_true, y_pred,ave_type=AVERAG_TYPE.MATTHEW_GEN.value,sample_weight=None):
    y_type, y_true, y_pred = _check_targets(y_true, y_pred)
    check_consistent_length(y_true, y_pred, sample_weight)
    if y_type not in {"binary", "multiclass"}:
        raise ValueError("%s is not supported" % y_type)

    lb = LabelEncoder()
    lb.fit(np.hstack([y_true, y_pred]))
    y_true = lb.transform(y_true)
    y_pred = lb.transform(y_pred)

    C = confusion_matrix(y_true, y_pred, sample_weight=sample_weight)
    dimension_size = C.shape[0]

     # A utitliy function which normalizes the confusion and perfroms the relevant average
    def norm_confusion_mat(conf_mat, average, dimension_size):
        m1 = C / C.sum( axis=1)
        m2 = C / C.sum( axis=0)

        return [[average([m1[i, j], m2[j][i]])
                 for i in range(dimension_size)] for j in range(dimension_size)]

    # A utitliy function that perfroms the generaized score of F1 . it calculates the hamonic average
    # over the trace of the normalized confusion matrix
    def gen_f1_scalar_op(h_conf_mat):
        l_mat = len(h_conf_mat)
        return st.mstats.hmean([h_conf_mat[i][i] for i in range(l_mat)])

    dimension_size =3
    # c=confusion_matrix(y_true=y_true,y_pred=y_pred ,labels=labels)
    av_func =st.mstats.gmean
    scalar_op =np.linalg.det
    if ave_type ==AVERAG_TYPE.F1_GEN.value:
        av_func = st.mstats.hmean
        scalar_op =gen_f1_scalar_op

    G_mat= norm_confusion_mat(C, av_func, dimension_size)
    return scalar_op(G_mat)

Labels: New Feature, Needs Decision - Include Feature