scikit-learn/examples/decomposition/plot_ica_blind_source_separ...

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

75 lines
2.1 KiB
Python
Raw Normal View History

2010-09-08 20:31:40 +08:00
"""
=====================================
2010-09-08 22:58:08 +08:00
Blind source separation using FastICA
2010-09-08 20:31:40 +08:00
=====================================
2010-09-08 22:58:08 +08:00
An example of estimating sources from noisy data.
2010-11-01 22:11:56 +08:00
:ref:`ICA` is used to estimate sources given noisy measurements.
2013-12-02 16:05:03 +08:00
Imagine 3 instruments playing simultaneously and 3 microphones
2010-09-08 22:58:08 +08:00
recording the mixed signals. ICA is used to recover the sources
2013-12-02 08:02:11 +08:00
ie. what is played by each instrument. Importantly, PCA fails
2013-12-02 08:04:20 +08:00
at recovering our `instruments` since the related signals reflect
non-Gaussian processes.
2010-09-08 22:58:08 +08:00
2010-09-08 20:31:40 +08:00
"""
import numpy as np
import matplotlib.pyplot as plt
2013-12-02 08:02:11 +08:00
from scipy import signal
2013-12-02 16:05:03 +08:00
from sklearn.decomposition import FastICA, PCA
2010-09-08 20:31:40 +08:00
# #############################################################################
2010-09-08 20:31:40 +08:00
# Generate sample data
np.random.seed(0)
2010-09-08 22:58:08 +08:00
n_samples = 2000
2013-12-02 08:02:11 +08:00
time = np.linspace(0, 8, n_samples)
s1 = np.sin(2 * time) # Signal 1 : sinusoidal signal
s2 = np.sign(np.sin(3 * time)) # Signal 2 : square signal
2013-12-02 08:02:11 +08:00
s3 = signal.sawtooth(2 * np.pi * time) # Signal 3: saw tooth signal
S = np.c_[s1, s2, s3]
S += 0.2 * np.random.normal(size=S.shape) # Add noise
2010-09-08 20:31:40 +08:00
S /= S.std(axis=0) # Standardize data
2010-09-08 20:31:40 +08:00
# Mix data
2013-12-02 08:02:11 +08:00
A = np.array([[1, 1, 1], [0.5, 2, 1.0], [1.5, 1.0, 2.0]]) # Mixing matrix
X = np.dot(S, A.T) # Generate observations
2013-12-02 16:05:03 +08:00
2010-09-08 22:58:08 +08:00
# Compute ICA
2013-12-02 16:05:03 +08:00
ica = FastICA(n_components=3)
2013-12-02 18:44:53 +08:00
S_ = ica.fit_transform(X) # Reconstruct signals
2013-07-23 21:48:52 +08:00
A_ = ica.mixing_ # Get estimated mixing matrix
2013-12-02 18:44:53 +08:00
# We can `prove` that the ICA model applies by reverting the unmixing.
2013-07-23 21:48:52 +08:00
assert np.allclose(X, np.dot(S_, A_.T) + ica.mean_)
2010-09-08 20:31:40 +08:00
2013-12-02 18:44:53 +08:00
# For comparison, compute PCA
2013-12-02 16:05:03 +08:00
pca = PCA(n_components=3)
2013-12-02 18:44:53 +08:00
H = pca.fit_transform(X) # Reconstruct signals based on orthogonal components
2013-12-02 08:02:11 +08:00
# #############################################################################
2010-09-08 20:31:40 +08:00
# Plot results
2013-12-02 08:02:11 +08:00
plt.figure()
2013-12-02 08:02:11 +08:00
models = [X, S, S_, H]
names = [
"Observations (mixed signal)",
"True Sources",
"ICA recovered signals",
2013-12-02 18:44:53 +08:00
"PCA recovered signals",
]
2013-12-02 08:02:11 +08:00
colors = ["red", "steelblue", "orange"]
for ii, (model, name) in enumerate(zip(models, names), 1):
plt.subplot(4, 1, ii)
plt.title(name)
2013-12-02 08:02:11 +08:00
for sig, color in zip(model.T, colors):
plt.plot(sig, color=color)
2013-12-02 08:02:11 +08:00
plt.tight_layout()
plt.show()