scikit-learn/sklearn/ensemble/forest.py

1633 lines
63 KiB
Python
Raw Normal View History

2011-11-20 06:06:53 +08:00
"""Forest of trees-based ensemble methods
2011-12-06 19:33:49 +08:00
Those methods include random forests and extremely randomized trees.
2011-11-20 06:06:53 +08:00
The module structure is the following:
2011-12-23 14:40:14 +08:00
- The ``BaseForest`` base class implements a common ``fit`` method for all
2011-12-06 19:33:49 +08:00
the estimators in the module. The ``fit`` method of the base ``Forest``
2011-11-20 06:06:53 +08:00
class calls the ``fit`` method of each sub-estimator on random samples
(with replacement, a.k.a. bootstrap) of the training set.
2011-11-20 06:06:53 +08:00
The init of the sub-estimator is further delegated to the
``BaseEnsemble`` constructor.
- The ``ForestClassifier`` and ``ForestRegressor`` base classes further
implement the prediction logic by computing an average of the predicted
outcomes of the sub-estimators.
- The ``RandomForestClassifier`` and ``RandomForestRegressor`` derived
classes provide the user with concrete implementations of
the forest ensemble method using classical, deterministic
2011-11-22 03:50:59 +08:00
``DecisionTreeClassifier`` and ``DecisionTreeRegressor`` as
sub-estimator implementations.
2011-11-20 06:06:53 +08:00
- The ``ExtraTreesClassifier`` and ``ExtraTreesRegressor`` derived
classes provide the user with concrete implementations of the
forest ensemble method using the extremely randomized trees
2011-11-22 03:50:59 +08:00
``ExtraTreeClassifier`` and ``ExtraTreeRegressor`` as
sub-estimator implementations.
2011-11-20 06:06:53 +08:00
2012-07-02 17:51:50 +08:00
Single and multi-output problems are both handled.
2011-11-12 18:29:38 +08:00
"""
2013-07-09 15:03:00 +08:00
# Authors: Gilles Louppe <g.louppe@gmail.com>
# Brian Holt <bdholt1@gmail.com>
# Joly Arnaud <arnaud.v.joly@gmail.com>
# Fares Hedayati <fares.hedayati@gmail.com>
#
# License: BSD 3 clause
2011-11-12 18:29:38 +08:00
from __future__ import division
import warnings
from warnings import warn
from abc import ABCMeta, abstractmethod
2011-11-12 18:29:38 +08:00
import numpy as np
from scipy.sparse import issparse
from scipy.sparse import hstack as sparse_hstack
2012-12-23 20:35:30 +08:00
from ..base import ClassifierMixin, RegressorMixin
from ..externals.joblib import Parallel, delayed
2013-04-04 03:07:20 +08:00
from ..externals import six
from ..feature_selection.from_model import _LearntSelectorMixin
2012-12-23 20:35:30 +08:00
from ..metrics import r2_score
2012-12-24 18:39:12 +08:00
from ..preprocessing import OneHotEncoder
2012-11-26 21:57:51 +08:00
from ..tree import (DecisionTreeClassifier, DecisionTreeRegressor,
ExtraTreeClassifier, ExtraTreeRegressor)
2012-07-21 22:13:31 +08:00
from ..tree._tree import DTYPE, DOUBLE
from ..utils import check_random_state, check_array, compute_sample_weight
from ..exceptions import DataConversionWarning, NotFittedError
from .base import BaseEnsemble, _partition_estimators
from ..utils.fixes import bincount
from ..utils.multiclass import check_classification_targets
2011-11-12 23:20:43 +08:00
__all__ = ["RandomForestClassifier",
"RandomForestRegressor",
"ExtraTreesClassifier",
"ExtraTreesRegressor",
"RandomTreesEmbedding"]
2011-11-12 18:29:38 +08:00
2011-12-21 03:03:25 +08:00
MAX_INT = np.iinfo(np.int32).max
2011-11-12 18:29:38 +08:00
2015-06-02 20:06:20 +08:00
def _generate_sample_indices(random_state, n_samples):
2015-05-29 18:45:08 +08:00
"""Private function used to _parallel_build_trees function."""
2015-06-02 20:06:20 +08:00
random_instance = check_random_state(random_state)
sample_indices = random_instance.randint(0, n_samples, n_samples)
2015-05-29 18:45:08 +08:00
return sample_indices
2015-06-02 20:06:20 +08:00
def _generate_unsampled_indices(random_state, n_samples):
2015-05-29 18:45:08 +08:00
"""Private function used to forest._set_oob_score fuction."""
2015-06-02 20:06:20 +08:00
sample_indices = _generate_sample_indices(random_state, n_samples)
2015-05-29 18:45:08 +08:00
sample_counts = bincount(sample_indices, minlength=n_samples)
unsampled_mask = sample_counts == 0
indices_range = np.arange(n_samples)
unsampled_indices = indices_range[unsampled_mask]
return unsampled_indices
2011-12-20 20:05:29 +08:00
def _parallel_build_trees(tree, forest, X, y, sample_weight, tree_idx, n_trees,
verbose=0, class_weight=None):
"""Private function used to fit a single tree in parallel."""
if verbose > 1:
print("building tree %d of %d" % (tree_idx + 1, n_trees))
if forest.bootstrap:
n_samples = X.shape[0]
if sample_weight is None:
curr_sample_weight = np.ones((n_samples,), dtype=np.float64)
2011-12-21 03:03:25 +08:00
else:
curr_sample_weight = sample_weight.copy()
2015-06-02 20:06:20 +08:00
indices = _generate_sample_indices(tree.random_state, n_samples)
sample_counts = bincount(indices, minlength=n_samples)
curr_sample_weight *= sample_counts
if class_weight == 'subsample':
with warnings.catch_warnings():
warnings.simplefilter('ignore', DeprecationWarning)
curr_sample_weight *= compute_sample_weight('auto', y, indices)
elif class_weight == 'balanced_subsample':
curr_sample_weight *= compute_sample_weight('balanced', y, indices)
tree.fit(X, y, sample_weight=curr_sample_weight, check_input=False)
else:
tree.fit(X, y, sample_weight=sample_weight, check_input=False)
return tree
def _parallel_helper(obj, methodname, *args, **kwargs):
"""Private helper to workaround Python 2 pickle limitations"""
return getattr(obj, methodname)(*args, **kwargs)
class BaseForest(six.with_metaclass(ABCMeta, BaseEnsemble,
_LearntSelectorMixin)):
2011-11-12 18:29:38 +08:00
"""Base class for forests of trees.
2011-11-12 23:20:43 +08:00
Warning: This class should not be used directly. Use derived classes
instead.
2011-11-12 18:29:38 +08:00
"""
@abstractmethod
2012-11-26 21:57:51 +08:00
def __init__(self,
base_estimator,
n_estimators=10,
estimator_params=tuple(),
bootstrap=False,
oob_score=False,
n_jobs=1,
random_state=None,
2014-07-23 04:08:46 +08:00
verbose=0,
2014-12-12 08:22:26 +08:00
warm_start=False,
class_weight=None):
2011-12-28 22:42:01 +08:00
super(BaseForest, self).__init__(
base_estimator=base_estimator,
n_estimators=n_estimators,
estimator_params=estimator_params)
2011-11-12 18:29:38 +08:00
self.bootstrap = bootstrap
self.oob_score = oob_score
self.n_jobs = n_jobs
self.random_state = random_state
self.verbose = verbose
2014-07-23 04:08:46 +08:00
self.warm_start = warm_start
2014-12-12 08:22:26 +08:00
self.class_weight = class_weight
2012-10-28 02:04:03 +08:00
def apply(self, X):
"""Apply trees in the forest to X, return leaf indices.
Parameters
----------
X : array-like or sparse matrix, shape = [n_samples, n_features]
The input samples. Internally, it will be converted to
``dtype=np.float32`` and if a sparse matrix is provided
to a sparse ``csr_matrix``.
2012-10-28 02:04:03 +08:00
Returns
-------
2012-10-30 18:25:21 +08:00
X_leaves : array_like, shape = [n_samples, n_estimators]
2012-10-28 02:04:03 +08:00
For each datapoint x in X and for each tree in the forest,
return the index of the leaf x ends up in.
"""
X = self._validate_X_predict(X)
results = Parallel(n_jobs=self.n_jobs, verbose=self.verbose,
backend="threading")(
delayed(_parallel_helper)(tree, 'apply', X, check_input=False)
for tree in self.estimators_)
return np.array(results).T
2012-10-28 02:04:03 +08:00
def decision_path(self, X):
"""Return the decision path in the forest
Parameters
----------
X : array-like or sparse matrix, shape = [n_samples, n_features]
The input samples. Internally, it will be converted to
``dtype=np.float32`` and if a sparse matrix is provided
to a sparse ``csr_matrix``.
Returns
-------
indicator : sparse csr array, shape = [n_samples, n_nodes]
Return a node indicator matrix where non zero elements
indicates that the samples goes through the nodes.
n_nodes_ptr : array of size (n_estimators + 1, )
The columns from indicator[n_nodes_ptr[i]:n_nodes_ptr[i+1]]
gives the indicator value for the i-th estimator.
"""
X = self._validate_X_predict(X)
indicators = Parallel(n_jobs=self.n_jobs, verbose=self.verbose,
backend="threading")(
delayed(_parallel_helper)(tree, 'decision_path', X,
check_input=False)
for tree in self.estimators_)
n_nodes = [0]
n_nodes.extend([i.shape[1] for i in indicators])
n_nodes_ptr = np.array(n_nodes).cumsum()
return sparse_hstack(indicators).tocsr(), n_nodes_ptr
2012-12-23 20:13:21 +08:00
def fit(self, X, y, sample_weight=None):
2011-11-12 18:29:38 +08:00
"""Build a forest of trees from the training set (X, y).
Parameters
----------
X : array-like or sparse matrix of shape = [n_samples, n_features]
The training input samples. Internally, it will be converted to
``dtype=np.float32`` and if a sparse matrix is provided
to a sparse ``csc_matrix``.
2011-11-12 18:29:38 +08:00
2012-07-02 17:51:50 +08:00
y : array-like, shape = [n_samples] or [n_samples, n_outputs]
The target values (class labels in classification, real numbers in
regression).
2011-11-12 18:29:38 +08:00
2012-12-23 22:31:22 +08:00
sample_weight : array-like, shape = [n_samples] or None
2013-01-07 15:10:11 +08:00
Sample weights. If None, then samples are equally weighted. Splits
that would create child nodes with net zero or negative weight are
ignored while searching for a split in each node. In the case of
classification, splits are also ignored if they would result in any
single class carrying a negative weight in either child node.
2012-12-23 20:13:21 +08:00
Returns
-------
2011-11-12 18:29:38 +08:00
self : object
Returns self.
"""
# Validate or convert input data
X = check_array(X, accept_sparse="csc", dtype=DTYPE)
y = check_array(y, accept_sparse='csc', ensure_2d=False, dtype=None)
if issparse(X):
# Pre-sort indices to avoid that each individual tree of the
# ensemble sorts the indices.
X.sort_indices()
2012-07-12 21:03:13 +08:00
2013-07-19 15:53:29 +08:00
# Remap output
2012-07-02 17:05:09 +08:00
n_samples, self.n_features_ = X.shape
2011-11-12 18:29:38 +08:00
2012-07-02 17:05:09 +08:00
y = np.atleast_1d(y)
if y.ndim == 2 and y.shape[1] == 1:
warn("A column-vector y was passed when a 1d array was"
" expected. Please change the shape of y to "
"(n_samples,), for example using ravel().",
DataConversionWarning, stacklevel=2)
2012-07-02 17:05:09 +08:00
if y.ndim == 1:
2012-11-26 21:11:36 +08:00
# reshape is necessary to preserve the data contiguity against vs
# [:, np.newaxis] that does not.
y = np.reshape(y, (-1, 1))
2012-07-02 17:05:09 +08:00
self.n_outputs_ = y.shape[1]
2015-01-11 03:49:42 +08:00
y, expanded_class_weight = self._validate_y_class_weight(y)
2011-11-12 18:29:38 +08:00
2012-11-26 17:01:52 +08:00
if getattr(y, "dtype", None) != DOUBLE or not y.flags.contiguous:
2012-07-21 22:13:31 +08:00
y = np.ascontiguousarray(y, dtype=DOUBLE)
2012-07-12 21:03:13 +08:00
2015-01-11 03:49:42 +08:00
if expanded_class_weight is not None:
2014-12-12 08:22:26 +08:00
if sample_weight is not None:
sample_weight = sample_weight * expanded_class_weight
2014-12-12 08:22:26 +08:00
else:
2015-01-11 03:49:42 +08:00
sample_weight = expanded_class_weight
2014-12-12 08:22:26 +08:00
2013-07-19 15:53:29 +08:00
# Check parameters
2013-07-23 18:59:32 +08:00
self._validate_estimator()
2013-07-19 15:53:29 +08:00
if not self.bootstrap and self.oob_score:
raise ValueError("Out of bag estimation only available"
" if bootstrap=True")
2014-07-23 04:08:46 +08:00
random_state = check_random_state(self.random_state)
2011-12-21 03:03:25 +08:00
2014-07-23 04:08:46 +08:00
if not self.warm_start:
# Free allocated memory, if any
self.estimators_ = []
n_more_estimators = self.n_estimators - len(self.estimators_)
if n_more_estimators < 0:
raise ValueError('n_estimators=%d must be larger or equal to '
'len(estimators_)=%d when warm_start==True'
% (self.n_estimators, len(self.estimators_)))
elif n_more_estimators == 0:
warn("Warm-start fitting without increasing n_estimators does not "
"fit new trees.")
else:
if self.warm_start and len(self.estimators_) > 0:
# We draw from the random state to get the random state we
# would have got if we hadn't used a warm_start.
random_state.randint(MAX_INT, size=len(self.estimators_))
trees = []
2014-07-23 04:08:46 +08:00
for i in range(n_more_estimators):
tree = self._make_estimator(append=False)
tree.set_params(random_state=random_state.randint(MAX_INT))
trees.append(tree)
# Parallel loop: we use the threading backend as the Cython code
# for fitting the trees is internally releasing the Python GIL
# making threading always more efficient than multiprocessing in
# that case.
trees = Parallel(n_jobs=self.n_jobs, verbose=self.verbose,
backend="threading")(
2014-07-23 04:08:46 +08:00
delayed(_parallel_build_trees)(
t, self, X, y, sample_weight, i, len(trees),
verbose=self.verbose, class_weight=self.class_weight)
for i, t in enumerate(trees))
2014-07-23 04:08:46 +08:00
# Collect newly grown trees
self.estimators_.extend(trees)
2011-11-12 18:29:38 +08:00
if self.oob_score:
self._set_oob_score(X, y)
# Decapsulate classes_ attributes
if hasattr(self, "classes_") and self.n_outputs_ == 1:
2013-07-19 15:53:29 +08:00
self.n_classes_ = self.n_classes_[0]
self.classes_ = self.classes_[0]
2011-12-28 00:44:04 +08:00
return self
@abstractmethod
def _set_oob_score(self, X, y):
"""Calculate out of bag predictions and score."""
2015-01-11 03:49:42 +08:00
def _validate_y_class_weight(self, y):
# Default implementation
2014-12-12 08:22:26 +08:00
return y, None
def _validate_X_predict(self, X):
2015-04-16 19:51:54 +08:00
"""Validate X whenever one tries to predict, apply, predict_proba"""
if self.estimators_ is None or len(self.estimators_) == 0:
raise NotFittedError("Estimator not fitted, "
"call `fit` before exploiting the model.")
return self.estimators_[0]._validate_X_predict(X, check_input=True)
2013-02-05 23:19:32 +08:00
@property
def feature_importances_(self):
"""Return the feature importances (the higher, the more important the
feature).
Returns
-------
feature_importances_ : array, shape = [n_features]
"""
if self.estimators_ is None or len(self.estimators_) == 0:
raise NotFittedError("Estimator not fitted, "
"call `fit` before `feature_importances_`.")
2013-02-05 23:19:32 +08:00
all_importances = Parallel(n_jobs=self.n_jobs,
backend="threading")(
delayed(getattr)(tree, 'feature_importances_')
for tree in self.estimators_)
return sum(all_importances) / len(self.estimators_)
2013-02-05 23:19:32 +08:00
2011-11-12 18:29:38 +08:00
2013-05-02 21:46:25 +08:00
class ForestClassifier(six.with_metaclass(ABCMeta, BaseForest,
ClassifierMixin)):
2011-11-12 18:29:38 +08:00
"""Base class for forest of trees-based classifiers.
2011-11-12 23:20:43 +08:00
Warning: This class should not be used directly. Use derived classes
instead.
"""
@abstractmethod
2012-11-26 21:57:51 +08:00
def __init__(self,
base_estimator,
n_estimators=10,
estimator_params=tuple(),
bootstrap=False,
oob_score=False,
n_jobs=1,
random_state=None,
2014-07-23 04:08:46 +08:00
verbose=0,
2014-12-12 08:22:26 +08:00
warm_start=False,
class_weight=None):
2011-11-12 18:29:38 +08:00
super(ForestClassifier, self).__init__(
base_estimator,
n_estimators=n_estimators,
estimator_params=estimator_params,
2011-11-12 18:29:38 +08:00
bootstrap=bootstrap,
oob_score=oob_score,
n_jobs=n_jobs,
random_state=random_state,
2014-07-23 04:08:46 +08:00
verbose=verbose,
2014-12-12 08:22:26 +08:00
warm_start=warm_start,
class_weight=class_weight)
2011-11-12 18:29:38 +08:00
def _set_oob_score(self, X, y):
"""Compute out-of-bag score"""
X = check_array(X, dtype=DTYPE, accept_sparse='csr')
n_classes_ = self.n_classes_
n_samples = y.shape[0]
oob_decision_function = []
oob_score = 0.0
predictions = []
for k in range(self.n_outputs_):
predictions.append(np.zeros((n_samples, n_classes_[k])))
for estimator in self.estimators_:
2015-06-02 20:12:30 +08:00
unsampled_indices = _generate_unsampled_indices(
estimator.random_state, n_samples)
2015-06-02 20:06:20 +08:00
p_estimator = estimator.predict_proba(X[unsampled_indices, :],
check_input=False)
if self.n_outputs_ == 1:
p_estimator = [p_estimator]
for k in range(self.n_outputs_):
2015-06-02 20:06:20 +08:00
predictions[k][unsampled_indices, :] += p_estimator[k]
for k in range(self.n_outputs_):
if (predictions[k].sum(axis=1) == 0).any():
warn("Some inputs do not have OOB scores. "
"This probably means too few trees were used "
"to compute any reliable oob estimates.")
decision = (predictions[k] /
predictions[k].sum(axis=1)[:, np.newaxis])
oob_decision_function.append(decision)
oob_score += np.mean(y[:, k] ==
np.argmax(predictions[k], axis=1), axis=0)
if self.n_outputs_ == 1:
self.oob_decision_function_ = oob_decision_function[0]
else:
self.oob_decision_function_ = oob_decision_function
self.oob_score_ = oob_score / self.n_outputs_
2015-01-11 03:49:42 +08:00
def _validate_y_class_weight(self, y):
check_classification_targets(y)
2015-01-11 03:49:42 +08:00
y = np.copy(y)
expanded_class_weight = None
if self.class_weight is not None:
y_original = np.copy(y)
self.classes_ = []
self.n_classes_ = []
2015-06-24 23:22:01 +08:00
y_store_unique_indices = np.zeros(y.shape, dtype=np.int)
for k in range(self.n_outputs_):
2015-06-24 23:22:01 +08:00
classes_k, y_store_unique_indices[:, k] = np.unique(y[:, k], return_inverse=True)
self.classes_.append(classes_k)
self.n_classes_.append(classes_k.shape[0])
2015-06-24 23:22:01 +08:00
y = y_store_unique_indices
if self.class_weight is not None:
2015-10-21 16:23:36 +08:00
valid_presets = ('auto', 'balanced', 'subsample', 'balanced_subsample')
if isinstance(self.class_weight, six.string_types):
if self.class_weight not in valid_presets:
raise ValueError('Valid presets for class_weight include '
'"balanced" and "balanced_subsample". Given "%s".'
% self.class_weight)
2015-10-21 16:23:36 +08:00
if self.class_weight == "subsample":
warn("class_weight='subsample' is deprecated in 0.17 and"
"will be removed in 0.19. It was replaced by "
"class_weight='balanced_subsample' using the balanced"
"strategy.", DeprecationWarning)
if self.warm_start:
warn('class_weight presets "balanced" or "balanced_subsample" are '
'not recommended for warm_start if the fitted data '
'differs from the full dataset. In order to use '
'"balanced" weights, use compute_class_weight("balanced", '
'classes, y). In place of y you can use a large '
'enough sample of the full training set target to '
'properly estimate the class frequency '
'distributions. Pass the resulting weights as the '
'class_weight parameter.')
2015-10-21 16:23:36 +08:00
if (self.class_weight not in ['subsample', 'balanced_subsample'] or
not self.bootstrap):
2015-10-21 16:23:36 +08:00
if self.class_weight == 'subsample':
class_weight = 'auto'
elif self.class_weight == "balanced_subsample":
class_weight = "balanced"
else:
class_weight = self.class_weight
with warnings.catch_warnings():
if class_weight == "auto":
warnings.simplefilter('ignore', DeprecationWarning)
expanded_class_weight = compute_sample_weight(class_weight,
y_original)
2015-01-11 03:49:42 +08:00
return y, expanded_class_weight
2011-11-12 18:29:38 +08:00
def predict(self, X):
"""Predict class for X.
The predicted class of an input sample is a vote by the trees in
the forest, weighted by their probability estimates. That is,
the predicted class is the one with highest mean probability
estimate across the trees.
2011-11-12 18:29:38 +08:00
Parameters
----------
X : array-like or sparse matrix of shape = [n_samples, n_features]
The input samples. Internally, it will be converted to
``dtype=np.float32`` and if a sparse matrix is provided
to a sparse ``csr_matrix``.
2011-11-12 18:29:38 +08:00
Returns
-------
2012-07-02 17:51:50 +08:00
y : array of shape = [n_samples] or [n_samples, n_outputs]
2011-11-12 18:29:38 +08:00
The predicted classes.
"""
2012-12-05 05:10:09 +08:00
proba = self.predict_proba(X)
2012-07-02 17:05:09 +08:00
if self.n_outputs_ == 1:
2012-12-05 05:10:09 +08:00
return self.classes_.take(np.argmax(proba, axis=1), axis=0)
2012-07-02 17:05:09 +08:00
else:
n_samples = proba[0].shape[0]
predictions = np.zeros((n_samples, self.n_outputs_))
2012-07-02 17:05:09 +08:00
for k in range(self.n_outputs_):
2012-12-05 05:10:09 +08:00
predictions[:, k] = self.classes_[k].take(np.argmax(proba[k],
2012-12-04 23:35:44 +08:00
axis=1),
axis=0)
2012-07-02 17:05:09 +08:00
return predictions
2011-11-12 18:29:38 +08:00
def predict_proba(self, X):
"""Predict class probabilities for X.
The predicted class probabilities of an input sample is computed as
2015-02-25 06:04:57 +08:00
the mean predicted class probabilities of the trees in the forest. The
class probability of a single tree is the fraction of samples of the same
class in a leaf.
2011-11-12 18:29:38 +08:00
Parameters
----------
X : array-like or sparse matrix of shape = [n_samples, n_features]
The input samples. Internally, it will be converted to
``dtype=np.float32`` and if a sparse matrix is provided
to a sparse ``csr_matrix``.
2011-11-12 18:29:38 +08:00
Returns
-------
2012-07-02 18:11:27 +08:00
p : array of shape = [n_samples, n_classes], or a list of n_outputs
such arrays if n_outputs > 1.
The class probabilities of the input samples. The order of the
classes corresponds to that in the attribute `classes_`.
2011-11-12 18:29:38 +08:00
"""
2011-12-21 03:03:25 +08:00
# Check data
X = self._validate_X_predict(X)
2011-11-22 16:54:46 +08:00
# Assign chunk of trees to jobs
n_jobs, _, _ = _partition_estimators(self.n_estimators, self.n_jobs)
# Parallel loop
2013-12-23 01:09:41 +08:00
all_proba = Parallel(n_jobs=n_jobs, verbose=self.verbose,
backend="threading")(
delayed(_parallel_helper)(e, 'predict_proba', X,
check_input=False)
for e in self.estimators_)
# Reduce
proba = all_proba[0]
if self.n_outputs_ == 1:
for j in range(1, len(all_proba)):
proba += all_proba[j]
proba /= len(self.estimators_)
2012-07-02 17:05:09 +08:00
else:
for j in range(1, len(all_proba)):
for k in range(self.n_outputs_):
proba[k] += all_proba[j][k]
for k in range(self.n_outputs_):
2012-12-05 05:10:09 +08:00
proba[k] /= self.n_estimators
2012-12-05 05:10:09 +08:00
return proba
2011-11-12 18:29:38 +08:00
def predict_log_proba(self, X):
"""Predict class log-probabilities for X.
The predicted class log-probabilities of an input sample is computed as
2013-09-09 14:38:46 +08:00
the log of the mean predicted class probabilities of the trees in the
forest.
2011-11-12 18:29:38 +08:00
Parameters
----------
X : array-like or sparse matrix of shape = [n_samples, n_features]
The input samples. Internally, it will be converted to
``dtype=np.float32`` and if a sparse matrix is provided
to a sparse ``csr_matrix``.
2011-11-12 18:29:38 +08:00
Returns
-------
2012-07-02 18:11:27 +08:00
p : array of shape = [n_samples, n_classes], or a list of n_outputs
such arrays if n_outputs > 1.
The class probabilities of the input samples. The order of the
classes corresponds to that in the attribute `classes_`.
2011-11-12 18:29:38 +08:00
"""
2012-07-02 17:51:50 +08:00
proba = self.predict_proba(X)
if self.n_outputs_ == 1:
return np.log(proba)
else:
for k in range(self.n_outputs_):
2012-07-02 17:51:50 +08:00
proba[k] = np.log(proba[k])
return proba
2011-11-12 18:29:38 +08:00
2011-11-12 23:20:43 +08:00
2013-04-04 03:07:20 +08:00
class ForestRegressor(six.with_metaclass(ABCMeta, BaseForest, RegressorMixin)):
2011-11-12 18:29:38 +08:00
"""Base class for forest of trees-based regressors.
2011-11-12 23:20:43 +08:00
Warning: This class should not be used directly. Use derived classes
instead.
"""
@abstractmethod
2012-11-26 21:57:51 +08:00
def __init__(self,
base_estimator,
n_estimators=10,
estimator_params=tuple(),
bootstrap=False,
oob_score=False,
n_jobs=1,
random_state=None,
2014-07-23 04:08:46 +08:00
verbose=0,
warm_start=False):
2011-11-12 18:29:38 +08:00
super(ForestRegressor, self).__init__(
base_estimator,
n_estimators=n_estimators,
estimator_params=estimator_params,
2011-11-12 18:29:38 +08:00
bootstrap=bootstrap,
oob_score=oob_score,
n_jobs=n_jobs,
random_state=random_state,
2014-07-23 04:08:46 +08:00
verbose=verbose,
warm_start=warm_start)
2011-11-12 18:29:38 +08:00
def predict(self, X):
"""Predict regression target for X.
The predicted regression target of an input sample is computed as the
mean predicted regression targets of the trees in the forest.
Parameters
----------
X : array-like or sparse matrix of shape = [n_samples, n_features]
The input samples. Internally, it will be converted to
``dtype=np.float32`` and if a sparse matrix is provided
to a sparse ``csr_matrix``.
2011-11-12 18:29:38 +08:00
Returns
-------
2014-12-01 09:59:42 +08:00
y : array of shape = [n_samples] or [n_samples, n_outputs]
2011-11-12 18:29:38 +08:00
The predicted values.
"""
2011-12-21 03:03:25 +08:00
# Check data
X = self._validate_X_predict(X)
2011-11-12 18:29:38 +08:00
# Assign chunk of trees to jobs
n_jobs, _, _ = _partition_estimators(self.n_estimators, self.n_jobs)
# Parallel loop
all_y_hat = Parallel(n_jobs=n_jobs, verbose=self.verbose,
backend="threading")(
delayed(_parallel_helper)(e, 'predict', X, check_input=False)
for e in self.estimators_)
# Reduce
y_hat = sum(all_y_hat) / len(self.estimators_)
2011-11-12 18:29:38 +08:00
return y_hat
def _set_oob_score(self, X, y):
"""Compute out-of-bag scores"""
X = check_array(X, dtype=DTYPE, accept_sparse='csr')
n_samples = y.shape[0]
predictions = np.zeros((n_samples, self.n_outputs_))
n_predictions = np.zeros((n_samples, self.n_outputs_))
for estimator in self.estimators_:
2015-06-02 20:12:30 +08:00
unsampled_indices = _generate_unsampled_indices(
estimator.random_state, n_samples)
p_estimator = estimator.predict(
X[unsampled_indices, :], check_input=False)
if self.n_outputs_ == 1:
p_estimator = p_estimator[:, np.newaxis]
2015-06-02 20:06:20 +08:00
predictions[unsampled_indices, :] += p_estimator
n_predictions[unsampled_indices, :] += 1
if (n_predictions == 0).any():
warn("Some inputs do not have OOB scores. "
"This probably means too few trees were used "
"to compute any reliable oob estimates.")
n_predictions[n_predictions == 0] = 1
predictions /= n_predictions
self.oob_prediction_ = predictions
if self.n_outputs_ == 1:
self.oob_prediction_ = \
self.oob_prediction_.reshape((n_samples, ))
self.oob_score_ = 0.0
for k in range(self.n_outputs_):
self.oob_score_ += r2_score(y[:, k],
predictions[:, k])
self.oob_score_ /= self.n_outputs_
2011-11-12 18:29:38 +08:00
class RandomForestClassifier(ForestClassifier):
"""A random forest classifier.
2011-11-12 18:29:38 +08:00
2013-06-29 20:57:41 +08:00
A random forest is a meta estimator that fits a number of decision tree
classifiers on various sub-samples of the dataset and use averaging to
improve the predictive accuracy and control over-fitting.
2015-07-07 11:52:43 +08:00
The sub-sample size is always the same as the original
input sample size but the samples are drawn with replacement if
`bootstrap=True` (default).
2015-06-03 12:24:04 +08:00
Read more in the :ref:`User Guide <forest>`.
2011-11-12 18:29:38 +08:00
Parameters
----------
n_estimators : integer, optional (default=10)
2011-11-12 18:29:38 +08:00
The number of trees in the forest.
criterion : string, optional (default="gini")
The function to measure the quality of a split. Supported criteria are
"gini" for the Gini impurity and "entropy" for the information gain.
Note: this parameter is tree-specific.
max_features : int, float, string or None, optional (default="auto")
2012-12-23 20:13:21 +08:00
The number of features to consider when looking for the best split:
2014-06-07 22:38:53 +08:00
- If int, then consider `max_features` features at each split.
- If float, then `max_features` is a percentage and
`int(max_features * n_features)` features are considered at each
split.
- If "auto", then `max_features=sqrt(n_features)`.
2015-07-07 11:52:43 +08:00
- If "sqrt", then `max_features=sqrt(n_features)` (same as "auto").
2014-06-07 22:38:53 +08:00
- If "log2", then `max_features=log2(n_features)`.
- If None, then `max_features=n_features`.
2013-01-17 07:04:40 +08:00
Note: the search for a split does not stop until at least one
valid partition of the node samples is found, even if it requires to
effectively inspect more than ``max_features`` features.
2012-12-23 20:13:21 +08:00
Note: this parameter is tree-specific.
max_depth : integer or None, optional (default=None)
The maximum depth of the tree. If None, then nodes are expanded until
all leaves are pure or until all leaves contain less than
min_samples_split samples.
Ignored if ``max_leaf_nodes`` is not None.
Note: this parameter is tree-specific.
min_samples_split : integer, optional (default=2)
The minimum number of samples required to split an internal node.
Note: this parameter is tree-specific.
min_samples_leaf : integer, optional (default=1)
2012-02-16 18:29:52 +08:00
The minimum number of samples in newly created leaves. A split is
discarded if after the split, one of the leaves would contain less then
``min_samples_leaf`` samples.
Note: this parameter is tree-specific.
2014-06-03 05:24:30 +08:00
min_weight_fraction_leaf : float, optional (default=0.)
The minimum weighted fraction of the input samples required to be at a
leaf node.
Note: this parameter is tree-specific.
2013-12-01 01:34:13 +08:00
max_leaf_nodes : int or None, optional (default=None)
Grow trees with ``max_leaf_nodes`` in best-first fashion.
Best nodes are defined as relative reduction in impurity.
If None then unlimited number of leaf nodes.
If not None then ``max_depth`` will be ignored.
2013-12-01 01:34:13 +08:00
Note: this parameter is tree-specific.
2011-11-12 18:29:38 +08:00
bootstrap : boolean, optional (default=True)
Whether bootstrap samples are used when building trees.
oob_score : bool
Whether to use out-of-bag samples to estimate
the generalization error.
2011-12-20 23:48:32 +08:00
n_jobs : integer, optional (default=1)
The number of jobs to run in parallel for both `fit` and `predict`.
If -1, then the number of jobs is set to the number of cores.
2011-12-20 23:48:32 +08:00
2011-11-12 18:29:38 +08:00
random_state : int, RandomState instance or None, optional (default=None)
If int, random_state is the seed used by the random number generator;
If RandomState instance, random_state is the random number generator;
If None, the random number generator is the RandomState instance used
by `np.random`.
verbose : int, optional (default=0)
Controls the verbosity of the tree building process.
2014-07-23 04:08:46 +08:00
warm_start : bool, optional (default=False)
When set to ``True``, reuse the solution of the previous call to fit
and add more estimators to the ensemble, otherwise, just fit a whole
new forest.
class_weight : dict, list of dicts, "balanced", "balanced_subsample" or None, optional
Weights associated with classes in the form ``{class_label: weight}``.
If not given, all classes are supposed to have weight one. For
multi-output problems, a list of dicts can be provided in the same
order as the columns of y.
2014-12-12 08:22:26 +08:00
The "balanced" mode uses the values of y to automatically adjust
weights inversely proportional to class frequencies in the input data
as ``n_samples / (n_classes * np.bincount(y))``
2014-12-12 08:22:26 +08:00
The "balanced_subsample" mode is the same as "balanced" except that weights are
computed based on the bootstrap sample for every tree grown.
2014-12-12 08:22:26 +08:00
For multi-output, the weights of each column of y will be multiplied.
Note that these weights will be multiplied with sample_weight (passed
through the fit method) if sample_weight is specified.
2014-12-12 08:22:26 +08:00
2011-12-28 00:44:04 +08:00
Attributes
----------
estimators_ : list of DecisionTreeClassifier
The collection of fitted sub-estimators.
classes_ : array of shape = [n_classes] or a list of such arrays
2012-12-23 20:13:21 +08:00
The classes labels (single output problem), or a list of arrays of
class labels (multi-output problem).
n_classes_ : int or list
2012-12-23 20:13:21 +08:00
The number of classes (single output problem), or a list containing the
number of classes for each output (multi-output problem).
2015-05-12 21:00:27 +08:00
n_features_ : int
The number of features when ``fit`` is performed.
n_outputs_ : int
The number of outputs when ``fit`` is performed.
feature_importances_ : array of shape = [n_features]
The feature importances (the higher, the more important the feature).
oob_score_ : float
Score of the training dataset obtained using an out-of-bag estimate.
oob_decision_function_ : array of shape = [n_samples, n_classes]
2012-01-23 17:02:01 +08:00
Decision function computed with out-of-bag estimate on the training
set. If n_estimators is small it might be possible that a data point
was never left out during the bootstrap. In this case,
`oob_decision_function_` might contain NaN.
References
----------
.. [1] L. Breiman, "Random Forests", Machine Learning, 45(1), 5-32, 2001.
2011-11-12 18:29:38 +08:00
See also
--------
2012-01-09 16:12:13 +08:00
DecisionTreeClassifier, ExtraTreesClassifier
2011-11-12 18:29:38 +08:00
"""
2012-11-26 21:57:51 +08:00
def __init__(self,
n_estimators=10,
criterion="gini",
max_depth=None,
min_samples_split=2,
2012-11-26 21:57:51 +08:00
min_samples_leaf=1,
2014-06-03 05:24:30 +08:00
min_weight_fraction_leaf=0.,
2012-11-26 21:57:51 +08:00
max_features="auto",
2013-12-01 01:34:13 +08:00
max_leaf_nodes=None,
2012-11-26 21:57:51 +08:00
bootstrap=True,
oob_score=False,
n_jobs=1,
random_state=None,
2014-07-23 04:08:46 +08:00
verbose=0,
2014-12-12 08:22:26 +08:00
warm_start=False,
class_weight=None):
2011-11-12 18:29:38 +08:00
super(RandomForestClassifier, self).__init__(
base_estimator=DecisionTreeClassifier(),
n_estimators=n_estimators,
estimator_params=("criterion", "max_depth", "min_samples_split",
2014-06-03 05:24:30 +08:00
"min_samples_leaf", "min_weight_fraction_leaf",
"max_features", "max_leaf_nodes",
"random_state"),
2011-11-12 18:29:38 +08:00
bootstrap=bootstrap,
oob_score=oob_score,
n_jobs=n_jobs,
random_state=random_state,
2014-07-23 04:08:46 +08:00
verbose=verbose,
2014-12-12 08:22:26 +08:00
warm_start=warm_start,
class_weight=class_weight)
self.criterion = criterion
self.max_depth = max_depth
self.min_samples_split = min_samples_split
self.min_samples_leaf = min_samples_leaf
2014-06-03 05:24:30 +08:00
self.min_weight_fraction_leaf = min_weight_fraction_leaf
self.max_features = max_features
2013-12-01 01:34:13 +08:00
self.max_leaf_nodes = max_leaf_nodes
2011-11-12 18:29:38 +08:00
class RandomForestRegressor(ForestRegressor):
"""A random forest regressor.
2011-11-12 18:29:38 +08:00
2013-06-27 21:09:16 +08:00
A random forest is a meta estimator that fits a number of classifying
decision trees on various sub-samples of the dataset and use averaging
to improve the predictive accuracy and control over-fitting.
2015-07-07 11:52:43 +08:00
The sub-sample size is always the same as the original
input sample size but the samples are drawn with replacement if
`bootstrap=True` (default).
2015-06-03 12:24:04 +08:00
Read more in the :ref:`User Guide <forest>`.
2011-11-12 18:29:38 +08:00
Parameters
----------
n_estimators : integer, optional (default=10)
2011-11-12 18:29:38 +08:00
The number of trees in the forest.
criterion : string, optional (default="mse")
The function to measure the quality of a split. The only supported
criterion is "mse" for the mean squared error.
Note: this parameter is tree-specific.
max_features : int, float, string or None, optional (default="auto")
2012-12-23 20:13:21 +08:00
The number of features to consider when looking for the best split:
2014-06-07 22:38:53 +08:00
- If int, then consider `max_features` features at each split.
- If float, then `max_features` is a percentage and
`int(max_features * n_features)` features are considered at each
split.
- If "auto", then `max_features=n_features`.
- If "sqrt", then `max_features=sqrt(n_features)`.
- If "log2", then `max_features=log2(n_features)`.
- If None, then `max_features=n_features`.
2013-01-17 07:04:40 +08:00
Note: the search for a split does not stop until at least one
valid partition of the node samples is found, even if it requires to
effectively inspect more than ``max_features`` features.
2012-12-23 20:13:21 +08:00
Note: this parameter is tree-specific.
max_depth : integer or None, optional (default=None)
The maximum depth of the tree. If None, then nodes are expanded until
all leaves are pure or until all leaves contain less than
min_samples_split samples.
Ignored if ``max_leaf_nodes`` is not None.
Note: this parameter is tree-specific.
min_samples_split : integer, optional (default=2)
The minimum number of samples required to split an internal node.
Note: this parameter is tree-specific.
min_samples_leaf : integer, optional (default=1)
2012-02-16 18:29:52 +08:00
The minimum number of samples in newly created leaves. A split is
discarded if after the split, one of the leaves would contain less then
``min_samples_leaf`` samples.
Note: this parameter is tree-specific.
2014-06-03 05:24:30 +08:00
min_weight_fraction_leaf : float, optional (default=0.)
The minimum weighted fraction of the input samples required to be at a
leaf node.
Note: this parameter is tree-specific.
2013-12-01 01:34:13 +08:00
max_leaf_nodes : int or None, optional (default=None)
Grow trees with ``max_leaf_nodes`` in best-first fashion.
Best nodes are defined as relative reduction in impurity.
If None then unlimited number of leaf nodes.
If not None then ``max_depth`` will be ignored.
2013-12-01 01:34:13 +08:00
Note: this parameter is tree-specific.
2011-11-12 18:29:38 +08:00
bootstrap : boolean, optional (default=True)
Whether bootstrap samples are used when building trees.
oob_score : bool
whether to use out-of-bag samples to estimate
the generalization error.
2011-12-20 23:48:32 +08:00
n_jobs : integer, optional (default=1)
The number of jobs to run in parallel for both `fit` and `predict`.
If -1, then the number of jobs is set to the number of cores.
2011-12-20 23:48:32 +08:00
2011-11-12 18:29:38 +08:00
random_state : int, RandomState instance or None, optional (default=None)
If int, random_state is the seed used by the random number generator;
If RandomState instance, random_state is the random number generator;
If None, the random number generator is the RandomState instance used
by `np.random`.
verbose : int, optional (default=0)
Controls the verbosity of the tree building process.
2014-07-23 04:08:46 +08:00
warm_start : bool, optional (default=False)
When set to ``True``, reuse the solution of the previous call to fit
and add more estimators to the ensemble, otherwise, just fit a whole
new forest.
2011-12-28 00:44:04 +08:00
Attributes
----------
estimators_ : list of DecisionTreeRegressor
The collection of fitted sub-estimators.
feature_importances_ : array of shape = [n_features]
2013-06-27 21:09:16 +08:00
The feature importances (the higher, the more important the feature).
2011-12-28 00:44:04 +08:00
2015-05-12 21:00:27 +08:00
n_features_ : int
The number of features when ``fit`` is performed.
n_outputs_ : int
The number of outputs when ``fit`` is performed.
oob_score_ : float
Score of the training dataset obtained using an out-of-bag estimate.
oob_prediction_ : array of shape = [n_samples]
Prediction computed with out-of-bag estimate on the training set.
References
----------
.. [1] L. Breiman, "Random Forests", Machine Learning, 45(1), 5-32, 2001.
2011-11-12 18:29:38 +08:00
See also
--------
2012-01-09 16:12:13 +08:00
DecisionTreeRegressor, ExtraTreesRegressor
2011-11-12 18:29:38 +08:00
"""
2012-11-26 21:57:51 +08:00
def __init__(self,
n_estimators=10,
criterion="mse",
max_depth=None,
min_samples_split=2,
2012-11-26 21:57:51 +08:00
min_samples_leaf=1,
2014-06-03 05:24:30 +08:00
min_weight_fraction_leaf=0.,
2012-11-26 21:57:51 +08:00
max_features="auto",
2013-12-01 01:34:13 +08:00
max_leaf_nodes=None,
2012-11-26 21:57:51 +08:00
bootstrap=True,
oob_score=False,
n_jobs=1,
random_state=None,
2014-07-23 04:08:46 +08:00
verbose=0,
warm_start=False):
2011-11-12 18:29:38 +08:00
super(RandomForestRegressor, self).__init__(
base_estimator=DecisionTreeRegressor(),
n_estimators=n_estimators,
estimator_params=("criterion", "max_depth", "min_samples_split",
2014-06-03 05:24:30 +08:00
"min_samples_leaf", "min_weight_fraction_leaf",
"max_features", "max_leaf_nodes",
"random_state"),
2011-11-12 18:29:38 +08:00
bootstrap=bootstrap,
oob_score=oob_score,
n_jobs=n_jobs,
random_state=random_state,
2014-07-23 04:08:46 +08:00
verbose=verbose,
warm_start=warm_start)
self.criterion = criterion
self.max_depth = max_depth
self.min_samples_split = min_samples_split
self.min_samples_leaf = min_samples_leaf
2014-06-03 05:24:30 +08:00
self.min_weight_fraction_leaf = min_weight_fraction_leaf
self.max_features = max_features
2013-12-01 01:34:13 +08:00
self.max_leaf_nodes = max_leaf_nodes
2011-11-12 18:29:38 +08:00
class ExtraTreesClassifier(ForestClassifier):
"""An extra-trees classifier.
2011-11-12 18:29:38 +08:00
This class implements a meta estimator that fits a number of
randomized decision trees (a.k.a. extra-trees) on various sub-samples
of the dataset and use averaging to improve the predictive accuracy
and control over-fitting.
2015-06-03 12:24:04 +08:00
Read more in the :ref:`User Guide <forest>`.
2011-11-12 18:29:38 +08:00
Parameters
----------
n_estimators : integer, optional (default=10)
2011-11-12 18:29:38 +08:00
The number of trees in the forest.
criterion : string, optional (default="gini")
The function to measure the quality of a split. Supported criteria are
"gini" for the Gini impurity and "entropy" for the information gain.
Note: this parameter is tree-specific.
max_features : int, float, string or None, optional (default="auto")
The number of features to consider when looking for the best split:
2014-06-07 22:38:53 +08:00
- If int, then consider `max_features` features at each split.
- If float, then `max_features` is a percentage and
`int(max_features * n_features)` features are considered at each
split.
- If "auto", then `max_features=sqrt(n_features)`.
- If "sqrt", then `max_features=sqrt(n_features)`.
- If "log2", then `max_features=log2(n_features)`.
- If None, then `max_features=n_features`.
2013-01-17 07:04:40 +08:00
Note: the search for a split does not stop until at least one
valid partition of the node samples is found, even if it requires to
effectively inspect more than ``max_features`` features.
2012-12-23 20:13:21 +08:00
Note: this parameter is tree-specific.
max_depth : integer or None, optional (default=None)
The maximum depth of the tree. If None, then nodes are expanded until
all leaves are pure or until all leaves contain less than
min_samples_split samples.
Ignored if ``max_leaf_nodes`` is not None.
Note: this parameter is tree-specific.
min_samples_split : integer, optional (default=2)
The minimum number of samples required to split an internal node.
Note: this parameter is tree-specific.
min_samples_leaf : integer, optional (default=1)
2012-02-16 18:29:52 +08:00
The minimum number of samples in newly created leaves. A split is
discarded if after the split, one of the leaves would contain less then
``min_samples_leaf`` samples.
Note: this parameter is tree-specific.
2014-06-03 05:24:30 +08:00
min_weight_fraction_leaf : float, optional (default=0.)
The minimum weighted fraction of the input samples required to be at a
leaf node.
Note: this parameter is tree-specific.
2013-12-01 01:34:13 +08:00
max_leaf_nodes : int or None, optional (default=None)
Grow trees with ``max_leaf_nodes`` in best-first fashion.
Best nodes are defined as relative reduction in impurity.
If None then unlimited number of leaf nodes.
If not None then ``max_depth`` will be ignored.
2013-12-01 01:34:13 +08:00
Note: this parameter is tree-specific.
bootstrap : boolean, optional (default=False)
2011-11-12 18:29:38 +08:00
Whether bootstrap samples are used when building trees.
oob_score : bool
Whether to use out-of-bag samples to estimate
the generalization error.
2011-12-20 23:48:32 +08:00
n_jobs : integer, optional (default=1)
The number of jobs to run in parallel for both `fit` and `predict`.
If -1, then the number of jobs is set to the number of cores.
2011-12-20 23:48:32 +08:00
2011-11-12 18:29:38 +08:00
random_state : int, RandomState instance or None, optional (default=None)
If int, random_state is the seed used by the random number generator;
If RandomState instance, random_state is the random number generator;
If None, the random number generator is the RandomState instance used
by `np.random`.
verbose : int, optional (default=0)
Controls the verbosity of the tree building process.
2014-07-23 04:08:46 +08:00
warm_start : bool, optional (default=False)
When set to ``True``, reuse the solution of the previous call to fit
and add more estimators to the ensemble, otherwise, just fit a whole
new forest.
class_weight : dict, list of dicts, "balanced", "balanced_subsample" or None, optional
Weights associated with classes in the form ``{class_label: weight}``.
If not given, all classes are supposed to have weight one. For
multi-output problems, a list of dicts can be provided in the same
order as the columns of y.
2014-12-12 08:22:26 +08:00
The "balanced" mode uses the values of y to automatically adjust
weights inversely proportional to class frequencies in the input data
as ``n_samples / (n_classes * np.bincount(y))``
2014-12-12 08:22:26 +08:00
The "balanced_subsample" mode is the same as "balanced" except that weights are
computed based on the bootstrap sample for every tree grown.
2014-12-12 08:22:26 +08:00
For multi-output, the weights of each column of y will be multiplied.
Note that these weights will be multiplied with sample_weight (passed
through the fit method) if sample_weight is specified.
2014-12-12 08:22:26 +08:00
2011-12-28 00:44:04 +08:00
Attributes
----------
estimators_ : list of DecisionTreeClassifier
The collection of fitted sub-estimators.
classes_ : array of shape = [n_classes] or a list of such arrays
2012-12-23 20:13:21 +08:00
The classes labels (single output problem), or a list of arrays of
class labels (multi-output problem).
n_classes_ : int or list
2012-12-23 20:13:21 +08:00
The number of classes (single output problem), or a list containing the
number of classes for each output (multi-output problem).
feature_importances_ : array of shape = [n_features]
2013-06-27 21:09:16 +08:00
The feature importances (the higher, the more important the feature).
2011-12-28 00:44:04 +08:00
2015-05-12 21:00:27 +08:00
n_features_ : int
The number of features when ``fit`` is performed.
n_outputs_ : int
The number of outputs when ``fit`` is performed.
oob_score_ : float
Score of the training dataset obtained using an out-of-bag estimate.
oob_decision_function_ : array of shape = [n_samples, n_classes]
2012-01-23 17:02:01 +08:00
Decision function computed with out-of-bag estimate on the training
set. If n_estimators is small it might be possible that a data point
was never left out during the bootstrap. In this case,
`oob_decision_function_` might contain NaN.
References
----------
.. [1] P. Geurts, D. Ernst., and L. Wehenkel, "Extremely randomized trees",
Machine Learning, 63(1), 3-42, 2006.
2011-11-12 18:29:38 +08:00
See also
--------
2012-01-23 17:02:01 +08:00
sklearn.tree.ExtraTreeClassifier : Base classifier for this ensemble.
RandomForestClassifier : Ensemble Classifier based on trees with optimal
splits.
2011-11-12 18:29:38 +08:00
"""
2012-11-26 21:57:51 +08:00
def __init__(self,
n_estimators=10,
criterion="gini",
max_depth=None,
min_samples_split=2,
2012-11-26 21:57:51 +08:00
min_samples_leaf=1,
2014-06-03 05:24:30 +08:00
min_weight_fraction_leaf=0.,
2012-11-26 21:57:51 +08:00
max_features="auto",
2013-12-01 01:34:13 +08:00
max_leaf_nodes=None,
2012-11-26 21:57:51 +08:00
bootstrap=False,
oob_score=False,
n_jobs=1,
random_state=None,
2014-07-23 04:08:46 +08:00
verbose=0,
2014-12-12 08:22:26 +08:00
warm_start=False,
class_weight=None):
2011-11-12 18:29:38 +08:00
super(ExtraTreesClassifier, self).__init__(
base_estimator=ExtraTreeClassifier(),
n_estimators=n_estimators,
estimator_params=("criterion", "max_depth", "min_samples_split",
2014-06-03 05:24:30 +08:00
"min_samples_leaf", "min_weight_fraction_leaf",
"max_features", "max_leaf_nodes", "random_state"),
2011-11-12 18:29:38 +08:00
bootstrap=bootstrap,
oob_score=oob_score,
n_jobs=n_jobs,
random_state=random_state,
2014-07-23 04:08:46 +08:00
verbose=verbose,
2014-12-12 08:22:26 +08:00
warm_start=warm_start,
class_weight=class_weight)
self.criterion = criterion
self.max_depth = max_depth
self.min_samples_split = min_samples_split
self.min_samples_leaf = min_samples_leaf
2014-06-03 05:24:30 +08:00
self.min_weight_fraction_leaf = min_weight_fraction_leaf
self.max_features = max_features
2013-12-01 01:34:13 +08:00
self.max_leaf_nodes = max_leaf_nodes
2011-11-12 18:29:38 +08:00
class ExtraTreesRegressor(ForestRegressor):
"""An extra-trees regressor.
2011-11-12 18:29:38 +08:00
This class implements a meta estimator that fits a number of
randomized decision trees (a.k.a. extra-trees) on various sub-samples
of the dataset and use averaging to improve the predictive accuracy
and control over-fitting.
2015-06-03 12:24:04 +08:00
Read more in the :ref:`User Guide <forest>`.
2011-11-12 18:29:38 +08:00
Parameters
----------
n_estimators : integer, optional (default=10)
2011-11-12 18:29:38 +08:00
The number of trees in the forest.
criterion : string, optional (default="mse")
The function to measure the quality of a split. The only supported
criterion is "mse" for the mean squared error.
Note: this parameter is tree-specific.
max_features : int, float, string or None, optional (default="auto")
2012-12-23 20:13:21 +08:00
The number of features to consider when looking for the best split:
2014-06-07 22:38:53 +08:00
- If int, then consider `max_features` features at each split.
- If float, then `max_features` is a percentage and
`int(max_features * n_features)` features are considered at each
split.
- If "auto", then `max_features=n_features`.
- If "sqrt", then `max_features=sqrt(n_features)`.
- If "log2", then `max_features=log2(n_features)`.
- If None, then `max_features=n_features`.
2013-01-17 07:04:40 +08:00
Note: the search for a split does not stop until at least one
valid partition of the node samples is found, even if it requires to
effectively inspect more than ``max_features`` features.
2012-12-23 20:13:21 +08:00
Note: this parameter is tree-specific.
max_depth : integer or None, optional (default=None)
The maximum depth of the tree. If None, then nodes are expanded until
all leaves are pure or until all leaves contain less than
min_samples_split samples.
Ignored if ``max_leaf_nodes`` is not None.
Note: this parameter is tree-specific.
min_samples_split : integer, optional (default=2)
The minimum number of samples required to split an internal node.
Note: this parameter is tree-specific.
min_samples_leaf : integer, optional (default=1)
2012-02-16 18:29:52 +08:00
The minimum number of samples in newly created leaves. A split is
discarded if after the split, one of the leaves would contain less then
``min_samples_leaf`` samples.
Note: this parameter is tree-specific.
2014-06-03 05:24:30 +08:00
min_weight_fraction_leaf : float, optional (default=0.)
The minimum weighted fraction of the input samples required to be at a
leaf node.
Note: this parameter is tree-specific.
2013-12-01 01:34:13 +08:00
max_leaf_nodes : int or None, optional (default=None)
Grow trees with ``max_leaf_nodes`` in best-first fashion.
Best nodes are defined as relative reduction in impurity.
If None then unlimited number of leaf nodes.
If not None then ``max_depth`` will be ignored.
2013-12-01 01:34:13 +08:00
Note: this parameter is tree-specific.
bootstrap : boolean, optional (default=False)
2011-11-12 18:29:38 +08:00
Whether bootstrap samples are used when building trees.
Note: this parameter is tree-specific.
2011-11-12 18:29:38 +08:00
oob_score : bool
Whether to use out-of-bag samples to estimate
the generalization error.
2011-12-20 23:48:32 +08:00
n_jobs : integer, optional (default=1)
The number of jobs to run in parallel for both `fit` and `predict`.
If -1, then the number of jobs is set to the number of cores.
2011-12-20 23:48:32 +08:00
2011-11-12 18:29:38 +08:00
random_state : int, RandomState instance or None, optional (default=None)
If int, random_state is the seed used by the random number generator;
If RandomState instance, random_state is the random number generator;
If None, the random number generator is the RandomState instance used
by `np.random`.
verbose : int, optional (default=0)
Controls the verbosity of the tree building process.
2014-07-23 04:08:46 +08:00
warm_start : bool, optional (default=False)
When set to ``True``, reuse the solution of the previous call to fit
and add more estimators to the ensemble, otherwise, just fit a whole
new forest.
2011-12-28 00:44:04 +08:00
Attributes
----------
estimators_ : list of DecisionTreeRegressor
The collection of fitted sub-estimators.
feature_importances_ : array of shape = [n_features]
2013-06-27 21:09:16 +08:00
The feature importances (the higher, the more important the feature).
2011-12-28 00:44:04 +08:00
2015-05-12 21:00:27 +08:00
n_features_ : int
The number of features.
n_outputs_ : int
The number of outputs.
oob_score_ : float
Score of the training dataset obtained using an out-of-bag estimate.
oob_prediction_ : array of shape = [n_samples]
Prediction computed with out-of-bag estimate on the training set.
References
----------
.. [1] P. Geurts, D. Ernst., and L. Wehenkel, "Extremely randomized trees",
Machine Learning, 63(1), 3-42, 2006.
2011-11-12 18:29:38 +08:00
See also
--------
2012-01-23 17:02:01 +08:00
sklearn.tree.ExtraTreeRegressor: Base estimator for this ensemble.
RandomForestRegressor: Ensemble regressor using trees with optimal splits.
2011-11-12 18:29:38 +08:00
"""
2012-11-26 21:57:51 +08:00
def __init__(self,
n_estimators=10,
criterion="mse",
max_depth=None,
min_samples_split=2,
2012-11-26 21:57:51 +08:00
min_samples_leaf=1,
2014-06-03 05:24:30 +08:00
min_weight_fraction_leaf=0.,
2012-11-26 21:57:51 +08:00
max_features="auto",
2013-12-01 01:34:13 +08:00
max_leaf_nodes=None,
2012-11-26 21:57:51 +08:00
bootstrap=False,
oob_score=False,
n_jobs=1,
random_state=None,
2014-07-23 04:08:46 +08:00
verbose=0,
warm_start=False):
2011-11-12 18:29:38 +08:00
super(ExtraTreesRegressor, self).__init__(
base_estimator=ExtraTreeRegressor(),
n_estimators=n_estimators,
estimator_params=("criterion", "max_depth", "min_samples_split",
2014-06-03 05:24:30 +08:00
"min_samples_leaf", "min_weight_fraction_leaf",
"max_features", "max_leaf_nodes",
"random_state"),
2011-11-12 18:29:38 +08:00
bootstrap=bootstrap,
oob_score=oob_score,
n_jobs=n_jobs,
random_state=random_state,
2014-07-23 04:08:46 +08:00
verbose=verbose,
warm_start=warm_start)
self.criterion = criterion
self.max_depth = max_depth
self.min_samples_split = min_samples_split
self.min_samples_leaf = min_samples_leaf
2014-06-03 05:24:30 +08:00
self.min_weight_fraction_leaf = min_weight_fraction_leaf
self.max_features = max_features
2013-12-01 01:34:13 +08:00
self.max_leaf_nodes = max_leaf_nodes
2012-10-28 17:00:39 +08:00
class RandomTreesEmbedding(BaseForest):
"""An ensemble of totally random trees.
2012-10-28 21:18:09 +08:00
An unsupervised transformation of a dataset to a high-dimensional
sparse representation. A datapoint is coded according to which leaf of
2012-10-30 18:25:21 +08:00
each tree it is sorted into. Using a one-hot encoding of the leaves,
this leads to a binary coding with as many ones as there are trees in
the forest.
2012-10-28 21:18:09 +08:00
The dimensionality of the resulting representation is
``n_out <= n_estimators * max_leaf_nodes``. If ``max_leaf_nodes == None``,
the number of leaf nodes is at most ``n_estimators * 2 ** max_depth``.
2012-10-28 21:18:09 +08:00
2015-06-03 12:24:04 +08:00
Read more in the :ref:`User Guide <random_trees_embedding>`.
2012-10-28 21:18:09 +08:00
Parameters
----------
n_estimators : int
Number of trees in the forest.
max_depth : int
The maximum depth of each tree. If None, then nodes are expanded until
all leaves are pure or until all leaves contain less than
min_samples_split samples.
Ignored if ``max_leaf_nodes`` is not None.
2012-10-28 21:18:09 +08:00
min_samples_split : integer, optional (default=2)
2012-10-28 21:18:09 +08:00
The minimum number of samples required to split an internal node.
min_samples_leaf : integer, optional (default=1)
The minimum number of samples in newly created leaves. A split is
discarded if after the split, one of the leaves would contain less then
``min_samples_leaf`` samples.
2014-06-03 05:24:30 +08:00
min_weight_fraction_leaf : float, optional (default=0.)
The minimum weighted fraction of the input samples required to be at a
leaf node.
2013-12-01 01:34:13 +08:00
max_leaf_nodes : int or None, optional (default=None)
Grow trees with ``max_leaf_nodes`` in best-first fashion.
Best nodes are defined as relative reduction in impurity.
If None then unlimited number of leaf nodes.
If not None then ``max_depth`` will be ignored.
2013-12-01 01:34:13 +08:00
2014-12-01 09:59:42 +08:00
sparse_output : bool, optional (default=True)
Whether or not to return a sparse CSR matrix, as default behavior,
or to return a dense array compatible with dense pipeline operators.
2012-10-28 21:18:09 +08:00
n_jobs : integer, optional (default=1)
The number of jobs to run in parallel for both `fit` and `predict`.
If -1, then the number of jobs is set to the number of cores.
2012-10-28 21:18:09 +08:00
random_state : int, RandomState instance or None, optional (default=None)
If int, random_state is the seed used by the random number generator;
If RandomState instance, random_state is the random number generator;
If None, the random number generator is the RandomState instance used
by `np.random`.
verbose : int, optional (default=0)
Controls the verbosity of the tree building process.
2014-07-23 04:08:46 +08:00
warm_start : bool, optional (default=False)
When set to ``True``, reuse the solution of the previous call to fit
and add more estimators to the ensemble, otherwise, just fit a whole
new forest.
2012-10-28 21:18:09 +08:00
Attributes
----------
estimators_ : list of DecisionTreeClassifier
2012-10-28 21:18:09 +08:00
The collection of fitted sub-estimators.
2012-11-11 00:20:49 +08:00
References
----------
.. [1] P. Geurts, D. Ernst., and L. Wehenkel, "Extremely randomized trees",
Machine Learning, 63(1), 3-42, 2006.
.. [2] Moosmann, F. and Triggs, B. and Jurie, F. "Fast discriminative
visual codebooks using randomized clustering forests"
NIPS 2007
2012-10-28 21:18:09 +08:00
"""
2012-11-26 21:57:51 +08:00
def __init__(self,
n_estimators=10,
max_depth=5,
min_samples_split=2,
2012-11-26 21:57:51 +08:00
min_samples_leaf=1,
2014-06-03 05:24:30 +08:00
min_weight_fraction_leaf=0.,
2013-12-01 01:34:13 +08:00
max_leaf_nodes=None,
sparse_output=True,
2012-11-26 21:57:51 +08:00
n_jobs=1,
random_state=None,
2014-07-23 04:08:46 +08:00
verbose=0,
warm_start=False):
super(RandomTreesEmbedding, self).__init__(
base_estimator=ExtraTreeRegressor(),
2012-10-30 18:25:21 +08:00
n_estimators=n_estimators,
estimator_params=("criterion", "max_depth", "min_samples_split",
2014-06-03 05:24:30 +08:00
"min_samples_leaf", "min_weight_fraction_leaf",
"max_features", "max_leaf_nodes",
"random_state"),
2012-10-30 18:25:21 +08:00
bootstrap=False,
oob_score=False,
n_jobs=n_jobs,
random_state=random_state,
2014-07-23 04:08:46 +08:00
verbose=verbose,
warm_start=warm_start)
2012-10-30 18:25:21 +08:00
self.criterion = 'mse'
2012-10-30 18:25:21 +08:00
self.max_depth = max_depth
self.min_samples_split = min_samples_split
self.min_samples_leaf = min_samples_leaf
2014-06-03 05:24:30 +08:00
self.min_weight_fraction_leaf = min_weight_fraction_leaf
2012-10-30 18:25:21 +08:00
self.max_features = 1
2013-12-01 01:34:13 +08:00
self.max_leaf_nodes = max_leaf_nodes
self.sparse_output = sparse_output
2012-10-28 17:00:39 +08:00
def _set_oob_score(self, X, y):
raise NotImplementedError("OOB score not supported by tree embedding")
def fit(self, X, y=None, sample_weight=None):
2012-10-28 21:18:09 +08:00
"""Fit estimator.
Parameters
----------
X : array-like or sparse matrix, shape=(n_samples, n_features)
The input samples. Use ``dtype=np.float32`` for maximum
efficiency. Sparse matrices are also supported, use sparse
2015-01-16 04:09:35 +08:00
``csc_matrix`` for maximum efficiency.
Returns
-------
self : object
Returns self.
2012-10-28 21:18:09 +08:00
"""
self.fit_transform(X, y, sample_weight=sample_weight)
2012-10-28 17:00:39 +08:00
return self
def fit_transform(self, X, y=None, sample_weight=None):
2012-10-28 21:18:09 +08:00
"""Fit estimator and transform dataset.
Parameters
----------
X : array-like or sparse matrix, shape=(n_samples, n_features)
Input data used to build forests. Use ``dtype=np.float32`` for
maximum efficiency.
2012-10-28 21:18:09 +08:00
Returns
-------
2014-12-01 09:59:42 +08:00
X_transformed : sparse matrix, shape=(n_samples, n_out)
2012-10-28 21:18:09 +08:00
Transformed dataset.
"""
# ensure_2d=False because there are actually unit test checking we fail
# for 1d.
X = check_array(X, accept_sparse=['csc'], ensure_2d=False)
if issparse(X):
# Pre-sort indices to avoid that each individual tree of the
# ensemble sorts the indices.
X.sort_indices()
rnd = check_random_state(self.random_state)
y = rnd.uniform(size=X.shape[0])
super(RandomTreesEmbedding, self).fit(X, y,
sample_weight=sample_weight)
self.one_hot_encoder_ = OneHotEncoder(sparse=self.sparse_output)
2012-10-28 17:00:39 +08:00
return self.one_hot_encoder_.fit_transform(self.apply(X))
def transform(self, X):
2012-10-28 21:18:09 +08:00
"""Transform dataset.
Parameters
----------
X : array-like or sparse matrix, shape=(n_samples, n_features)
Input data to be transformed. Use ``dtype=np.float32`` for maximum
efficiency. Sparse matrices are also supported, use sparse
2015-01-16 04:09:35 +08:00
``csr_matrix`` for maximum efficiency.
2012-10-28 21:18:09 +08:00
Returns
-------
2014-12-01 09:59:42 +08:00
X_transformed : sparse matrix, shape=(n_samples, n_out)
2012-10-28 21:18:09 +08:00
Transformed dataset.
"""
2012-10-28 17:00:39 +08:00
return self.one_hot_encoder_.transform(self.apply(X))