scikit-learn/examples/decomposition/plot_ica_vs_pca.py

106 lines
3.3 KiB
Python
Raw Normal View History

2010-09-08 22:58:08 +08:00
"""
==========================
FastICA on 2D point clouds
==========================
This example illustrates visually in the feature space a comparison by
results using two different component analysis techniques.
:ref:`ICA` vs :ref:`PCA`.
Representing ICA in the feature space gives the view of 'geometric ICA':
ICA is an algorithm that finds directions in the feature space
corresponding to projections with high non-Gaussianity. These directions
need not be orthogonal in the original feature space, but they are
orthogonal in the whitened feature space, in which all directions
correspond to the same variance.
PCA, on the other hand, finds orthogonal directions in the raw feature
2011-04-09 18:10:06 +08:00
space that correspond to directions accounting for maximum variance.
Here we simulate independent sources using a highly non-Gaussian
process, 2 student T with a low number of degrees of freedom (top left
figure). We mix them to create observations (top right figure).
In this raw observation space, directions identified by PCA are
2013-12-02 18:46:35 +08:00
represented by orange vectors. We represent the signal in the PCA space,
after whitening by the variance corresponding to the PCA vectors (lower
left). Running ICA corresponds to finding a rotation in this space to
identify the directions of largest non-Gaussianity (lower right).
2010-09-08 22:58:08 +08:00
"""
print(__doc__)
# Authors: Alexandre Gramfort, Gael Varoquaux
# License: BSD 3 clause
2010-09-08 22:58:08 +08:00
import numpy as np
import matplotlib.pyplot as plt
2010-09-08 22:58:08 +08:00
from sklearn.decomposition import PCA, FastICA
2010-09-08 22:58:08 +08:00
# #############################################################################
2010-09-08 22:58:08 +08:00
# Generate sample data
rng = np.random.RandomState(42)
S = rng.standard_t(1.5, size=(20000, 2))
S[:, 0] *= 2.
2010-09-08 22:58:08 +08:00
# Mix data
2011-06-04 22:07:48 +08:00
A = np.array([[1, 1], [0, 2]]) # Mixing matrix
2010-09-08 22:58:08 +08:00
2011-06-04 22:07:48 +08:00
X = np.dot(S, A.T) # Generate observations
2010-09-08 22:58:08 +08:00
pca = PCA()
2011-06-04 22:07:48 +08:00
S_pca_ = pca.fit(X).transform(X)
2010-09-08 22:58:08 +08:00
ica = FastICA(random_state=rng)
2011-04-04 21:42:16 +08:00
S_ica_ = ica.fit(X).transform(X) # Estimate the sources
2011-06-04 22:07:48 +08:00
S_ica_ /= S_ica_.std(axis=0)
2010-09-08 22:58:08 +08:00
# #############################################################################
2010-09-08 22:58:08 +08:00
# Plot results
2010-09-08 23:38:51 +08:00
def plot_samples(S, axis_list=None):
plt.scatter(S[:, 0], S[:, 1], s=2, marker='o', zorder=10,
color='steelblue', alpha=0.5)
2010-09-08 22:58:08 +08:00
if axis_list is not None:
2013-12-02 16:39:15 +08:00
colors = ['orange', 'red']
2010-09-08 22:58:08 +08:00
for color, axis in zip(colors, axis_list):
axis /= axis.std()
x_axis, y_axis = axis
# Trick to get legend to work
plt.plot(0.1 * x_axis, 0.1 * y_axis, linewidth=2, color=color)
plt.quiver((0, 0), (0, 0), x_axis, y_axis, zorder=11, width=0.01,
scale=6, color=color)
plt.hlines(0, -3, 3)
plt.vlines(0, -3, 3)
plt.xlim(-3, 3)
plt.ylim(-3, 3)
plt.xlabel('x')
plt.ylabel('y')
plt.figure()
plt.subplot(2, 2, 1)
2010-09-08 23:38:51 +08:00
plot_samples(S / S.std())
plt.title('True Independent Sources')
2010-09-08 22:58:08 +08:00
2013-07-23 21:48:52 +08:00
axis_list = [pca.components_.T, ica.mixing_]
plt.subplot(2, 2, 2)
2010-09-08 23:38:51 +08:00
plot_samples(X / np.std(X), axis_list=axis_list)
legend = plt.legend(['PCA', 'ICA'], loc='upper right')
2013-12-02 16:39:15 +08:00
legend.set_zorder(100)
plt.title('Observations')
2010-09-08 22:58:08 +08:00
plt.subplot(2, 2, 3)
2011-06-04 23:35:49 +08:00
plot_samples(S_pca_ / np.std(S_pca_, axis=0))
plt.title('PCA recovered signals')
2010-09-08 22:58:08 +08:00
plt.subplot(2, 2, 4)
2010-09-08 23:38:51 +08:00
plot_samples(S_ica_ / np.std(S_ica_))
plt.title('ICA recovered signals')
2010-09-08 22:58:08 +08:00
plt.subplots_adjust(0.09, 0.04, 0.94, 0.94, 0.26, 0.36)
plt.show()