Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d0750d0

Browse files
committed
Merge pull request scikit-learn#198 from amueller/fastICA_transposed
Merge amueller's branch on consistent shape handling for the ICA module.
2 parents dd00031 + cf8bf52 commit d0750d0

File tree

4 files changed

+41
-30
lines changed

4 files changed

+41
-30
lines changed

examples/decomposition/plot_ica_blind_source_separation.py

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,33 +20,32 @@
2020
np.random.seed(0)
2121
n_samples = 2000
2222
time = np.linspace(0, 10, n_samples)
23-
s1 = np.sin(2*time) # Signal 1 : sinusoidal signal
24-
s2 = np.sign(np.sin(3*time)) # Signal 2 : square signal
25-
S = np.c_[s1,s2].T
26-
S += 0.2*np.random.normal(size=S.shape) # Add noise
23+
s1 = np.sin(2 * time) # Signal 1 : sinusoidal signal
24+
s2 = np.sign(np.sin(3 * time)) # Signal 2 : square signal
25+
S = np.c_[s1, s2]
26+
S += 0.2 * np.random.normal(size=S.shape) # Add noise
2727

28-
S /= S.std(axis=1)[:,np.newaxis] # Standardize data
28+
S /= S.std(axis=0) # Standardize data
2929
# Mix data
30-
A = [[1, 1], [0.5, 2]] # Mixing matrix
31-
X = np.dot(A, S) # Generate observations
30+
A = np.array([[1, 1], [0.5, 2]]) # Mixing matrix
31+
X = np.dot(S, A.T) # Generate observations
3232
# Compute ICA
3333
ica = FastICA()
34-
S_ = ica.fit(X).transform(X) # Get the estimated sources
35-
A_ = ica.get_mixing_matrix() # Get estimated mixing matrix
36-
37-
assert np.allclose(X, np.dot(A_, S_))
34+
S_ = ica.fit(X).transform(X) # Get the estimated sources
35+
A_ = ica.get_mixing_matrix() # Get estimated mixing matrix
36+
assert np.allclose(X, np.dot(S_, A_.T))
3837

3938
###############################################################################
4039
# Plot results
4140
pl.figure()
4241
pl.subplot(3, 1, 1)
43-
pl.plot(S.T)
42+
pl.plot(S)
4443
pl.title('True Sources')
4544
pl.subplot(3, 1, 2)
46-
pl.plot(X.T)
45+
pl.plot(X)
4746
pl.title('Observations (mixed signal)')
4847
pl.subplot(3, 1, 3)
49-
pl.plot(S_.T)
48+
pl.plot(S_)
5049
pl.title('ICA estimated sources')
5150
pl.subplots_adjust(0.09, 0.04, 0.94, 0.94, 0.26, 0.36)
5251
pl.show()

examples/decomposition/plot_ica_vs_pca.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,28 +37,28 @@
3737

3838
###############################################################################
3939
# Generate sample data
40-
S = np.random.standard_t(1.5, size=(2, 10000))
40+
S = np.random.standard_t(1.5, size=(10000, 2))
4141
S[0] *= 2.
4242

4343
# Mix data
44-
A = [[1, 1], [0, 2]] # Mixing matrix
44+
A = np.array([[1, 1], [0, 2]]) # Mixing matrix
4545

46-
X = np.dot(A, S) # Generate observations
46+
X = np.dot(S, A.T) # Generate observations
4747

4848
pca = PCA()
49-
S_pca_ = pca.fit(X.T).transform(X.T).T
49+
S_pca_ = pca.fit(X).transform(X)
5050

5151
ica = FastICA()
5252
S_ica_ = ica.fit(X).transform(X) # Estimate the sources
5353

54-
S_ica_ /= S_ica_.std(axis=1)[:, np.newaxis]
54+
S_ica_ /= S_ica_.std(axis=0)
5555

5656

5757
###############################################################################
5858
# Plot results
5959

