scikit-learn/sklearn/utils/multiclass.py

136 lines
3.8 KiB
Python

# Author: Arnaud Joly
#
# License: BSD 3 clause
"""
Multi-class / multi-label utility function
==========================================
"""
from collections import Sequence
from itertools import chain
import numpy as np
from ..externals.six import string_types
def unique_labels(*lists_of_labels):
"""Extract an ordered array of unique labels
Parameters
----------
lists_of_labels : list of labels,
The supported "list of labels" are:
- a list / tuple / numpy array of int
- a list of lists / tuples of int;
- a binary indicator matrix (2D numpy array)
Returns
-------
out : numpy array of shape [n_unique_labels]
An ordered array of unique labels.
Examples
--------
>>> from sklearn.utils.multiclass import unique_labels
>>> unique_labels([3, 5, 5, 5, 7, 7])
array([3, 5, 7])
>>> unique_labels([1, 2, 3, 4], [2, 2, 3, 4])
array([1, 2, 3, 4])
>>> unique_labels([1, 2, 10], [5, 11])
array([ 1, 2, 5, 10, 11])
>>> unique_labels(np.array([[0.0, 1.0], [1.0, 1.0]]), np.zeros((2, 2)))
array([0, 1])
>>> unique_labels([(1, 2), (3,)], [(1, 2), tuple()])
array([1, 2, 3])
"""
def _unique_labels(y):
classes = None
if is_multilabel(y):
if is_label_indicator_matrix(y):
classes = np.arange(y.shape[1])
else:
classes = np.array(sorted(set(chain(*y))))
else:
classes = np.unique(y)
return classes
if not lists_of_labels:
raise ValueError('No list of labels has been passed.')
return np.unique(np.hstack(_unique_labels(y) for y in lists_of_labels))
def is_label_indicator_matrix(y):
""" Check if ``y`` is in the label indicator matrix format (multilabel).
Parameters
----------
y : numpy array of shape [n_samples] or sequence of sequences
Target values. In the multilabel case the nested sequences can
have variable lengths.
Returns
-------
out : bool,
Return ``True``, if ``y`` is in a label indicator matrix format,
else ``False``.
Examples
--------
>>> import numpy as np
>>> from sklearn.utils.multiclass import is_label_indicator_matrix
>>> is_label_indicator_matrix([0, 1, 0, 1])
False
>>> is_label_indicator_matrix([[1], [0, 2], []])
False
>>> is_label_indicator_matrix(np.array([[1, 0], [0, 0]]))
True
>>> is_label_indicator_matrix(np.array([[1], [0], [0]]))
False
>>> is_label_indicator_matrix(np.array([[1, 0, 0]]))
False
"""
return (hasattr(y, "shape") and len(y.shape) == 2 and y.shape[1] > 1 and
y.shape[0] > 1 and np.size(np.unique(y)) <= 2)
def is_multilabel(y):
""" Check if ``y`` is in a multilabel format.
Parameters
----------
y : numpy array of shape [n_samples] or sequence of sequences
Target values. In the multilabel case the nested sequences can
have variable lengths.
Returns
-------
out : bool,
Return ``True``, if ``y`` is in a multilabel format, else ```False``.
Examples
--------
>>> import numpy as np
>>> from sklearn.utils.multiclass import is_multilabel
>>> is_multilabel([0, 1, 0, 1])
False
>>> is_multilabel([[1], [0, 2], []])
True
>>> is_multilabel(np.array([[1, 0], [0, 0]]))
True
>>> is_multilabel(np.array([[1], [0], [0]]))
False
>>> is_multilabel(np.array([[1, 0, 0]]))
False
"""
# the explicit check for ndarray is for forward compatibility; future
# versions of Numpy might want to register ndarray as a Sequence
return (not isinstance(y[0], np.ndarray) and isinstance(y[0], Sequence) and
not isinstance(y[0], string_types) or is_label_indicator_matrix(y))