2010-03-03 23:41:42 +08:00
|
|
|
"""
|
|
|
|
|
Todo: cross-check the F-value with stats model
|
|
|
|
|
"""
|
2015-02-24 22:04:57 +08:00
|
|
|
from __future__ import division
|
2012-09-18 20:15:06 +08:00
|
|
|
import itertools
|
2015-02-24 22:04:57 +08:00
|
|
|
import warnings
|
2010-03-03 23:41:42 +08:00
|
|
|
import numpy as np
|
2012-09-18 20:15:06 +08:00
|
|
|
from scipy import stats, sparse
|
2012-08-19 02:29:38 +08:00
|
|
|
|
2014-05-06 14:44:37 +08:00
|
|
|
from sklearn.utils.testing import assert_equal
|
|
|
|
|
from sklearn.utils.testing import assert_almost_equal
|
|
|
|
|
from sklearn.utils.testing import assert_raises
|
|
|
|
|
from sklearn.utils.testing import assert_true
|
|
|
|
|
from sklearn.utils.testing import assert_array_equal
|
|
|
|
|
from sklearn.utils.testing import assert_array_almost_equal
|
|
|
|
|
from sklearn.utils.testing import assert_not_in
|
|
|
|
|
from sklearn.utils.testing import assert_less
|
2014-10-09 00:26:41 +08:00
|
|
|
from sklearn.utils.testing import assert_warns
|
2014-05-06 14:44:37 +08:00
|
|
|
from sklearn.utils.testing import ignore_warnings
|
2015-02-06 00:12:10 +08:00
|
|
|
from sklearn.utils.testing import assert_warns_message
|
2015-02-24 22:04:57 +08:00
|
|
|
from sklearn.utils.testing import assert_greater
|
|
|
|
|
from sklearn.utils.testing import assert_greater_equal
|
2013-05-06 12:36:57 +08:00
|
|
|
from sklearn.utils import safe_mask
|
2014-05-06 14:44:37 +08:00
|
|
|
|
2012-09-18 20:13:36 +08:00
|
|
|
from sklearn.datasets.samples_generator import (make_classification,
|
|
|
|
|
make_regression)
|
2012-08-19 02:29:38 +08:00
|
|
|
from sklearn.feature_selection import (chi2, f_classif, f_oneway, f_regression,
|
|
|
|
|
SelectPercentile, SelectKBest,
|
|
|
|
|
SelectFpr, SelectFdr, SelectFwe,
|
|
|
|
|
GenericUnivariateSelect)
|
2010-03-04 00:36:24 +08:00
|
|
|
|
2011-11-29 07:03:19 +08:00
|
|
|
|
2010-11-14 02:09:03 +08:00
|
|
|
##############################################################################
|
2010-07-28 17:16:31 +08:00
|
|
|
# Test the score functions
|
|
|
|
|
|
2010-11-14 02:09:03 +08:00
|
|
|
def test_f_oneway_vs_scipy_stats():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test that our f_oneway gives the same result as scipy.stats
|
2012-05-06 22:22:39 +08:00
|
|
|
rng = np.random.RandomState(0)
|
|
|
|
|
X1 = rng.randn(10, 3)
|
|
|
|
|
X2 = 1 + rng.randn(10, 3)
|
2010-11-14 02:09:03 +08:00
|
|
|
f, pv = stats.f_oneway(X1, X2)
|
|
|
|
|
f2, pv2 = f_oneway(X1, X2)
|
2012-02-11 22:43:03 +08:00
|
|
|
assert_true(np.allclose(f, f2))
|
|
|
|
|
assert_true(np.allclose(pv, pv2))
|
2010-11-14 02:09:03 +08:00
|
|
|
|
2012-05-16 03:18:30 +08:00
|
|
|
|
2012-05-12 06:02:07 +08:00
|
|
|
def test_f_oneway_ints():
|
|
|
|
|
# Smoke test f_oneway on integers: that it does raise casting errors
|
|
|
|
|
# with recent numpys
|
2014-07-29 14:54:28 +08:00
|
|
|
rng = np.random.RandomState(0)
|
|
|
|
|
X = rng.randint(10, size=(10, 10))
|
2013-12-17 05:02:05 +08:00
|
|
|
y = np.arange(10)
|
|
|
|
|
fint, pint = f_oneway(X, y)
|
|
|
|
|
|
|
|
|
|
# test that is gives the same result as with float
|
|
|
|
|
f, p = f_oneway(X.astype(np.float), y)
|
2014-07-23 21:18:16 +08:00
|
|
|
assert_array_almost_equal(f, fint, decimal=4)
|
|
|
|
|
assert_array_almost_equal(p, pint, decimal=4)
|
2012-05-12 06:02:07 +08:00
|
|
|
|
2010-11-14 02:09:03 +08:00
|
|
|
|
2010-07-28 17:16:31 +08:00
|
|
|
def test_f_classif():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test whether the F test yields meaningful results
|
|
|
|
|
# on a simple simulated classification problem
|
2012-08-15 06:33:41 +08:00
|
|
|
X, y = make_classification(n_samples=200, n_features=20,
|
2011-09-07 05:12:26 +08:00
|
|
|
n_informative=3, n_redundant=2,
|
|
|
|
|
n_repeated=0, n_classes=8,
|
2011-08-04 20:08:25 +08:00
|
|
|
n_clusters_per_class=1, flip_y=0.0,
|
2011-08-05 02:30:15 +08:00
|
|
|
class_sep=10, shuffle=False, random_state=0)
|
2011-08-04 20:08:25 +08:00
|
|
|
|
2012-08-15 06:33:41 +08:00
|
|
|
F, pv = f_classif(X, y)
|
2015-02-07 21:15:02 +08:00
|
|
|
F_sparse, pv_sparse = f_classif(sparse.csr_matrix(X), y)
|
2014-05-06 14:44:37 +08:00
|
|
|
assert_true((F > 0).all())
|
|
|
|
|
assert_true((pv > 0).all())
|
|
|
|
|
assert_true((pv < 1).all())
|
|
|
|
|
assert_true((pv[:5] < 0.05).all())
|
|
|
|
|
assert_true((pv[5:] > 1.e-4).all())
|
2012-08-15 17:35:06 +08:00
|
|
|
assert_array_almost_equal(F_sparse, F)
|
|
|
|
|
assert_array_almost_equal(pv_sparse, pv)
|
2010-03-03 23:41:42 +08:00
|
|
|
|
2010-07-28 17:16:31 +08:00
|
|
|
|
|
|
|
|
def test_f_regression():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test whether the F test yields meaningful results
|
|
|
|
|
# on a simple simulated regression problem
|
2012-12-22 20:02:50 +08:00
|
|
|
X, y = make_regression(n_samples=200, n_features=20, n_informative=5,
|
|
|
|
|
shuffle=False, random_state=0)
|
2012-08-15 06:33:41 +08:00
|
|
|
|
|
|
|
|
F, pv = f_regression(X, y)
|
2014-05-06 14:44:37 +08:00
|
|
|
assert_true((F > 0).all())
|
|
|
|
|
assert_true((pv > 0).all())
|
|
|
|
|
assert_true((pv < 1).all())
|
|
|
|
|
assert_true((pv[:5] < 0.05).all())
|
|
|
|
|
assert_true((pv[5:] > 1.e-4).all())
|
2012-08-15 06:33:41 +08:00
|
|
|
|
2012-08-15 17:35:06 +08:00
|
|
|
# again without centering, compare with sparse
|
|
|
|
|
F, pv = f_regression(X, y, center=False)
|
|
|
|
|
F_sparse, pv_sparse = f_regression(sparse.csr_matrix(X), y, center=False)
|
|
|
|
|
assert_array_almost_equal(F_sparse, F)
|
|
|
|
|
assert_array_almost_equal(pv_sparse, pv)
|
2010-03-03 23:41:42 +08:00
|
|
|
|
2010-07-28 17:16:31 +08:00
|
|
|
|
2012-03-26 21:55:24 +08:00
|
|
|
def test_f_regression_input_dtype():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test whether f_regression returns the same value
|
|
|
|
|
# for any numeric data_type
|
2012-05-06 22:22:39 +08:00
|
|
|
rng = np.random.RandomState(0)
|
|
|
|
|
X = rng.rand(10, 20)
|
2012-03-29 21:21:08 +08:00
|
|
|
y = np.arange(10).astype(np.int)
|
2012-03-26 21:55:24 +08:00
|
|
|
|
|
|
|
|
F1, pv1 = f_regression(X, y)
|
2012-03-29 21:21:08 +08:00
|
|
|
F2, pv2 = f_regression(X, y.astype(np.float))
|
|
|
|
|
assert_array_almost_equal(F1, F2, 5)
|
|
|
|
|
assert_array_almost_equal(pv1, pv2, 5)
|
2012-03-26 21:55:24 +08:00
|
|
|
|
|
|
|
|
|
2014-02-08 00:27:33 +08:00
|
|
|
def test_f_regression_center():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test whether f_regression preserves dof according to 'center' argument
|
|
|
|
|
# We use two centered variates so we have a simple relationship between
|
|
|
|
|
# F-score with variates centering and F-score without variates centering.
|
2014-02-08 00:27:33 +08:00
|
|
|
# Create toy example
|
2014-07-20 19:31:45 +08:00
|
|
|
X = np.arange(-5, 6).reshape(-1, 1) # X has zero mean
|
2014-02-08 00:27:33 +08:00
|
|
|
n_samples = X.size
|
|
|
|
|
Y = np.ones(n_samples)
|
|
|
|
|
Y[::2] *= -1.
|
|
|
|
|
Y[0] = 0. # have Y mean being null
|
|
|
|
|
|
|
|
|
|
F1, _ = f_regression(X, Y, center=True)
|
|
|
|
|
F2, _ = f_regression(X, Y, center=False)
|
2014-02-08 01:46:48 +08:00
|
|
|
assert_array_almost_equal(F1 * (n_samples - 1.) / (n_samples - 2.), F2)
|
2014-02-08 02:15:45 +08:00
|
|
|
assert_almost_equal(F2[0], 0.232558139) # value from statsmodels OLS
|
2014-02-08 00:27:33 +08:00
|
|
|
|
|
|
|
|
|
2010-07-28 17:16:31 +08:00
|
|
|
def test_f_classif_multi_class():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test whether the F test yields meaningful results
|
|
|
|
|
# on a simple simulated classification problem
|
2012-08-15 06:33:41 +08:00
|
|
|
X, y = make_classification(n_samples=200, n_features=20,
|
2011-09-07 05:12:26 +08:00
|
|
|
n_informative=3, n_redundant=2,
|
|
|
|
|
n_repeated=0, n_classes=8,
|
2011-08-04 20:08:25 +08:00
|
|
|
n_clusters_per_class=1, flip_y=0.0,
|
2011-08-05 02:30:15 +08:00
|
|
|
class_sep=10, shuffle=False, random_state=0)
|
2011-08-04 20:08:25 +08:00
|
|
|
|
2012-08-15 06:33:41 +08:00
|
|
|
F, pv = f_classif(X, y)
|
2014-05-06 14:44:37 +08:00
|
|
|
assert_true((F > 0).all())
|
|
|
|
|
assert_true((pv > 0).all())
|
|
|
|
|
assert_true((pv < 1).all())
|
|
|
|
|
assert_true((pv[:5] < 0.05).all())
|
|
|
|
|
assert_true((pv[5:] > 1.e-4).all())
|
2010-03-03 23:41:42 +08:00
|
|
|
|
2010-07-27 18:08:18 +08:00
|
|
|
|
2010-07-28 17:16:31 +08:00
|
|
|
def test_select_percentile_classif():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test whether the relative univariate feature selection
|
|
|
|
|
# gets the correct items in a simple classification problem
|
|
|
|
|
# with the percentile heuristic
|
2012-08-15 06:33:41 +08:00
|
|
|
X, y = make_classification(n_samples=200, n_features=20,
|
2011-09-07 05:12:26 +08:00
|
|
|
n_informative=3, n_redundant=2,
|
|
|
|
|
n_repeated=0, n_classes=8,
|
2011-08-04 20:08:25 +08:00
|
|
|
n_clusters_per_class=1, flip_y=0.0,
|
2011-08-05 02:30:15 +08:00
|
|
|
class_sep=10, shuffle=False, random_state=0)
|
2010-06-26 20:44:24 +08:00
|
|
|
|
2010-11-14 02:09:03 +08:00
|
|
|
univariate_filter = SelectPercentile(f_classif, percentile=25)
|
2012-08-15 06:33:41 +08:00
|
|
|
X_r = univariate_filter.fit(X, y).transform(X)
|
2010-11-06 22:42:55 +08:00
|
|
|
X_r2 = GenericUnivariateSelect(f_classif, mode='percentile',
|
2012-12-22 20:02:50 +08:00
|
|
|
param=25).fit(X, y).transform(X)
|
2010-07-28 17:16:31 +08:00
|
|
|
assert_array_equal(X_r, X_r2)
|
|
|
|
|
support = univariate_filter.get_support()
|
2010-03-03 23:41:42 +08:00
|
|
|
gtruth = np.zeros(20)
|
2011-11-29 07:03:19 +08:00
|
|
|
gtruth[:5] = 1
|
2010-06-23 19:08:12 +08:00
|
|
|
assert_array_equal(support, gtruth)
|
2010-03-03 23:41:42 +08:00
|
|
|
|
2011-11-29 07:03:19 +08:00
|
|
|
|
2012-08-15 06:33:41 +08:00
|
|
|
def test_select_percentile_classif_sparse():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test whether the relative univariate feature selection
|
|
|
|
|
# gets the correct items in a simple classification problem
|
|
|
|
|
# with the percentile heuristic
|
2012-08-15 06:33:41 +08:00
|
|
|
X, y = make_classification(n_samples=200, n_features=20,
|
|
|
|
|
n_informative=3, n_redundant=2,
|
|
|
|
|
n_repeated=0, n_classes=8,
|
|
|
|
|
n_clusters_per_class=1, flip_y=0.0,
|
|
|
|
|
class_sep=10, shuffle=False, random_state=0)
|
|
|
|
|
X = sparse.csr_matrix(X)
|
|
|
|
|
univariate_filter = SelectPercentile(f_classif, percentile=25)
|
|
|
|
|
X_r = univariate_filter.fit(X, y).transform(X)
|
|
|
|
|
X_r2 = GenericUnivariateSelect(f_classif, mode='percentile',
|
2012-12-22 20:02:50 +08:00
|
|
|
param=25).fit(X, y).transform(X)
|
2012-08-15 06:33:41 +08:00
|
|
|
assert_array_equal(X_r.toarray(), X_r2.toarray())
|
|
|
|
|
support = univariate_filter.get_support()
|
|
|
|
|
gtruth = np.zeros(20)
|
|
|
|
|
gtruth[:5] = 1
|
|
|
|
|
assert_array_equal(support, gtruth)
|
|
|
|
|
|
2013-05-06 19:55:35 +08:00
|
|
|
X_r2inv = univariate_filter.inverse_transform(X_r2)
|
2013-05-06 12:36:57 +08:00
|
|
|
assert_true(sparse.issparse(X_r2inv))
|
|
|
|
|
support_mask = safe_mask(X_r2inv, support)
|
2013-05-06 19:55:35 +08:00
|
|
|
assert_equal(X_r2inv.shape, X.shape)
|
2013-05-06 12:36:57 +08:00
|
|
|
assert_array_equal(X_r2inv[:, support_mask].toarray(), X_r.toarray())
|
|
|
|
|
# Check other columns are empty
|
|
|
|
|
assert_equal(X_r2inv.getnnz(), X_r.getnnz())
|
|
|
|
|
|
2012-08-15 06:33:41 +08:00
|
|
|
|
2010-11-14 02:09:03 +08:00
|
|
|
##############################################################################
|
2010-07-28 17:16:31 +08:00
|
|
|
# Test univariate selection in classification settings
|
|
|
|
|
|
|
|
|
|
def test_select_kbest_classif():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test whether the relative univariate feature selection
|
|
|
|
|
# gets the correct items in a simple classification problem
|
|
|
|
|
# with the k best heuristic
|
2012-08-15 06:33:41 +08:00
|
|
|
X, y = make_classification(n_samples=200, n_features=20,
|
2011-09-07 05:12:26 +08:00
|
|
|
n_informative=3, n_redundant=2,
|
|
|
|
|
n_repeated=0, n_classes=8,
|
2011-08-04 20:08:25 +08:00
|
|
|
n_clusters_per_class=1, flip_y=0.0,
|
2011-08-05 02:30:15 +08:00
|
|
|
class_sep=10, shuffle=False, random_state=0)
|
2011-08-04 20:08:25 +08:00
|
|
|
|
2010-11-14 02:09:03 +08:00
|
|
|
univariate_filter = SelectKBest(f_classif, k=5)
|
2012-08-15 06:33:41 +08:00
|
|
|
X_r = univariate_filter.fit(X, y).transform(X)
|
2012-12-22 20:02:50 +08:00
|
|
|
X_r2 = GenericUnivariateSelect(
|
|
|
|
|
f_classif, mode='k_best', param=5).fit(X, y).transform(X)
|
2010-07-28 17:16:31 +08:00
|
|
|
assert_array_equal(X_r, X_r2)
|
|
|
|
|
support = univariate_filter.get_support()
|
2010-03-03 23:41:42 +08:00
|
|
|
gtruth = np.zeros(20)
|
2011-11-29 07:03:19 +08:00
|
|
|
gtruth[:5] = 1
|
2010-06-23 19:08:12 +08:00
|
|
|
assert_array_equal(support, gtruth)
|
2010-03-03 23:41:42 +08:00
|
|
|
|
2010-07-28 17:16:31 +08:00
|
|
|
|
2013-03-13 11:47:51 +08:00
|
|
|
def test_select_kbest_all():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test whether k="all" correctly returns all features.
|
2013-03-13 11:47:51 +08:00
|
|
|
X, y = make_classification(n_samples=20, n_features=10,
|
|
|
|
|
shuffle=False, random_state=0)
|
|
|
|
|
|
|
|
|
|
univariate_filter = SelectKBest(f_classif, k='all')
|
|
|
|
|
X_r = univariate_filter.fit(X, y).transform(X)
|
|
|
|
|
assert_array_equal(X, X_r)
|
|
|
|
|
|
2014-05-05 22:52:14 +08:00
|
|
|
|
2014-03-28 03:18:50 +08:00
|
|
|
def test_select_kbest_zero():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test whether k=0 correctly returns no features.
|
2014-03-28 03:18:50 +08:00
|
|
|
X, y = make_classification(n_samples=20, n_features=10,
|
|
|
|
|
shuffle=False, random_state=0)
|
|
|
|
|
|
|
|
|
|
univariate_filter = SelectKBest(f_classif, k=0)
|
2015-02-06 00:12:10 +08:00
|
|
|
univariate_filter.fit(X, y)
|
2014-03-28 03:18:50 +08:00
|
|
|
support = univariate_filter.get_support()
|
2014-05-05 22:52:14 +08:00
|
|
|
gtruth = np.zeros(10, dtype=bool)
|
2014-03-28 03:18:50 +08:00
|
|
|
assert_array_equal(support, gtruth)
|
2015-02-06 00:12:10 +08:00
|
|
|
X_selected = assert_warns_message(UserWarning, 'No features were selected',
|
|
|
|
|
univariate_filter.transform, X)
|
|
|
|
|
assert_equal(X_selected.shape, (20, 0))
|
2013-03-13 11:47:51 +08:00
|
|
|
|
2014-05-05 22:52:14 +08:00
|
|
|
|
2015-02-07 21:15:02 +08:00
|
|
|
def test_select_heuristics_classif():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test whether the relative univariate feature selection
|
|
|
|
|
# gets the correct items in a simple classification problem
|
|
|
|
|
# with the fdr, fwe and fpr heuristics
|
2012-08-15 06:33:41 +08:00
|
|
|
X, y = make_classification(n_samples=200, n_features=20,
|
2011-09-07 05:12:26 +08:00
|
|
|
n_informative=3, n_redundant=2,
|
|
|
|
|
n_repeated=0, n_classes=8,
|
2011-08-04 20:08:25 +08:00
|
|
|
n_clusters_per_class=1, flip_y=0.0,
|
2011-08-05 02:30:15 +08:00
|
|
|
class_sep=10, shuffle=False, random_state=0)
|
2011-08-04 20:08:25 +08:00
|
|
|
|
2010-07-28 17:16:31 +08:00
|
|
|
univariate_filter = SelectFwe(f_classif, alpha=0.01)
|
2012-08-15 06:33:41 +08:00
|
|
|
X_r = univariate_filter.fit(X, y).transform(X)
|
2010-03-03 23:41:42 +08:00
|
|
|
gtruth = np.zeros(20)
|
2011-11-29 07:03:19 +08:00
|
|
|
gtruth[:5] = 1
|
2015-02-07 21:15:02 +08:00
|
|
|
for mode in ['fdr', 'fpr', 'fwe']:
|
|
|
|
|
X_r2 = GenericUnivariateSelect(
|
|
|
|
|
f_classif, mode=mode, param=0.01).fit(X, y).transform(X)
|
|
|
|
|
assert_array_equal(X_r, X_r2)
|
|
|
|
|
support = univariate_filter.get_support()
|
|
|
|
|
assert_array_almost_equal(support, gtruth)
|
2010-03-03 23:41:42 +08:00
|
|
|
|
|
|
|
|
|
2010-11-14 02:09:03 +08:00
|
|
|
##############################################################################
|
2010-07-28 17:16:31 +08:00
|
|
|
# Test univariate selection in regression settings
|
2010-03-03 23:41:42 +08:00
|
|
|
|
2013-05-07 10:16:09 +08:00
|
|
|
|
|
|
|
|
def assert_best_scores_kept(score_filter):
|
|
|
|
|
scores = score_filter.scores_
|
|
|
|
|
support = score_filter.get_support()
|
|
|
|
|
assert_array_equal(np.sort(scores[support]),
|
|
|
|
|
np.sort(scores)[-support.sum():])
|
|
|
|
|
|
|
|
|
|
|
2010-07-28 17:16:31 +08:00
|
|
|
def test_select_percentile_regression():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test whether the relative univariate feature selection
|
|
|
|
|
# gets the correct items in a simple regression problem
|
|
|
|
|
# with the percentile heuristic
|
2012-08-15 06:33:41 +08:00
|
|
|
X, y = make_regression(n_samples=200, n_features=20,
|
2011-08-05 02:30:15 +08:00
|
|
|
n_informative=5, shuffle=False, random_state=0)
|
2011-08-04 20:08:25 +08:00
|
|
|
|
2010-11-14 02:09:03 +08:00
|
|
|
univariate_filter = SelectPercentile(f_regression, percentile=25)
|
2012-08-15 06:33:41 +08:00
|
|
|
X_r = univariate_filter.fit(X, y).transform(X)
|
2013-05-07 10:16:09 +08:00
|
|
|
assert_best_scores_kept(univariate_filter)
|
2012-12-22 20:02:50 +08:00
|
|
|
X_r2 = GenericUnivariateSelect(
|
|
|
|
|
f_regression, mode='percentile', param=25).fit(X, y).transform(X)
|
2010-07-28 17:16:31 +08:00
|
|
|
assert_array_equal(X_r, X_r2)
|
|
|
|
|
support = univariate_filter.get_support()
|
2010-03-03 23:41:42 +08:00
|
|
|
gtruth = np.zeros(20)
|
2011-11-29 07:03:19 +08:00
|
|
|
gtruth[:5] = 1
|
2010-06-23 19:08:12 +08:00
|
|
|
assert_array_equal(support, gtruth)
|
2011-05-04 23:49:17 +08:00
|
|
|
X_2 = X.copy()
|
2011-02-01 07:08:48 +08:00
|
|
|
X_2[:, np.logical_not(support)] = 0
|
|
|
|
|
assert_array_equal(X_2, univariate_filter.inverse_transform(X_r))
|
2013-05-06 12:13:13 +08:00
|
|
|
# Check inverse_transform respects dtype
|
|
|
|
|
assert_array_equal(X_2.astype(bool),
|
|
|
|
|
univariate_filter.inverse_transform(X_r.astype(bool)))
|
2010-03-03 23:41:42 +08:00
|
|
|
|
2010-07-28 17:16:31 +08:00
|
|
|
|
|
|
|
|
def test_select_percentile_regression_full():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test whether the relative univariate feature selection
|
|
|
|
|
# selects all features when '100%' is asked.
|
2012-08-15 06:33:41 +08:00
|
|
|
X, y = make_regression(n_samples=200, n_features=20,
|
2011-08-05 02:30:15 +08:00
|
|
|
n_informative=5, shuffle=False, random_state=0)
|
2011-08-04 20:08:25 +08:00
|
|
|
|
2010-07-28 17:16:31 +08:00
|
|
|
univariate_filter = SelectPercentile(f_regression, percentile=100)
|
2012-08-15 06:33:41 +08:00
|
|
|
X_r = univariate_filter.fit(X, y).transform(X)
|
2013-05-07 10:16:09 +08:00
|
|
|
assert_best_scores_kept(univariate_filter)
|
2012-12-22 20:02:50 +08:00
|
|
|
X_r2 = GenericUnivariateSelect(
|
|
|
|
|
f_regression, mode='percentile', param=100).fit(X, y).transform(X)
|
2010-07-28 17:16:31 +08:00
|
|
|
assert_array_equal(X_r, X_r2)
|
|
|
|
|
support = univariate_filter.get_support()
|
2010-03-23 16:34:04 +08:00
|
|
|
gtruth = np.ones(20)
|
2010-06-23 19:08:12 +08:00
|
|
|
assert_array_equal(support, gtruth)
|
2010-03-23 16:34:04 +08:00
|
|
|
|
2010-07-28 17:16:31 +08:00
|
|
|
|
2012-09-18 20:13:36 +08:00
|
|
|
def test_invalid_percentile():
|
2014-05-05 22:52:14 +08:00
|
|
|
X, y = make_regression(n_samples=10, n_features=20,
|
|
|
|
|
n_informative=2, shuffle=False, random_state=0)
|
|
|
|
|
|
|
|
|
|
assert_raises(ValueError, SelectPercentile(percentile=-1).fit, X, y)
|
2014-05-06 14:44:37 +08:00
|
|
|
assert_raises(ValueError, SelectPercentile(percentile=101).fit, X, y)
|
|
|
|
|
assert_raises(ValueError, GenericUnivariateSelect(mode='percentile',
|
|
|
|
|
param=-1).fit, X, y)
|
|
|
|
|
assert_raises(ValueError, GenericUnivariateSelect(mode='percentile',
|
|
|
|
|
param=101).fit, X, y)
|
2012-09-18 20:13:36 +08:00
|
|
|
|
|
|
|
|
|
2010-07-28 17:16:31 +08:00
|
|
|
def test_select_kbest_regression():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test whether the relative univariate feature selection
|
|
|
|
|
# gets the correct items in a simple regression problem
|
|
|
|
|
# with the k best heuristic
|
2015-02-07 21:15:02 +08:00
|
|
|
X, y = make_regression(n_samples=200, n_features=20, n_informative=5,
|
|
|
|
|
shuffle=False, random_state=0, noise=10)
|
2011-08-04 20:08:25 +08:00
|
|
|
|
2010-07-28 17:16:31 +08:00
|
|
|
univariate_filter = SelectKBest(f_regression, k=5)
|
2012-08-15 06:33:41 +08:00
|
|
|
X_r = univariate_filter.fit(X, y).transform(X)
|
2013-05-07 10:16:09 +08:00
|
|
|
assert_best_scores_kept(univariate_filter)
|
2012-12-22 20:02:50 +08:00
|
|
|
X_r2 = GenericUnivariateSelect(
|
|
|
|
|
f_regression, mode='k_best', param=5).fit(X, y).transform(X)
|
2010-07-28 17:16:31 +08:00
|
|
|
assert_array_equal(X_r, X_r2)
|
|
|
|
|
support = univariate_filter.get_support()
|
2010-03-03 23:41:42 +08:00
|
|
|
gtruth = np.zeros(20)
|
2011-11-29 07:03:19 +08:00
|
|
|
gtruth[:5] = 1
|
2010-06-23 19:08:12 +08:00
|
|
|
assert_array_equal(support, gtruth)
|
2010-03-03 23:41:42 +08:00
|
|
|
|
2010-07-28 17:16:31 +08:00
|
|
|
|
2015-02-07 21:15:02 +08:00
|
|
|
def test_select_heuristics_regression():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test whether the relative univariate feature selection
|
|
|
|
|
# gets the correct items in a simple regression problem
|
|
|
|
|
# with the fpr, fdr or fwe heuristics
|
2015-02-07 21:15:02 +08:00
|
|
|
X, y = make_regression(n_samples=200, n_features=20, n_informative=5,
|
|
|
|
|
shuffle=False, random_state=0, noise=10)
|
2011-08-04 20:08:25 +08:00
|
|
|
|
2010-07-28 17:16:31 +08:00
|
|
|
univariate_filter = SelectFpr(f_regression, alpha=0.01)
|
2012-08-15 06:33:41 +08:00
|
|
|
X_r = univariate_filter.fit(X, y).transform(X)
|
2010-03-03 23:41:42 +08:00
|
|
|
gtruth = np.zeros(20)
|
2011-11-29 07:03:19 +08:00
|
|
|
gtruth[:5] = 1
|
2015-02-07 21:15:02 +08:00
|
|
|
for mode in ['fdr', 'fpr', 'fwe']:
|
|
|
|
|
X_r2 = GenericUnivariateSelect(
|
|
|
|
|
f_regression, mode=mode, param=0.01).fit(X, y).transform(X)
|
|
|
|
|
assert_array_equal(X_r, X_r2)
|
|
|
|
|
support = univariate_filter.get_support()
|
|
|
|
|
assert_array_equal(support[:5], np.ones((5, ), dtype=np.bool))
|
|
|
|
|
assert_less(np.sum(support[5:] == 1), 3)
|
2010-03-03 23:41:42 +08:00
|
|
|
|
2010-07-28 17:16:31 +08:00
|
|
|
|
|
|
|
|
def test_select_fdr_regression():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test that fdr heuristic actually has low FDR.
|
2015-02-07 21:15:02 +08:00
|
|
|
def single_fdr(alpha, n_informative, random_state):
|
2015-02-24 22:04:57 +08:00
|
|
|
X, y = make_regression(n_samples=150, n_features=20,
|
2014-03-04 20:17:04 +08:00
|
|
|
n_informative=n_informative, shuffle=False,
|
2015-02-25 05:24:36 +08:00
|
|
|
random_state=random_state, noise=10)
|
2015-02-24 22:04:57 +08:00
|
|
|
|
|
|
|
|
with warnings.catch_warnings(record=True):
|
|
|
|
|
# Warnings can be raised when no features are selected
|
|
|
|
|
# (low alpha or very noisy data)
|
|
|
|
|
univariate_filter = SelectFdr(f_regression, alpha=alpha)
|
|
|
|
|
X_r = univariate_filter.fit(X, y).transform(X)
|
|
|
|
|
X_r2 = GenericUnivariateSelect(
|
|
|
|
|
f_regression, mode='fdr', param=alpha).fit(X, y).transform(X)
|
2014-03-04 20:17:04 +08:00
|
|
|
|
|
|
|
|
assert_array_equal(X_r, X_r2)
|
|
|
|
|
support = univariate_filter.get_support()
|
|
|
|
|
num_false_positives = np.sum(support[n_informative:] == 1)
|
|
|
|
|
num_true_positives = np.sum(support[:n_informative] == 1)
|
|
|
|
|
|
2015-02-24 22:04:57 +08:00
|
|
|
if num_false_positives == 0:
|
|
|
|
|
return 0.
|
|
|
|
|
false_discovery_rate = (num_false_positives /
|
|
|
|
|
(num_true_positives + num_false_positives))
|
2015-02-07 21:15:02 +08:00
|
|
|
return false_discovery_rate
|
|
|
|
|
|
2015-02-24 22:04:57 +08:00
|
|
|
for alpha in [0.001, 0.01, 0.1]:
|
|
|
|
|
for n_informative in [1, 5, 10]:
|
2015-02-25 05:24:36 +08:00
|
|
|
# As per Benjamini-Hochberg, the expected false discovery rate
|
2015-02-24 22:04:57 +08:00
|
|
|
# should be lower than alpha:
|
|
|
|
|
# FDR = E(FP / (TP + FP)) <= alpha
|
2015-02-07 21:15:02 +08:00
|
|
|
false_discovery_rate = np.mean([single_fdr(alpha, n_informative,
|
|
|
|
|
random_state) for
|
2015-02-24 22:04:57 +08:00
|
|
|
random_state in range(30)])
|
|
|
|
|
assert_greater_equal(alpha, false_discovery_rate)
|
|
|
|
|
|
|
|
|
|
# Make sure that the empirical false discovery rate increases
|
|
|
|
|
# with alpha:
|
|
|
|
|
if false_discovery_rate != 0:
|
|
|
|
|
assert_greater(false_discovery_rate, alpha / 10)
|
2010-03-03 23:41:42 +08:00
|
|
|
|
2010-07-28 17:16:31 +08:00
|
|
|
|
|
|
|
|
def test_select_fwe_regression():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test whether the relative univariate feature selection
|
|
|
|
|
# gets the correct items in a simple regression problem
|
|
|
|
|
# with the fwe heuristic
|
2012-08-15 06:33:41 +08:00
|
|
|
X, y = make_regression(n_samples=200, n_features=20,
|
2011-08-05 02:30:15 +08:00
|
|
|
n_informative=5, shuffle=False, random_state=0)
|
2011-08-04 20:08:25 +08:00
|
|
|
|
2010-07-28 17:16:31 +08:00
|
|
|
univariate_filter = SelectFwe(f_regression, alpha=0.01)
|
2012-08-15 06:33:41 +08:00
|
|
|
X_r = univariate_filter.fit(X, y).transform(X)
|
2012-12-22 20:02:50 +08:00
|
|
|
X_r2 = GenericUnivariateSelect(
|
|
|
|
|
f_regression, mode='fwe', param=0.01).fit(X, y).transform(X)
|
2010-07-28 17:16:31 +08:00
|
|
|
assert_array_equal(X_r, X_r2)
|
|
|
|
|
support = univariate_filter.get_support()
|
2010-03-03 23:41:42 +08:00
|
|
|
gtruth = np.zeros(20)
|
2011-11-29 07:03:19 +08:00
|
|
|
gtruth[:5] = 1
|
2014-05-06 14:44:37 +08:00
|
|
|
assert_array_equal(support[:5], np.ones((5, ), dtype=np.bool))
|
|
|
|
|
assert_less(np.sum(support[5:] == 1), 2)
|
2012-04-30 23:24:17 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_selectkbest_tiebreaking():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test whether SelectKBest actually selects k features in case of ties.
|
|
|
|
|
# Prior to 0.11, SelectKBest would return more features than requested.
|
2013-05-07 10:16:09 +08:00
|
|
|
Xs = [[0, 1, 1], [0, 0, 1], [1, 0, 0], [1, 1, 0]]
|
|
|
|
|
y = [1]
|
|
|
|
|
dummy_score = lambda X, y: (X[0], X[0])
|
|
|
|
|
for X in Xs:
|
2013-10-23 22:55:56 +08:00
|
|
|
sel = SelectKBest(dummy_score, k=1)
|
|
|
|
|
X1 = ignore_warnings(sel.fit_transform)([X], y)
|
|
|
|
|
assert_equal(X1.shape[1], 1)
|
|
|
|
|
assert_best_scores_kept(sel)
|
2012-08-19 02:29:38 +08:00
|
|
|
|
2013-10-23 22:55:56 +08:00
|
|
|
sel = SelectKBest(dummy_score, k=2)
|
|
|
|
|
X2 = ignore_warnings(sel.fit_transform)([X], y)
|
|
|
|
|
assert_equal(X2.shape[1], 2)
|
|
|
|
|
assert_best_scores_kept(sel)
|
2012-08-19 02:29:38 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_selectpercentile_tiebreaking():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test if SelectPercentile selects the right n_features in case of ties.
|
2013-05-07 10:16:09 +08:00
|
|
|
Xs = [[0, 1, 1], [0, 0, 1], [1, 0, 0], [1, 1, 0]]
|
|
|
|
|
y = [1]
|
|
|
|
|
dummy_score = lambda X, y: (X[0], X[0])
|
|
|
|
|
for X in Xs:
|
2013-10-23 22:55:56 +08:00
|
|
|
sel = SelectPercentile(dummy_score, percentile=34)
|
|
|
|
|
X1 = ignore_warnings(sel.fit_transform)([X], y)
|
|
|
|
|
assert_equal(X1.shape[1], 1)
|
|
|
|
|
assert_best_scores_kept(sel)
|
2013-05-07 10:16:09 +08:00
|
|
|
|
2013-10-23 22:55:56 +08:00
|
|
|
sel = SelectPercentile(dummy_score, percentile=67)
|
|
|
|
|
X2 = ignore_warnings(sel.fit_transform)([X], y)
|
|
|
|
|
assert_equal(X2.shape[1], 2)
|
|
|
|
|
assert_best_scores_kept(sel)
|
2012-09-18 20:15:06 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_tied_pvalues():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test whether k-best and percentiles work with tied pvalues from chi2.
|
2012-09-18 20:15:06 +08:00
|
|
|
# chi2 will return the same p-values for the following features, but it
|
|
|
|
|
# will return different scores.
|
|
|
|
|
X0 = np.array([[10000, 9999, 9998], [1, 1, 1]])
|
|
|
|
|
y = [0, 1]
|
|
|
|
|
|
|
|
|
|
for perm in itertools.permutations((0, 1, 2)):
|
|
|
|
|
X = X0[:, perm]
|
|
|
|
|
Xt = SelectKBest(chi2, k=2).fit_transform(X, y)
|
|
|
|
|
assert_equal(Xt.shape, (2, 2))
|
|
|
|
|
assert_not_in(9998, Xt)
|
|
|
|
|
|
|
|
|
|
Xt = SelectPercentile(chi2, percentile=67).fit_transform(X, y)
|
|
|
|
|
assert_equal(Xt.shape, (2, 2))
|
|
|
|
|
assert_not_in(9998, Xt)
|
2012-10-16 18:44:04 +08:00
|
|
|
|
|
|
|
|
|
2013-08-19 17:15:38 +08:00
|
|
|
def test_tied_scores():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test for stable sorting in k-best with tied scores.
|
2013-08-19 17:15:38 +08:00
|
|
|
X_train = np.array([[0, 0, 0], [1, 1, 1]])
|
|
|
|
|
y_train = [0, 1]
|
|
|
|
|
|
|
|
|
|
for n_features in [1, 2, 3]:
|
|
|
|
|
sel = SelectKBest(chi2, k=n_features).fit(X_train, y_train)
|
2015-08-25 07:52:40 +08:00
|
|
|
X_test = sel.transform([[0, 1, 2]])
|
2013-08-19 17:15:38 +08:00
|
|
|
assert_array_equal(X_test[0], np.arange(3)[-n_features:])
|
|
|
|
|
|
|
|
|
|
|
2012-10-16 18:44:04 +08:00
|
|
|
def test_nans():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Assert that SelectKBest and SelectPercentile can handle NaNs.
|
2012-10-16 18:44:04 +08:00
|
|
|
# First feature has zero variance to confuse f_classif (ANOVA) and
|
|
|
|
|
# make it return a NaN.
|
2014-05-06 14:44:37 +08:00
|
|
|
X = [[0, 1, 0], [0, -1, -1], [0, .5, .5]]
|
2012-10-16 18:44:04 +08:00
|
|
|
y = [1, 0, 1]
|
|
|
|
|
|
|
|
|
|
for select in (SelectKBest(f_classif, 2),
|
|
|
|
|
SelectPercentile(f_classif, percentile=67)):
|
2013-10-23 22:55:56 +08:00
|
|
|
ignore_warnings(select.fit)(X, y)
|
2012-10-16 18:44:04 +08:00
|
|
|
assert_array_equal(select.get_support(indices=True), np.array([1, 2]))
|
2012-10-31 23:35:15 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_score_func_error():
|
2014-05-06 14:44:37 +08:00
|
|
|
X = [[0, 1, 0], [0, -1, -1], [0, .5, .5]]
|
|
|
|
|
y = [1, 0, 1]
|
|
|
|
|
|
|
|
|
|
for SelectFeatures in [SelectKBest, SelectPercentile, SelectFwe,
|
|
|
|
|
SelectFdr, SelectFpr, GenericUnivariateSelect]:
|
|
|
|
|
assert_raises(TypeError, SelectFeatures(score_func=10).fit, X, y)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_invalid_k():
|
|
|
|
|
X = [[0, 1, 0], [0, -1, -1], [0, .5, .5]]
|
2014-05-05 22:52:14 +08:00
|
|
|
y = [1, 0, 1]
|
|
|
|
|
|
2014-05-06 14:44:37 +08:00
|
|
|
assert_raises(ValueError, SelectKBest(k=-1).fit, X, y)
|
|
|
|
|
assert_raises(ValueError, SelectKBest(k=4).fit, X, y)
|
|
|
|
|
assert_raises(ValueError,
|
|
|
|
|
GenericUnivariateSelect(mode='k_best', param=-1).fit, X, y)
|
|
|
|
|
assert_raises(ValueError,
|
|
|
|
|
GenericUnivariateSelect(mode='k_best', param=4).fit, X, y)
|
2014-10-09 00:26:41 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_f_classif_constant_feature():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test that f_classif warns if a feature is constant throughout.
|
2014-10-09 00:26:41 +08:00
|
|
|
|
|
|
|
|
X, y = make_classification(n_samples=10, n_features=5)
|
|
|
|
|
X[:, 0] = 2.0
|
|
|
|
|
assert_warns(UserWarning, f_classif, X, y)
|
2015-02-06 00:12:10 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_no_feature_selected():
|
|
|
|
|
rng = np.random.RandomState(0)
|
|
|
|
|
|
|
|
|
|
# Generate random uncorrelated data: a strict univariate test should
|
|
|
|
|
# rejects all the features
|
|
|
|
|
X = rng.rand(40, 10)
|
|
|
|
|
y = rng.randint(0, 4, size=40)
|
2015-02-07 18:37:06 +08:00
|
|
|
strict_selectors = [
|
|
|
|
|
SelectFwe(alpha=0.01).fit(X, y),
|
|
|
|
|
SelectFdr(alpha=0.01).fit(X, y),
|
|
|
|
|
SelectFpr(alpha=0.01).fit(X, y),
|
|
|
|
|
SelectPercentile(percentile=0).fit(X, y),
|
|
|
|
|
SelectKBest(k=0).fit(X, y),
|
|
|
|
|
]
|
|
|
|
|
for selector in strict_selectors:
|
|
|
|
|
assert_array_equal(selector.get_support(), np.zeros(10))
|
|
|
|
|
X_selected = assert_warns_message(
|
|
|
|
|
UserWarning, 'No features were selected', selector.transform, X)
|
|
|
|
|
assert_equal(X_selected.shape, (40, 0))
|