2012-03-12 17:19:01 +08:00
|
|
|
.. _supervised_learning_tut:
|
|
|
|
|
|
2011-12-18 19:39:53 +08:00
|
|
|
=======================================================================================
|
|
|
|
|
Supervised learning: predicting an output variable from high-dimensional observations
|
|
|
|
|
=======================================================================================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.. topic:: The problem solved in supervised learning
|
|
|
|
|
|
2013-01-22 21:02:56 +08:00
|
|
|
:ref:`Supervised learning <supervised-learning>`
|
2012-02-17 00:39:45 +08:00
|
|
|
consists in learning the link between two
|
2014-07-06 19:33:20 +08:00
|
|
|
datasets: the observed data ``X`` and an external variable ``y`` that we
|
|
|
|
|
are trying to predict, usually called "target" or "labels". Most often,
|
|
|
|
|
``y`` is a 1D array of length ``n_samples``.
|
2013-01-22 21:02:56 +08:00
|
|
|
|
2015-12-03 07:16:40 +08:00
|
|
|
All supervised `estimators <https://en.wikipedia.org/wiki/Estimator>`_
|
2014-07-06 19:33:20 +08:00
|
|
|
in scikit-learn implement a ``fit(X, y)`` method to fit the model
|
|
|
|
|
and a ``predict(X)`` method that, given unlabeled observations ``X``,
|
|
|
|
|
returns the predicted labels ``y``.
|
2011-12-18 19:39:53 +08:00
|
|
|
|
|
|
|
|
.. topic:: Vocabulary: classification and regression
|
|
|
|
|
|
|
|
|
|
If the prediction task is to classify the observations in a set of
|
|
|
|
|
finite labels, in other words to "name" the objects observed, the task
|
2012-12-06 09:20:28 +08:00
|
|
|
is said to be a **classification** task. On the other hand, if the goal
|
|
|
|
|
is to predict a continuous target variable, it is said to be a
|
2011-12-18 19:39:53 +08:00
|
|
|
**regression** task.
|
|
|
|
|
|
2014-07-06 19:33:20 +08:00
|
|
|
When doing classification in scikit-learn, ``y`` is a vector of integers
|
|
|
|
|
or strings.
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2014-07-06 19:33:20 +08:00
|
|
|
Note: See the :ref:`Introduction to machine learning with scikit-learn
|
2012-02-17 00:39:45 +08:00
|
|
|
Tutorial <introduction>` for a quick run-through on the basic machine
|
2014-07-06 19:33:20 +08:00
|
|
|
learning vocabulary used within scikit-learn.
|
2012-02-17 00:39:45 +08:00
|
|
|
|
2011-12-18 19:39:53 +08:00
|
|
|
Nearest neighbor and the curse of dimensionality
|
|
|
|
|
=================================================
|
|
|
|
|
|
|
|
|
|
.. topic:: Classifying irises:
|
2013-01-22 21:02:56 +08:00
|
|
|
|
2011-12-18 19:39:53 +08:00
|
|
|
The iris dataset is a classification task consisting in identifying 3
|
|
|
|
|
different types of irises (Setosa, Versicolour, and Virginica) from
|
|
|
|
|
their petal and sepal length and width::
|
|
|
|
|
|
|
|
|
|
>>> import numpy as np
|
2012-02-17 00:39:45 +08:00
|
|
|
>>> from sklearn import datasets
|
2019-08-25 05:54:16 +08:00
|
|
|
>>> iris_X, iris_y = datasets.load_iris(return_X_y=True)
|
2011-12-18 19:39:53 +08:00
|
|
|
>>> np.unique(iris_y)
|
|
|
|
|
array([0, 1, 2])
|
|
|
|
|
|
2020-08-29 22:32:33 +08:00
|
|
|
.. image:: /auto_examples/datasets/images/sphx_glr_plot_iris_dataset_001.png
|
|
|
|
|
:target: ../../auto_examples/datasets/plot_iris_dataset.html
|
|
|
|
|
:align: center
|
|
|
|
|
:scale: 50
|
|
|
|
|
|
2012-02-17 00:39:45 +08:00
|
|
|
k-Nearest neighbors classifier
|
2011-12-18 19:39:53 +08:00
|
|
|
-------------------------------
|
|
|
|
|
|
2013-01-22 21:02:56 +08:00
|
|
|
The simplest possible classifier is the
|
2015-12-03 07:16:40 +08:00
|
|
|
`nearest neighbor <https://en.wikipedia.org/wiki/K-nearest_neighbor_algorithm>`_:
|
2013-01-22 21:02:56 +08:00
|
|
|
given a new observation ``X_test``, find in the training set (i.e. the data
|
2012-02-17 00:39:45 +08:00
|
|
|
used to train the estimator) the observation with the closest feature vector.
|
2012-02-17 21:32:32 +08:00
|
|
|
(Please see the :ref:`Nearest Neighbors section<neighbors>` of the online
|
|
|
|
|
Scikit-learn documentation for more information about this type of classifier.)
|
2011-12-18 19:39:53 +08:00
|
|
|
|
|
|
|
|
.. topic:: Training set and testing set
|
|
|
|
|
|
2012-12-06 09:20:28 +08:00
|
|
|
While experimenting with any learning algorithm, it is important not to
|
2011-12-18 19:39:53 +08:00
|
|
|
test the prediction of an estimator on the data used to fit the
|
2012-12-06 09:20:28 +08:00
|
|
|
estimator as this would not be evaluating the performance of the
|
2011-12-18 19:39:53 +08:00
|
|
|
estimator on **new data**. This is why datasets are often split into
|
|
|
|
|
*train* and *test* data.
|
|
|
|
|
|
|
|
|
|
**KNN (k nearest neighbors) classification example**:
|
|
|
|
|
|
2016-07-28 05:27:50 +08:00
|
|
|
.. image:: /auto_examples/neighbors/images/sphx_glr_plot_classification_001.png
|
2012-03-07 07:52:17 +08:00
|
|
|
:target: ../../auto_examples/neighbors/plot_classification.html
|
2012-02-20 21:47:32 +08:00
|
|
|
:align: center
|
2012-03-07 07:52:17 +08:00
|
|
|
:scale: 70
|
2011-12-18 19:39:53 +08:00
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
|
|
>>> # Split iris data in train and test data
|
|
|
|
|
>>> # A random permutation, to split the data randomly
|
|
|
|
|
>>> np.random.seed(0)
|
|
|
|
|
>>> indices = np.random.permutation(len(iris_X))
|
|
|
|
|
>>> iris_X_train = iris_X[indices[:-10]]
|
|
|
|
|
>>> iris_y_train = iris_y[indices[:-10]]
|
2018-10-05 22:51:42 +08:00
|
|
|
>>> iris_X_test = iris_X[indices[-10:]]
|
|
|
|
|
>>> iris_y_test = iris_y[indices[-10:]]
|
2011-12-18 19:39:53 +08:00
|
|
|
>>> # Create and fit a nearest-neighbor classifier
|
2012-02-17 21:32:32 +08:00
|
|
|
>>> from sklearn.neighbors import KNeighborsClassifier
|
|
|
|
|
>>> knn = KNeighborsClassifier()
|
2019-06-01 16:53:45 +08:00
|
|
|
>>> knn.fit(iris_X_train, iris_y_train)
|
|
|
|
|
KNeighborsClassifier()
|
2011-12-18 19:39:53 +08:00
|
|
|
>>> knn.predict(iris_X_test)
|
|
|
|
|
array([1, 2, 1, 0, 0, 0, 2, 1, 2, 0])
|
|
|
|
|
>>> iris_y_test
|
|
|
|
|
array([1, 1, 1, 0, 0, 0, 2, 1, 2, 0])
|
|
|
|
|
|
2012-02-24 23:51:49 +08:00
|
|
|
.. _curse_of_dimensionality:
|
|
|
|
|
|
2011-12-18 19:39:53 +08:00
|
|
|
The curse of dimensionality
|
|
|
|
|
-------------------------------
|
|
|
|
|
|
2013-01-22 21:02:56 +08:00
|
|
|
For an estimator to be effective, you need the distance between neighboring
|
2014-07-06 19:33:20 +08:00
|
|
|
points to be less than some value :math:`d`, which depends on the problem.
|
2017-04-19 20:28:49 +08:00
|
|
|
In one dimension, this requires on average :math:`n \sim 1/d` points.
|
2014-07-06 19:33:20 +08:00
|
|
|
In the context of the above :math:`k`-NN example, if the data is described by
|
|
|
|
|
just one feature with values ranging from 0 to 1 and with :math:`n` training
|
|
|
|
|
observations, then new data will be no further away than :math:`1/n`.
|
2012-03-21 17:08:15 +08:00
|
|
|
Therefore, the nearest neighbor decision rule will be efficient as soon as
|
2014-07-06 19:33:20 +08:00
|
|
|
:math:`1/n` is small compared to the scale of between-class feature variations.
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2017-04-19 20:28:49 +08:00
|
|
|
If the number of features is :math:`p`, you now require :math:`n \sim 1/d^p`
|
2014-07-06 19:33:20 +08:00
|
|
|
points. Let's say that we require 10 points in one dimension: now :math:`10^p`
|
|
|
|
|
points are required in :math:`p` dimensions to pave the :math:`[0, 1]` space.
|
|
|
|
|
As :math:`p` becomes large, the number of training points required for a good
|
2012-03-21 17:08:15 +08:00
|
|
|
estimator grows exponentially.
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2013-01-22 21:02:56 +08:00
|
|
|
For example, if each point is just a single number (8 bytes), then an
|
2017-04-19 20:28:49 +08:00
|
|
|
effective :math:`k`-NN estimator in a paltry :math:`p \sim 20` dimensions would
|
2014-07-06 19:33:20 +08:00
|
|
|
require more training data than the current estimated size of the entire
|
|
|
|
|
internet (±1000 Exabytes or so).
|
2012-03-21 17:08:15 +08:00
|
|
|
|
2013-01-22 21:02:56 +08:00
|
|
|
This is called the
|
2015-12-03 07:16:40 +08:00
|
|
|
`curse of dimensionality <https://en.wikipedia.org/wiki/Curse_of_dimensionality>`_
|
2012-03-20 15:49:35 +08:00
|
|
|
and is a core problem that machine learning addresses.
|
2011-12-18 19:39:53 +08:00
|
|
|
|
|
|
|
|
Linear model: from regression to sparsity
|
|
|
|
|
==========================================
|
|
|
|
|
|
|
|
|
|
.. topic:: Diabetes dataset
|
|
|
|
|
|
|
|
|
|
The diabetes dataset consists of 10 physiological variables (age,
|
|
|
|
|
sex, weight, blood pressure) measure on 442 patients, and an
|
|
|
|
|
indication of disease progression after one year::
|
|
|
|
|
|
2019-08-25 11:17:01 +08:00
|
|
|
>>> diabetes_X, diabetes_y = datasets.load_diabetes(return_X_y=True)
|
|
|
|
|
>>> diabetes_X_train = diabetes_X[:-20]
|
|
|
|
|
>>> diabetes_X_test = diabetes_X[-20:]
|
|
|
|
|
>>> diabetes_y_train = diabetes_y[:-20]
|
|
|
|
|
>>> diabetes_y_test = diabetes_y[-20:]
|
2013-01-22 21:02:56 +08:00
|
|
|
|
2012-05-03 00:37:58 +08:00
|
|
|
The task at hand is to predict disease progression from physiological
|
2013-01-22 21:02:56 +08:00
|
|
|
variables.
|
2011-12-18 19:39:53 +08:00
|
|
|
|
|
|
|
|
Linear regression
|
|
|
|
|
------------------
|
|
|
|
|
|
2012-03-08 22:21:53 +08:00
|
|
|
.. currentmodule:: sklearn.linear_model
|
|
|
|
|
|
|
|
|
|
:class:`LinearRegression`,
|
2016-02-26 10:16:28 +08:00
|
|
|
in its simplest form, fits a linear model to the data set by adjusting
|
2013-01-22 21:02:56 +08:00
|
|
|
a set of parameters in order to make the sum of the squared residuals
|
2012-12-06 09:20:28 +08:00
|
|
|
of the model as small as possible.
|
2012-02-21 18:45:35 +08:00
|
|
|
|
2011-12-18 19:39:53 +08:00
|
|
|
Linear models: :math:`y = X\beta + \epsilon`
|
|
|
|
|
|
|
|
|
|
* :math:`X`: data
|
|
|
|
|
* :math:`y`: target variable
|
|
|
|
|
* :math:`\beta`: Coefficients
|
|
|
|
|
* :math:`\epsilon`: Observation noise
|
|
|
|
|
|
2020-08-29 22:32:33 +08:00
|
|
|
.. image:: /auto_examples/linear_model/images/sphx_glr_plot_ols_001.png
|
|
|
|
|
:target: ../../auto_examples/linear_model/plot_ols.html
|
|
|
|
|
:scale: 50
|
|
|
|
|
:align: center
|
|
|
|
|
|
2013-01-22 21:02:56 +08:00
|
|
|
::
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2012-02-21 18:45:35 +08:00
|
|
|
>>> from sklearn import linear_model
|
2011-12-18 19:39:53 +08:00
|
|
|
>>> regr = linear_model.LinearRegression()
|
|
|
|
|
>>> regr.fit(diabetes_X_train, diabetes_y_train)
|
2019-06-01 16:53:45 +08:00
|
|
|
LinearRegression()
|
2021-05-18 22:09:36 +08:00
|
|
|
>>> print(regr.coef_) # doctest: +SKIP
|
2012-03-02 18:53:07 +08:00
|
|
|
[ 0.30349955 -237.63931533 510.53060544 327.73698041 -814.13170937
|
|
|
|
|
492.81458798 102.84845219 184.60648906 743.51961675 76.09517222]
|
2013-01-22 21:02:56 +08:00
|
|
|
|
2018-11-22 09:23:57 +08:00
|
|
|
|
2011-12-18 19:39:53 +08:00
|
|
|
>>> # The mean square error
|
2018-10-05 22:51:42 +08:00
|
|
|
>>> np.mean((regr.predict(diabetes_X_test) - diabetes_y_test)**2)
|
2021-12-17 18:33:18 +08:00
|
|
|
2004.5...
|
2011-12-18 19:39:53 +08:00
|
|
|
|
|
|
|
|
>>> # Explained variance score: 1 is perfect prediction
|
2012-02-23 03:38:28 +08:00
|
|
|
>>> # and 0 means that there is no linear relationship
|
2016-07-16 14:39:10 +08:00
|
|
|
>>> # between X and y.
|
2019-06-01 16:53:45 +08:00
|
|
|
>>> regr.score(diabetes_X_test, diabetes_y_test)
|
2021-12-17 18:33:18 +08:00
|
|
|
0.585...
|
2011-12-18 19:39:53 +08:00
|
|
|
|
|
|
|
|
|
2012-02-28 08:05:16 +08:00
|
|
|
.. _shrinkage:
|
|
|
|
|
|
2013-01-22 21:02:56 +08:00
|
|
|
Shrinkage
|
2011-12-18 19:39:53 +08:00
|
|
|
----------
|
|
|
|
|
|
|
|
|
|
If there are few data points per dimension, noise in the observations
|
|
|
|
|
induces high variance:
|
|
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
|
|
>>> X = np.c_[ .5, 1].T
|
|
|
|
|
>>> y = [.5, 1]
|
|
|
|
|
>>> test = np.c_[ 0, 2].T
|
|
|
|
|
>>> regr = linear_model.LinearRegression()
|
2013-01-22 21:02:56 +08:00
|
|
|
|
2021-06-17 23:45:53 +08:00
|
|
|
>>> import matplotlib.pyplot as plt
|
|
|
|
|
>>> plt.figure()
|
|
|
|
|
<...>
|
2011-12-18 19:39:53 +08:00
|
|
|
>>> np.random.seed(0)
|
2021-06-17 23:45:53 +08:00
|
|
|
>>> for _ in range(6):
|
2018-10-05 22:51:42 +08:00
|
|
|
... this_X = .1 * np.random.normal(size=(2, 1)) + X
|
|
|
|
|
... regr.fit(this_X, y)
|
2021-06-17 23:45:53 +08:00
|
|
|
... plt.plot(test, regr.predict(test))
|
|
|
|
|
... plt.scatter(this_X, y, s=3)
|
|
|
|
|
LinearRegression...
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2020-08-29 22:32:33 +08:00
|
|
|
.. image:: /auto_examples/linear_model/images/sphx_glr_plot_ols_ridge_variance_001.png
|
|
|
|
|
:target: ../../auto_examples/linear_model/plot_ols_ridge_variance.html
|
|
|
|
|
:align: center
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2012-12-06 09:20:28 +08:00
|
|
|
A solution in high-dimensional statistical learning is to *shrink* the
|
2011-12-18 19:39:53 +08:00
|
|
|
regression coefficients to zero: any two randomly chosen set of
|
2012-03-08 22:21:53 +08:00
|
|
|
observations are likely to be uncorrelated. This is called :class:`Ridge`
|
2011-12-18 19:39:53 +08:00
|
|
|
regression:
|
|
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
|
|
>>> regr = linear_model.Ridge(alpha=.1)
|
|
|
|
|
|
2021-06-17 23:45:53 +08:00
|
|
|
>>> plt.figure()
|
|
|
|
|
<...>
|
2011-12-18 19:39:53 +08:00
|
|
|
>>> np.random.seed(0)
|
2021-06-17 23:45:53 +08:00
|
|
|
>>> for _ in range(6):
|
2018-10-05 22:51:42 +08:00
|
|
|
... this_X = .1 * np.random.normal(size=(2, 1)) + X
|
|
|
|
|
... regr.fit(this_X, y)
|
2021-06-17 23:45:53 +08:00
|
|
|
... plt.plot(test, regr.predict(test))
|
|
|
|
|
... plt.scatter(this_X, y, s=3)
|
|
|
|
|
Ridge...
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2020-08-29 22:32:33 +08:00
|
|
|
.. image:: /auto_examples/linear_model/images/sphx_glr_plot_ols_ridge_variance_002.png
|
|
|
|
|
:target: ../../auto_examples/linear_model/plot_ols_ridge_variance.html
|
|
|
|
|
:align: center
|
|
|
|
|
|
2011-12-18 19:39:53 +08:00
|
|
|
This is an example of **bias/variance tradeoff**: the larger the ridge
|
2014-07-06 19:33:20 +08:00
|
|
|
``alpha`` parameter, the higher the bias and the lower the variance.
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2014-07-06 19:33:20 +08:00
|
|
|
We can choose ``alpha`` to minimize left out error, this time using the
|
2013-01-22 21:02:56 +08:00
|
|
|
diabetes dataset rather than our synthetic data::
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2018-10-05 22:51:42 +08:00
|
|
|
>>> alphas = np.logspace(-4, -1, 6)
|
|
|
|
|
>>> print([regr.set_params(alpha=alpha)
|
|
|
|
|
... .fit(diabetes_X_train, diabetes_y_train)
|
|
|
|
|
... .score(diabetes_X_test, diabetes_y_test)
|
2018-08-03 18:34:25 +08:00
|
|
|
... for alpha in alphas])
|
2021-12-17 18:33:18 +08:00
|
|
|
[0.585..., 0.585..., 0.5854..., 0.5855..., 0.583..., 0.570...]
|
2011-12-18 19:39:53 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
|
|
|
|
Capturing in the fitted parameters noise that prevents the model to
|
2013-01-22 21:02:56 +08:00
|
|
|
generalize to new data is called
|
2015-12-03 07:16:40 +08:00
|
|
|
`overfitting <https://en.wikipedia.org/wiki/Overfitting>`_. The bias introduced
|
2013-01-22 21:02:56 +08:00
|
|
|
by the ridge regression is called a
|
2015-12-03 07:16:40 +08:00
|
|
|
`regularization <https://en.wikipedia.org/wiki/Regularization_%28machine_learning%29>`_.
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2012-02-28 08:05:16 +08:00
|
|
|
.. _sparsity:
|
|
|
|
|
|
2011-12-18 19:39:53 +08:00
|
|
|
Sparsity
|
|
|
|
|
----------
|
|
|
|
|
|
|
|
|
|
|
2016-07-28 05:27:50 +08:00
|
|
|
.. |diabetes_ols_1| image:: /auto_examples/linear_model/images/sphx_glr_plot_ols_3d_001.png
|
2012-03-06 20:23:48 +08:00
|
|
|
:target: ../../auto_examples/linear_model/plot_ols_3d.html
|
2011-12-18 19:39:53 +08:00
|
|
|
:scale: 65
|
|
|
|
|
|
2016-07-28 05:27:50 +08:00
|
|
|
.. |diabetes_ols_3| image:: /auto_examples/linear_model/images/sphx_glr_plot_ols_3d_003.png
|
2012-03-06 20:23:48 +08:00
|
|
|
:target: ../../auto_examples/linear_model/plot_ols_3d.html
|
2011-12-18 19:39:53 +08:00
|
|
|
:scale: 65
|
|
|
|
|
|
2016-07-28 05:27:50 +08:00
|
|
|
.. |diabetes_ols_2| image:: /auto_examples/linear_model/images/sphx_glr_plot_ols_3d_002.png
|
2012-03-06 20:23:48 +08:00
|
|
|
:target: ../../auto_examples/linear_model/plot_ols_3d.html
|
2011-12-18 19:39:53 +08:00
|
|
|
:scale: 65
|
|
|
|
|
|
|
|
|
|
|
2012-02-24 23:51:49 +08:00
|
|
|
|
|
|
|
|
|
2011-12-18 19:39:53 +08:00
|
|
|
.. rst-class:: centered
|
|
|
|
|
|
2012-02-24 23:51:49 +08:00
|
|
|
**Fitting only features 1 and 2**
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2013-01-22 21:02:56 +08:00
|
|
|
.. centered:: |diabetes_ols_1| |diabetes_ols_3| |diabetes_ols_2|
|
2011-12-18 19:39:53 +08:00
|
|
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
|
|
|
|
A representation of the full diabetes dataset would involve 11
|
2012-12-06 09:20:28 +08:00
|
|
|
dimensions (10 feature dimensions and one of the target variable). It
|
2011-12-18 19:39:53 +08:00
|
|
|
is hard to develop an intuition on such representation, but it may be
|
|
|
|
|
useful to keep in mind that it would be a fairly *empty* space.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-12-06 09:20:28 +08:00
|
|
|
We can see that, although feature 2 has a strong coefficient on the full
|
2014-07-06 19:33:20 +08:00
|
|
|
model, it conveys little information on ``y`` when considered with feature 1.
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2013-01-22 21:02:56 +08:00
|
|
|
To improve the conditioning of the problem (i.e. mitigating the
|
|
|
|
|
:ref:`curse_of_dimensionality`), it would be interesting to select only the
|
|
|
|
|
informative features and set non-informative ones, like feature 2 to 0. Ridge
|
2012-02-24 23:51:49 +08:00
|
|
|
regression will decrease their contribution, but not set them to zero. Another
|
2013-01-22 21:02:56 +08:00
|
|
|
penalization approach, called :ref:`lasso` (least absolute shrinkage and
|
|
|
|
|
selection operator), can set some coefficients to zero. Such methods are
|
2012-12-06 09:20:28 +08:00
|
|
|
called **sparse method** and sparsity can be seen as an
|
2014-07-06 19:33:20 +08:00
|
|
|
application of Occam's razor: *prefer simpler models*.
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2013-01-22 21:02:56 +08:00
|
|
|
::
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2012-05-03 00:37:58 +08:00
|
|
|
>>> regr = linear_model.Lasso()
|
2018-10-05 22:51:42 +08:00
|
|
|
>>> scores = [regr.set_params(alpha=alpha)
|
|
|
|
|
... .fit(diabetes_X_train, diabetes_y_train)
|
|
|
|
|
... .score(diabetes_X_test, diabetes_y_test)
|
|
|
|
|
... for alpha in alphas]
|
2012-05-03 00:37:58 +08:00
|
|
|
>>> best_alpha = alphas[scores.index(max(scores))]
|
2011-12-18 19:39:53 +08:00
|
|
|
>>> regr.alpha = best_alpha
|
|
|
|
|
>>> regr.fit(diabetes_X_train, diabetes_y_train)
|
2019-06-01 16:53:45 +08:00
|
|
|
Lasso(alpha=0.025118864315095794)
|
|
|
|
|
>>> print(regr.coef_)
|
2021-12-17 18:33:18 +08:00
|
|
|
[ 0. -212.4... 517.2... 313.7... -160.8...
|
|
|
|
|
-0. -187.1... 69.3... 508.6... 71.8... ]
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2012-12-06 09:20:28 +08:00
|
|
|
.. topic:: **Different algorithms for the same problem**
|
2012-05-07 05:33:55 +08:00
|
|
|
|
2011-12-18 19:39:53 +08:00
|
|
|
Different algorithms can be used to solve the same mathematical
|
2014-07-06 19:33:20 +08:00
|
|
|
problem. For instance the ``Lasso`` object in scikit-learn
|
2013-01-22 21:02:56 +08:00
|
|
|
solves the lasso regression problem using a
|
2017-02-12 23:53:58 +08:00
|
|
|
`coordinate descent <https://en.wikipedia.org/wiki/Coordinate_descent>`_ method,
|
2014-07-06 19:33:20 +08:00
|
|
|
that is efficient on large datasets. However, scikit-learn also
|
2017-02-18 18:29:07 +08:00
|
|
|
provides the :class:`LassoLars` object using the *LARS* algorithm,
|
2014-07-06 19:33:20 +08:00
|
|
|
which is very efficient for problems in which the weight vector estimated
|
|
|
|
|
is very sparse (i.e. problems with very few observations).
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2012-03-12 17:19:01 +08:00
|
|
|
.. _clf_tut:
|
|
|
|
|
|
2011-12-18 19:39:53 +08:00
|
|
|
Classification
|
|
|
|
|
---------------
|
|
|
|
|
|
2013-01-22 21:02:56 +08:00
|
|
|
For classification, as in the labeling
|
2015-12-03 07:16:40 +08:00
|
|
|
`iris <https://en.wikipedia.org/wiki/Iris_flower_data_set>`_ task, linear
|
2013-01-22 21:02:56 +08:00
|
|
|
regression is not the right approach as it will give too much weight to
|
|
|
|
|
data far from the decision frontier. A linear approach is to fit a sigmoid
|
2012-12-06 09:20:28 +08:00
|
|
|
function or **logistic** function:
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2020-08-29 22:32:33 +08:00
|
|
|
.. image:: /auto_examples/linear_model/images/sphx_glr_plot_logistic_001.png
|
|
|
|
|
:target: ../../auto_examples/linear_model/plot_logistic.html
|
|
|
|
|
:scale: 70
|
|
|
|
|
:align: center
|
|
|
|
|
|
2011-12-18 19:39:53 +08:00
|
|
|
.. math::
|
|
|
|
|
|
|
|
|
|
y = \textrm{sigmoid}(X\beta - \textrm{offset}) + \epsilon =
|
|
|
|
|
\frac{1}{1 + \textrm{exp}(- X\beta + \textrm{offset})} + \epsilon
|
|
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
2019-05-22 21:57:15 +08:00
|
|
|
>>> log = linear_model.LogisticRegression(C=1e5)
|
2019-06-01 16:53:45 +08:00
|
|
|
>>> log.fit(iris_X_train, iris_y_train)
|
|
|
|
|
LogisticRegression(C=100000.0)
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2012-03-08 22:21:53 +08:00
|
|
|
This is known as :class:`LogisticRegression`.
|
|
|
|
|
|
2016-07-28 05:27:50 +08:00
|
|
|
.. image:: /auto_examples/linear_model/images/sphx_glr_plot_iris_logistic_001.png
|
2012-03-07 10:55:18 +08:00
|
|
|
:target: ../../auto_examples/linear_model/plot_iris_logistic.html
|
2011-12-18 19:39:53 +08:00
|
|
|
:scale: 83
|
2020-08-29 22:32:33 +08:00
|
|
|
:align: center
|
2011-12-18 19:39:53 +08:00
|
|
|
|
|
|
|
|
.. topic:: Multiclass classification
|
|
|
|
|
|
|
|
|
|
If you have several classes to predict, an option often used is to fit
|
2012-12-06 09:20:28 +08:00
|
|
|
one-versus-all classifiers and then use a voting heuristic for the final
|
2011-12-18 19:39:53 +08:00
|
|
|
decision.
|
|
|
|
|
|
|
|
|
|
.. topic:: Shrinkage and sparsity with logistic regression
|
|
|
|
|
|
2014-07-06 19:33:20 +08:00
|
|
|
The ``C`` parameter controls the amount of regularization in the
|
|
|
|
|
:class:`LogisticRegression` object: a large value for ``C`` results in
|
2012-05-03 00:37:58 +08:00
|
|
|
less regularization.
|
2014-07-06 19:33:20 +08:00
|
|
|
``penalty="l2"`` gives :ref:`shrinkage` (i.e. non-sparse coefficients), while
|
|
|
|
|
``penalty="l1"`` gives :ref:`sparsity`.
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2012-03-08 22:21:53 +08:00
|
|
|
.. topic:: **Exercise**
|
2011-12-18 19:39:53 +08:00
|
|
|
:class: green
|
|
|
|
|
|
2012-03-26 15:55:57 +08:00
|
|
|
Try classifying the digits dataset with nearest neighbors and a linear
|
2011-12-18 19:39:53 +08:00
|
|
|
model. Leave out the last 10% and test prediction performance on these
|
|
|
|
|
observations.
|
|
|
|
|
|
2017-06-28 23:00:13 +08:00
|
|
|
.. literalinclude:: ../../auto_examples/exercises/plot_digits_classification_exercise.py
|
2014-08-20 15:30:31 +08:00
|
|
|
:lines: 15-19
|
2012-03-26 07:20:53 +08:00
|
|
|
|
2020-08-29 22:32:33 +08:00
|
|
|
A solution can be downloaded :download:`here <../../auto_examples/exercises/plot_digits_classification_exercise.py>`.
|
2011-12-18 19:39:53 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
Support vector machines (SVMs)
|
|
|
|
|
================================
|
|
|
|
|
|
|
|
|
|
Linear SVMs
|
|
|
|
|
-------------
|
|
|
|
|
|
2012-03-08 22:21:53 +08:00
|
|
|
|
2013-01-22 21:02:56 +08:00
|
|
|
:ref:`svm` belong to the discriminant model family: they try to find a combination of
|
2012-03-08 22:21:53 +08:00
|
|
|
samples to build a plane maximizing the margin between the two classes.
|
2014-07-06 19:33:20 +08:00
|
|
|
Regularization is set by the ``C`` parameter: a small value for ``C`` means the margin
|
2012-05-03 00:37:58 +08:00
|
|
|
is calculated using many or all of the observations around the separating line
|
|
|
|
|
(more regularization);
|
2014-07-06 19:33:20 +08:00
|
|
|
a large value for ``C`` means the margin is calculated on observations close to
|
2012-05-03 00:37:58 +08:00
|
|
|
the separating line (less regularization).
|
2012-02-28 08:05:16 +08:00
|
|
|
|
2012-03-08 22:21:53 +08:00
|
|
|
.. currentmodule :: sklearn.svm
|
|
|
|
|
|
2020-08-29 22:32:33 +08:00
|
|
|
.. figure:: /auto_examples/svm/images/sphx_glr_plot_svm_margin_001.png
|
2012-03-07 10:55:18 +08:00
|
|
|
:target: ../../auto_examples/svm/plot_svm_margin.html
|
2020-11-02 22:39:58 +08:00
|
|
|
|
2020-08-29 22:32:33 +08:00
|
|
|
**Unregularized SVM**
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2020-08-29 22:32:33 +08:00
|
|
|
.. figure:: /auto_examples/svm/images/sphx_glr_plot_svm_margin_002.png
|
2012-03-07 10:55:18 +08:00
|
|
|
:target: ../../auto_examples/svm/plot_svm_margin.html
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2020-08-29 22:32:33 +08:00
|
|
|
**Regularized SVM (default)**
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2013-10-15 00:28:07 +08:00
|
|
|
.. topic:: Example:
|
|
|
|
|
|
2019-01-17 20:31:48 +08:00
|
|
|
- :ref:`sphx_glr_auto_examples_svm_plot_iris_svc.py`
|
2013-10-15 00:28:07 +08:00
|
|
|
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2012-03-08 22:21:53 +08:00
|
|
|
SVMs can be used in regression --:class:`SVR` (Support Vector Regression)--, or in
|
2013-01-22 21:02:56 +08:00
|
|
|
classification --:class:`SVC` (Support Vector Classification).
|
2011-12-18 19:39:53 +08:00
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
2012-03-02 18:53:07 +08:00
|
|
|
>>> from sklearn import svm
|
2011-12-18 19:39:53 +08:00
|
|
|
>>> svc = svm.SVC(kernel='linear')
|
2019-06-01 16:53:45 +08:00
|
|
|
>>> svc.fit(iris_X_train, iris_y_train)
|
|
|
|
|
SVC(kernel='linear')
|
2011-12-18 19:39:53 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
.. warning:: **Normalizing data**
|
|
|
|
|
|
|
|
|
|
For many estimators, including the SVMs, having datasets with unit
|
|
|
|
|
standard deviation for each feature is important to get good
|
|
|
|
|
prediction.
|
|
|
|
|
|
2012-03-12 17:19:01 +08:00
|
|
|
.. _using_kernels_tut:
|
|
|
|
|
|
2011-12-18 19:39:53 +08:00
|
|
|
Using kernels
|
2020-08-29 22:32:33 +08:00
|
|
|
-------------
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2012-03-20 15:49:35 +08:00
|
|
|
Classes are not always linearly separable in feature space. The solution is to
|
2013-01-22 21:02:56 +08:00
|
|
|
build a decision function that is not linear but may be polynomial instead.
|
2012-12-06 09:20:28 +08:00
|
|
|
This is done using the *kernel trick* that can be seen as
|
|
|
|
|
creating a decision energy by positioning *kernels* on observations:
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2020-08-29 22:32:33 +08:00
|
|
|
Linear kernel
|
|
|
|
|
^^^^^^^^^^^^^
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2020-08-29 22:32:33 +08:00
|
|
|
::
|
2012-02-28 08:05:16 +08:00
|
|
|
|
2020-08-29 22:32:33 +08:00
|
|
|
>>> svc = svm.SVC(kernel='linear')
|
2012-02-28 08:05:16 +08:00
|
|
|
|
2020-08-29 22:32:33 +08:00
|
|
|
.. image:: /auto_examples/svm/images/sphx_glr_plot_svm_kernels_001.png
|
2012-03-07 10:55:18 +08:00
|
|
|
:target: ../../auto_examples/svm/plot_svm_kernels.html
|
2012-02-28 08:05:16 +08:00
|
|
|
|
2020-08-29 22:32:33 +08:00
|
|
|
Polynomial kernel
|
|
|
|
|
^^^^^^^^^^^^^^^^^
|
2013-01-22 21:02:56 +08:00
|
|
|
|
2020-08-29 22:32:33 +08:00
|
|
|
::
|
2013-01-22 21:02:56 +08:00
|
|
|
|
2020-08-29 22:32:33 +08:00
|
|
|
>>> svc = svm.SVC(kernel='poly',
|
|
|
|
|
... degree=3)
|
|
|
|
|
>>> # degree: polynomial degree
|
2013-01-22 21:02:56 +08:00
|
|
|
|
2020-08-29 22:32:33 +08:00
|
|
|
.. image:: /auto_examples/svm/images/sphx_glr_plot_svm_kernels_002.png
|
|
|
|
|
:target: ../../auto_examples/svm/plot_svm_kernels.html
|
2013-01-22 21:02:56 +08:00
|
|
|
|
2020-08-29 22:32:33 +08:00
|
|
|
RBF kernel (Radial Basis Function)
|
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
2012-02-28 08:05:16 +08:00
|
|
|
|
2020-08-29 22:32:33 +08:00
|
|
|
::
|
2013-01-22 21:02:56 +08:00
|
|
|
|
2020-08-29 22:32:33 +08:00
|
|
|
>>> svc = svm.SVC(kernel='rbf')
|
|
|
|
|
>>> # gamma: inverse of size of
|
|
|
|
|
>>> # radial kernel
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2020-08-29 22:32:33 +08:00
|
|
|
.. image:: /auto_examples/svm/images/sphx_glr_plot_svm_kernels_003.png
|
|
|
|
|
:target: ../../auto_examples/svm/plot_svm_kernels.html
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2012-02-28 08:05:16 +08:00
|
|
|
|
|
|
|
|
|
2011-12-18 19:39:53 +08:00
|
|
|
.. topic:: **Interactive example**
|
|
|
|
|
|
2016-01-25 07:50:40 +08:00
|
|
|
See the :ref:`SVM GUI <sphx_glr_auto_examples_applications_svm_gui.py>` to download
|
2014-07-06 19:33:20 +08:00
|
|
|
``svm_gui.py``; add data points of both classes with right and left button,
|
2012-02-28 20:53:55 +08:00
|
|
|
fit the model and change parameters and data.
|
2011-12-18 19:39:53 +08:00
|
|
|
|
2012-03-26 07:20:53 +08:00
|
|
|
.. topic:: **Exercise**
|
2011-12-18 19:39:53 +08:00
|
|
|
:class: green
|
|
|
|
|
|
|
|
|
|
Try classifying classes 1 and 2 from the iris dataset with SVMs, with
|
|
|
|
|
the 2 first features. Leave out 10% of each class and test prediction
|
|
|
|
|
performance on these observations.
|
|
|
|
|
|
|
|
|
|
**Warning**: the classes are ordered, do not leave out the last 10%,
|
|
|
|
|
you would be testing on only one class.
|
|
|
|
|
|
2014-07-06 19:33:20 +08:00
|
|
|
**Hint**: You can use the ``decision_function`` method on a grid to get
|
2011-12-18 19:39:53 +08:00
|
|
|
intuitions.
|
|
|
|
|
|
2012-03-26 07:20:53 +08:00
|
|
|
.. literalinclude:: ../../auto_examples/exercises/plot_iris_exercise.py
|
2014-08-20 15:59:31 +08:00
|
|
|
:lines: 18-23
|
2012-03-26 07:20:53 +08:00
|
|
|
|
2020-08-29 22:32:33 +08:00
|
|
|
.. image:: /auto_examples/datasets/images/sphx_glr_plot_iris_dataset_001.png
|
|
|
|
|
:target: ../../auto_examples/datasets/plot_iris_dataset.html
|
|
|
|
|
:align: center
|
|
|
|
|
:scale: 70
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
A solution can be downloaded :download:`here <../../auto_examples/exercises/plot_iris_exercise.py>`
|