PageRenderTime 42ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/sklearn/utils/tests/test_multiclass.py

https://gitlab.com/admin-github-cloud/scikit-learn
Python | 347 lines | 273 code | 50 blank | 24 comment | 28 complexity | a47ed4716fd1fcf86a5702abe1b4fbde MD5 | raw file
  1. from __future__ import division
  2. import numpy as np
  3. import scipy.sparse as sp
  4. from itertools import product
  5. from sklearn.externals.six.moves import xrange
  6. from sklearn.externals.six import iteritems
  7. from scipy.sparse import issparse
  8. from scipy.sparse import csc_matrix
  9. from scipy.sparse import csr_matrix
  10. from scipy.sparse import coo_matrix
  11. from scipy.sparse import dok_matrix
  12. from scipy.sparse import lil_matrix
  13. from sklearn.utils.testing import assert_array_equal
  14. from sklearn.utils.testing import assert_array_almost_equal
  15. from sklearn.utils.testing import assert_equal
  16. from sklearn.utils.testing import assert_true
  17. from sklearn.utils.testing import assert_false
  18. from sklearn.utils.testing import assert_raises
  19. from sklearn.utils.testing import assert_raises_regex
  20. from sklearn.utils.multiclass import unique_labels
  21. from sklearn.utils.multiclass import is_multilabel
  22. from sklearn.utils.multiclass import type_of_target
  23. from sklearn.utils.multiclass import class_distribution
  24. from sklearn.utils.multiclass import check_classification_targets
  25. class NotAnArray(object):
  26. """An object that is convertable to an array. This is useful to
  27. simulate a Pandas timeseries."""
  28. def __init__(self, data):
  29. self.data = data
  30. def __array__(self):
  31. return self.data
  32. EXAMPLES = {
  33. 'multilabel-indicator': [
  34. # valid when the data is formatted as sparse or dense, identified
  35. # by CSR format when the testing takes place
  36. csr_matrix(np.random.RandomState(42).randint(2, size=(10, 10))),
  37. csr_matrix(np.array([[0, 1], [1, 0]])),
  38. csr_matrix(np.array([[0, 1], [1, 0]], dtype=np.bool)),
  39. csr_matrix(np.array([[0, 1], [1, 0]], dtype=np.int8)),
  40. csr_matrix(np.array([[0, 1], [1, 0]], dtype=np.uint8)),
  41. csr_matrix(np.array([[0, 1], [1, 0]], dtype=np.float)),
  42. csr_matrix(np.array([[0, 1], [1, 0]], dtype=np.float32)),
  43. csr_matrix(np.array([[0, 0], [0, 0]])),
  44. csr_matrix(np.array([[0, 1]])),
  45. # Only valid when data is dense
  46. np.array([[-1, 1], [1, -1]]),
  47. np.array([[-3, 3], [3, -3]]),
  48. NotAnArray(np.array([[-3, 3], [3, -3]])),
  49. ],
  50. 'multiclass': [
  51. [1, 0, 2, 2, 1, 4, 2, 4, 4, 4],
  52. np.array([1, 0, 2]),
  53. np.array([1, 0, 2], dtype=np.int8),
  54. np.array([1, 0, 2], dtype=np.uint8),
  55. np.array([1, 0, 2], dtype=np.float),
  56. np.array([1, 0, 2], dtype=np.float32),
  57. np.array([[1], [0], [2]]),
  58. NotAnArray(np.array([1, 0, 2])),
  59. [0, 1, 2],
  60. ['a', 'b', 'c'],
  61. np.array([u'a', u'b', u'c']),
  62. np.array([u'a', u'b', u'c'], dtype=object),
  63. np.array(['a', 'b', 'c'], dtype=object),
  64. ],
  65. 'multiclass-multioutput': [
  66. np.array([[1, 0, 2, 2], [1, 4, 2, 4]]),
  67. np.array([[1, 0, 2, 2], [1, 4, 2, 4]], dtype=np.int8),
  68. np.array([[1, 0, 2, 2], [1, 4, 2, 4]], dtype=np.uint8),
  69. np.array([[1, 0, 2, 2], [1, 4, 2, 4]], dtype=np.float),
  70. np.array([[1, 0, 2, 2], [1, 4, 2, 4]], dtype=np.float32),
  71. np.array([['a', 'b'], ['c', 'd']]),
  72. np.array([[u'a', u'b'], [u'c', u'd']]),
  73. np.array([[u'a', u'b'], [u'c', u'd']], dtype=object),
  74. np.array([[1, 0, 2]]),
  75. NotAnArray(np.array([[1, 0, 2]])),
  76. ],
  77. 'binary': [
  78. [0, 1],
  79. [1, 1],
  80. [],
  81. [0],
  82. np.array([0, 1, 1, 1, 0, 0, 0, 1, 1, 1]),
  83. np.array([0, 1, 1, 1, 0, 0, 0, 1, 1, 1], dtype=np.bool),
  84. np.array([0, 1, 1, 1, 0, 0, 0, 1, 1, 1], dtype=np.int8),
  85. np.array([0, 1, 1, 1, 0, 0, 0, 1, 1, 1], dtype=np.uint8),
  86. np.array([0, 1, 1, 1, 0, 0, 0, 1, 1, 1], dtype=np.float),
  87. np.array([0, 1, 1, 1, 0, 0, 0, 1, 1, 1], dtype=np.float32),
  88. np.array([[0], [1]]),
  89. NotAnArray(np.array([[0], [1]])),
  90. [1, -1],
  91. [3, 5],
  92. ['a'],
  93. ['a', 'b'],
  94. ['abc', 'def'],
  95. np.array(['abc', 'def']),
  96. [u'a', u'b'],
  97. np.array(['abc', 'def'], dtype=object),
  98. ],
  99. 'continuous': [
  100. [1e-5],
  101. [0, .5],
  102. np.array([[0], [.5]]),
  103. np.array([[0], [.5]], dtype=np.float32),
  104. ],
  105. 'continuous-multioutput': [
  106. np.array([[0, .5], [.5, 0]]),
  107. np.array([[0, .5], [.5, 0]], dtype=np.float32),
  108. np.array([[0, .5]]),
  109. ],
  110. 'unknown': [
  111. [[]],
  112. [()],
  113. # sequence of sequences that weren't supported even before deprecation
  114. np.array([np.array([]), np.array([1, 2, 3])], dtype=object),
  115. [np.array([]), np.array([1, 2, 3])],
  116. [set([1, 2, 3]), set([1, 2])],
  117. [frozenset([1, 2, 3]), frozenset([1, 2])],
  118. # and also confusable as sequences of sequences
  119. [{0: 'a', 1: 'b'}, {0: 'a'}],
  120. # empty second dimension
  121. np.array([[], []]),
  122. # 3d
  123. np.array([[[0, 1], [2, 3]], [[4, 5], [6, 7]]]),
  124. ]
  125. }
  126. NON_ARRAY_LIKE_EXAMPLES = [
  127. set([1, 2, 3]),
  128. {0: 'a', 1: 'b'},
  129. {0: [5], 1: [5]},
  130. 'abc',
  131. frozenset([1, 2, 3]),
  132. None,
  133. ]
  134. MULTILABEL_SEQUENCES = [
  135. [[1], [2], [0, 1]],
  136. [(), (2), (0, 1)],
  137. np.array([[], [1, 2]], dtype='object'),
  138. NotAnArray(np.array([[], [1, 2]], dtype='object'))
  139. ]
  140. def test_unique_labels():
  141. # Empty iterable
  142. assert_raises(ValueError, unique_labels)
  143. # Multiclass problem
  144. assert_array_equal(unique_labels(xrange(10)), np.arange(10))
  145. assert_array_equal(unique_labels(np.arange(10)), np.arange(10))
  146. assert_array_equal(unique_labels([4, 0, 2]), np.array([0, 2, 4]))
  147. # Multilabel indicator
  148. assert_array_equal(unique_labels(np.array([[0, 0, 1],
  149. [1, 0, 1],
  150. [0, 0, 0]])),
  151. np.arange(3))
  152. assert_array_equal(unique_labels(np.array([[0, 0, 1],
  153. [0, 0, 0]])),
  154. np.arange(3))
  155. # Several arrays passed
  156. assert_array_equal(unique_labels([4, 0, 2], xrange(5)),
  157. np.arange(5))
  158. assert_array_equal(unique_labels((0, 1, 2), (0,), (2, 1)),
  159. np.arange(3))
  160. # Border line case with binary indicator matrix
  161. assert_raises(ValueError, unique_labels, [4, 0, 2], np.ones((5, 5)))
  162. assert_raises(ValueError, unique_labels, np.ones((5, 4)), np.ones((5, 5)))
  163. assert_array_equal(unique_labels(np.ones((4, 5)), np.ones((5, 5))),
  164. np.arange(5))
  165. def test_unique_labels_non_specific():
  166. # Test unique_labels with a variety of collected examples
  167. # Smoke test for all supported format
  168. for format in ["binary", "multiclass", "multilabel-indicator"]:
  169. for y in EXAMPLES[format]:
  170. unique_labels(y)
  171. # We don't support those format at the moment
  172. for example in NON_ARRAY_LIKE_EXAMPLES:
  173. assert_raises(ValueError, unique_labels, example)
  174. for y_type in ["unknown", "continuous", 'continuous-multioutput',
  175. 'multiclass-multioutput']:
  176. for example in EXAMPLES[y_type]:
  177. assert_raises(ValueError, unique_labels, example)
  178. def test_unique_labels_mixed_types():
  179. # Mix with binary or multiclass and multilabel
  180. mix_clf_format = product(EXAMPLES["multilabel-indicator"],
  181. EXAMPLES["multiclass"] +
  182. EXAMPLES["binary"])
  183. for y_multilabel, y_multiclass in mix_clf_format:
  184. assert_raises(ValueError, unique_labels, y_multiclass, y_multilabel)
  185. assert_raises(ValueError, unique_labels, y_multilabel, y_multiclass)
  186. assert_raises(ValueError, unique_labels, [[1, 2]], [["a", "d"]])
  187. assert_raises(ValueError, unique_labels, ["1", 2])
  188. assert_raises(ValueError, unique_labels, [["1", 2], [1, 3]])
  189. assert_raises(ValueError, unique_labels, [["1", "2"], [2, 3]])
  190. def test_is_multilabel():
  191. for group, group_examples in iteritems(EXAMPLES):
  192. if group in ['multilabel-indicator']:
  193. dense_assert_, dense_exp = assert_true, 'True'
  194. else:
  195. dense_assert_, dense_exp = assert_false, 'False'
  196. for example in group_examples:
  197. # Only mark explicitly defined sparse examples as valid sparse
  198. # multilabel-indicators
  199. if group == 'multilabel-indicator' and issparse(example):
  200. sparse_assert_, sparse_exp = assert_true, 'True'
  201. else:
  202. sparse_assert_, sparse_exp = assert_false, 'False'
  203. if (issparse(example) or
  204. (hasattr(example, '__array__') and
  205. np.asarray(example).ndim == 2 and
  206. np.asarray(example).dtype.kind in 'biuf' and
  207. np.asarray(example).shape[1] > 0)):
  208. examples_sparse = [sparse_matrix(example)
  209. for sparse_matrix in [coo_matrix,
  210. csc_matrix,
  211. csr_matrix,
  212. dok_matrix,
  213. lil_matrix]]
  214. for exmpl_sparse in examples_sparse:
  215. sparse_assert_(is_multilabel(exmpl_sparse),
  216. msg=('is_multilabel(%r)'
  217. ' should be %s')
  218. % (exmpl_sparse, sparse_exp))
  219. # Densify sparse examples before testing
  220. if issparse(example):
  221. example = example.toarray()
  222. dense_assert_(is_multilabel(example),
  223. msg='is_multilabel(%r) should be %s'
  224. % (example, dense_exp))
  225. def test_check_classification_targets():
  226. for y_type in EXAMPLES.keys():
  227. if y_type in ["unknown", "continuous", 'continuous-multioutput']:
  228. for example in EXAMPLES[y_type]:
  229. msg = 'Unknown label type: '
  230. assert_raises_regex(ValueError, msg,
  231. check_classification_targets, example)
  232. else:
  233. for example in EXAMPLES[y_type]:
  234. check_classification_targets(example)
  235. # @ignore_warnings
  236. def test_type_of_target():
  237. for group, group_examples in iteritems(EXAMPLES):
  238. for example in group_examples:
  239. assert_equal(type_of_target(example), group,
  240. msg=('type_of_target(%r) should be %r, got %r'
  241. % (example, group, type_of_target(example))))
  242. for example in NON_ARRAY_LIKE_EXAMPLES:
  243. msg_regex = 'Expected array-like \(array or non-string sequence\).*'
  244. assert_raises_regex(ValueError, msg_regex, type_of_target, example)
  245. for example in MULTILABEL_SEQUENCES:
  246. msg = ('You appear to be using a legacy multi-label data '
  247. 'representation. Sequence of sequences are no longer supported;'
  248. ' use a binary array or sparse matrix instead.')
  249. assert_raises_regex(ValueError, msg, type_of_target, example)
  250. def test_class_distribution():
  251. y = np.array([[1, 0, 0, 1],
  252. [2, 2, 0, 1],
  253. [1, 3, 0, 1],
  254. [4, 2, 0, 1],
  255. [2, 0, 0, 1],
  256. [1, 3, 0, 1]])
  257. # Define the sparse matrix with a mix of implicit and explicit zeros
  258. data = np.array([1, 2, 1, 4, 2, 1, 0, 2, 3, 2, 3, 1, 1, 1, 1, 1, 1])
  259. indices = np.array([0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 5, 0, 1, 2, 3, 4, 5])
  260. indptr = np.array([0, 6, 11, 11, 17])
  261. y_sp = sp.csc_matrix((data, indices, indptr), shape=(6, 4))
  262. classes, n_classes, class_prior = class_distribution(y)
  263. classes_sp, n_classes_sp, class_prior_sp = class_distribution(y_sp)
  264. classes_expected = [[1, 2, 4],
  265. [0, 2, 3],
  266. [0],
  267. [1]]
  268. n_classes_expected = [3, 3, 1, 1]
  269. class_prior_expected = [[3/6, 2/6, 1/6],
  270. [1/3, 1/3, 1/3],
  271. [1.0],
  272. [1.0]]
  273. for k in range(y.shape[1]):
  274. assert_array_almost_equal(classes[k], classes_expected[k])
  275. assert_array_almost_equal(n_classes[k], n_classes_expected[k])
  276. assert_array_almost_equal(class_prior[k], class_prior_expected[k])
  277. assert_array_almost_equal(classes_sp[k], classes_expected[k])
  278. assert_array_almost_equal(n_classes_sp[k], n_classes_expected[k])
  279. assert_array_almost_equal(class_prior_sp[k], class_prior_expected[k])
  280. # Test again with explicit sample weights
  281. (classes,
  282. n_classes,
  283. class_prior) = class_distribution(y, [1.0, 2.0, 1.0, 2.0, 1.0, 2.0])
  284. (classes_sp,
  285. n_classes_sp,
  286. class_prior_sp) = class_distribution(y, [1.0, 2.0, 1.0, 2.0, 1.0, 2.0])
  287. class_prior_expected = [[4/9, 3/9, 2/9],
  288. [2/9, 4/9, 3/9],
  289. [1.0],
  290. [1.0]]
  291. for k in range(y.shape[1]):
  292. assert_array_almost_equal(classes[k], classes_expected[k])
  293. assert_array_almost_equal(n_classes[k], n_classes_expected[k])
  294. assert_array_almost_equal(class_prior[k], class_prior_expected[k])
  295. assert_array_almost_equal(classes_sp[k], classes_expected[k])
  296. assert_array_almost_equal(n_classes_sp[k], n_classes_expected[k])
  297. assert_array_almost_equal(class_prior_sp[k], class_prior_expected[k])