6060
def plot_samples(S, axis_list=None):
61-
pl.scatter(S[0], S[1], s=2, marker='o', linewidths=0, zorder=10)
61+
pl.scatter(S[:,0], S[:,1], s=2, marker='o', linewidths=0, zorder=10)
6262
if axis_list is not None:
6363
colors = [(0, 0.6, 0), (0.6, 0, 0)]
6464
for color, axis in zip(colors, axis_list):
@@ -74,8 +74,8 @@ def plot_samples(S, axis_list=None):
7474
pl.vlines(0, -3, 3)
7575
pl.xlim(-3, 3)
7676
pl.ylim(-3, 3)
77-
pl.xlabel('$x$')
78-
pl.ylabel('$y$')
77+
pl.xlabel('x')
78+
pl.ylabel('y')
7979

8080
pl.subplot(2, 2, 1)
8181
plot_samples(S / S.std())
@@ -88,7 +88,7 @@ def plot_samples(S, axis_list=None):
8888
pl.title('Observations')
8989

9090
pl.subplot(2, 2, 3)
91-
plot_samples(S_pca_ / np.std(S_pca_, axis=-1)[:, np.newaxis])
91+
plot_samples(S_pca_ / np.std(S_pca_, axis=0))
9292
pl.title('PCA scores')
9393

9494
pl.subplot(2, 2, 4)

scikits/learn/decomposition/fastica_.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
# License: BSD 3 clause
1111

1212
import types
13+
import warnings
1314
import numpy as np
1415
from scipy import linalg
1516

@@ -182,13 +183,23 @@ def fastica(X, n_components=None, algorithm="parallel", whiten=True,
182183
matrix. In short ICA attempts to `un-mix' the data by estimating an
183184
un-mixing matrix W where S = W K X.
184185
186+
This implementation was originally made for data of shape
187+
[n_features, n_samples]. Now the input is transposed
188+
before the algorithm is applied. This makes it slightly
189+
faster for Fortran-ordered input.
190+
185191
Implemented using FastICA:
186192
187193
* A. Hyvarinen and E. Oja, Independent Component Analysis:
188194
Algorithms and Applications, Neural Networks, 13(4-5), 2000,
189195
pp. 411-430
190196
191197
"""
198+
# make interface compatible with other decompositions
199+
warnings.warn("The interface of fastica changed: X is now\
200+
assumed to be of shape [n_samples, n_features]")
201+
X = X.T
202+
192203
algorithm_funcs = {'parallel': _ica_par,
193204
'deflation': _ica_def}
194205

@@ -281,10 +292,10 @@ def gprime(x, fun_args):
281292

282293
if whiten:
283294
S = np.dot(np.dot(W, K), X)
284-
return K, W, S
295+
return K, W, S.T
285296
else:
286297
S = np.dot(W, X)
287-
return W, S
298+
return W, S.T
288299

289300

290301
class FastICA(BaseEstimator):
@@ -359,9 +370,9 @@ def fit(self, X, **params):
359370
def transform(self, X):
360371
"""Apply un-mixing matrix "W" to X to recover the sources
361372
362-
S = W * X
373+
S = X * W.T
363374
"""
364-
return np.dot(self.unmixing_matrix_, X)
375+
return np.dot(X, self.unmixing_matrix_.T)
365376

366377
def get_mixing_matrix(self):
367378
"""Compute the mixing matrix

scikits/learn/decomposition/tests/test_fastica.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ def test_fastica(add_noise=False):
7171
non_linearity = ['logcosh', 'exp', 'cube']
7272
for nl in non_linearity:
7373
for algo in algorithm:
74-
k_, mixing_, s_ = fastica(m, fun=nl, algorithm=algo)
75-
74+
k_, mixing_, s_ = fastica(m.T, fun=nl, algorithm=algo)
75+
s_ = s_.T
7676
# Check that the mixing model described in the docstring holds:
7777
assert_almost_equal(s_, np.dot(np.dot(mixing_, k_), m))
7878

@@ -122,7 +122,8 @@ def test_non_square_fastica(add_noise=False):
122122

123123
center_and_norm(m)
124124

125-
k_, mixing_, s_ = fastica(m, n_components=2)
125+
k_, mixing_, s_ = fastica(m.T, n_components=2)
126+
s_ = s_.T
126127

127128
# Check that the mixing model described in the docstring holds:
128129
assert_almost_equal(s_, np.dot(np.dot(mixing_, k_), m))

0 commit comments

Comments
 (0)