Switch to unified view

a b/code/preprocessing/EEG/fastica/fpica.m
1
function [A, W] = fpica(X, whiteningMatrix, dewhiteningMatrix, approach, ...
2
            numOfIC, g, finetune, a1, a2, myy, stabilization, ...
3
            epsilon, maxNumIterations, maxFinetune, initState, ...
4
            guess, sampleSize, displayMode, displayInterval, ...
5
            s_verbose);
6
%FPICA - Fixed point ICA. Main algorithm of FASTICA.
7
%
8
% [A, W] = fpica(whitesig, whiteningMatrix, dewhiteningMatrix, approach,
9
%        numOfIC, g, finetune, a1, a2, mu, stabilization, epsilon, 
10
%        maxNumIterations, maxFinetune, initState, guess, sampleSize,
11
%        displayMode, displayInterval, verbose);
12
% 
13
% Perform independent component analysis using Hyvarinen's fixed point
14
% algorithm. Outputs an estimate of the mixing matrix A and its inverse W.
15
%
16
% whitesig                              :the whitened data as row vectors
17
% whiteningMatrix                       :can be obtained with function whitenv
18
% dewhiteningMatrix                     :can be obtained with function whitenv
19
% approach      [ 'symm' | 'defl' ]     :the approach used (deflation or symmetric)
20
% numOfIC       [ 0 - Dim of whitesig ] :number of independent components estimated
21
% g             [ 'pow3' | 'tanh' |     :the nonlinearity used
22
%                 'gaus' | 'skew' ]     
23
% finetune      [same as g + 'off']     :the nonlinearity used in finetuning.
24
% a1                                    :parameter for tuning 'tanh'
25
% a2                                    :parameter for tuning 'gaus'
26
% mu                                    :step size in stabilized algorithm
27
% stabilization [ 'on' | 'off' ]        :if mu < 1 then automatically on
28
% epsilon                               :stopping criterion
29
% maxNumIterations                      :maximum number of iterations 
30
% maxFinetune                           :maximum number of iteretions for finetuning
31
% initState     [ 'rand' | 'guess' ]    :initial guess or random initial state. See below
32
% guess                                 :initial guess for A. Ignored if initState = 'rand'
33
% sampleSize    [ 0 - 1 ]               :percentage of the samples used in one iteration
34
% displayMode   [ 'signals' | 'basis' | :plot running estimate
35
%                 'filters' | 'off' ]
36
% displayInterval                       :number of iterations we take between plots
37
% verbose       [ 'on' | 'off' ]        :report progress in text format
38
%
39
% EXAMPLE
40
%       [E, D] = pcamat(vectors);
41
%       [nv, wm, dwm] = whitenv(vectors, E, D);
42
%       [A, W] = fpica(nv, wm, dwm);
43
%
44
%
45
% This function is needed by FASTICA and FASTICAG
46
%
47
%   See also FASTICA, FASTICAG, WHITENV, PCAMAT
48
49
% @(#)$Id$
50
51
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
52
% Global variable for stopping the ICA calculations from the GUI
53
global g_FastICA_interrupt;
54
if isempty(g_FastICA_interrupt)
55
  clear global g_FastICA_interrupt;
56
  interruptible = 0;
57
else
58
  interruptible = 1;
59
end
60
61
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
62
% Default values
63
64
if nargin < 3, error('Not enough arguments!'); end
65
[vectorSize, numSamples] = size(X);
66
if nargin < 20, s_verbose = 'on'; end
67
if nargin < 19, displayInterval = 1; end
68
if nargin < 18, displayMode = 'on'; end
69
if nargin < 17, sampleSize = 1; end
70
if nargin < 16, guess = 1; end
71
if nargin < 15, initState = 'rand'; end
72
if nargin < 14, maxFinetune = 100; end
73
if nargin < 13, maxNumIterations = 1000; end
74
if nargin < 12, epsilon = 0.0001; end
75
if nargin < 11, stabilization = 'on'; end
76
if nargin < 10, myy = 1; end
77
if nargin < 9, a2 = 1; end
78
if nargin < 8, a1 = 1; end
79
if nargin < 7, finetune = 'off'; end
80
if nargin < 6, g = 'pow3'; end
81
if nargin < 5, numOfIC = vectorSize; end     % vectorSize = Dim
82
if nargin < 4, approach = 'defl'; end
83
84
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
85
% Checking the data
86
87
if ~isreal(X)
88
  error('Input has an imaginary part.');
89
end
90
91
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
92
% Checking the value for verbose
93
94
switch lower(s_verbose)
95
 case 'on'
96
  b_verbose = 1;
97
 case 'off'
98
  b_verbose = 0;
99
 otherwise
100
  error(sprintf('Illegal value [ %s ] for parameter: ''verbose''\n', s_verbose));
101
end
102
103
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
104
% Checking the value for approach
105
106
switch lower(approach)
107
 case 'symm'
108
  approachMode = 1;
109
 case 'defl'
110
  approachMode = 2;
111
 otherwise
112
  error(sprintf('Illegal value [ %s ] for parameter: ''approach''\n', approach));
113
end
114
if b_verbose, fprintf('Used approach [ %s ].\n', approach); end
115
116
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
117
% Checking the value for numOfIC
118
119
if vectorSize < numOfIC
120
  error('Must have numOfIC <= Dimension!');
121
end
122
123
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
124
% Checking the sampleSize
125
if sampleSize > 1
126
  sampleSize = 1;
127
  if b_verbose
128
    fprintf('Warning: Setting ''sampleSize'' to 1.\n');
129
  end  
130
elseif sampleSize < 1
131
  if (sampleSize * numSamples) < 1000
132
    sampleSize = min(1000/numSamples, 1);
133
    if b_verbose
134
      fprintf('Warning: Setting ''sampleSize'' to %0.3f (%d samples).\n', ...
135
          sampleSize, floor(sampleSize * numSamples));
136
    end  
137
  end
138
end
139
if b_verbose
140
  if  b_verbose & (sampleSize < 1)
141
    fprintf('Using about %0.0f%% of the samples in random order in every step.\n',sampleSize*100);
142
  end
143
end
144
145
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
146
% Checking the value for nonlinearity.
147
148
switch lower(g)
149
 case 'pow3'
150
  gOrig = 10;
151
 case 'tanh'
152
  gOrig = 20;
153
 case {'gaus', 'gauss'}
154
  gOrig = 30;
155
 case 'skew'
156
  gOrig = 40;
157
 otherwise
158
  error(sprintf('Illegal value [ %s ] for parameter: ''g''\n', g));
159
end
160
if sampleSize ~= 1
161
  gOrig = gOrig + 2;
162
end
163
if myy ~= 1
164
  gOrig = gOrig + 1;
165
end
166
167
if b_verbose,
168
  fprintf('Used nonlinearity [ %s ].\n', g);
169
end
170
171
finetuningEnabled = 1;
172
switch lower(finetune)
173
 case 'pow3'
174
  gFine = 10 + 1;
175
 case 'tanh'
176
  gFine = 20 + 1;
177
 case {'gaus', 'gauss'}
178
  gFine = 30 + 1;
179
 case 'skew'
180
  gFine = 40 + 1;
181
 case 'off'
182
  if myy ~= 1
183
    gFine = gOrig;
184
  else 
185
    gFine = gOrig + 1;
186
  end
187
  finetuningEnabled = 0;
188
 otherwise
189
  error(sprintf('Illegal value [ %s ] for parameter: ''finetune''\n', ...
190
        finetune));
191
end
192
193
if b_verbose & finetuningEnabled
194
  fprintf('Finetuning enabled (nonlinearity: [ %s ]).\n', finetune);
195
end
196
197
switch lower(stabilization)
198
 case 'on'
199
  stabilizationEnabled = 1;
200
 case 'off'
201
  if myy ~= 1
202
    stabilizationEnabled = 1;
203
  else
204
    stabilizationEnabled = 0;
205
  end
206
 otherwise
207
  error(sprintf('Illegal value [ %s ] for parameter: ''stabilization''\n', ...
208
        stabilization)); 
209
end
210
211
if b_verbose & stabilizationEnabled
212
  fprintf('Using stabilized algorithm.\n');
213
end
214
215
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
216
% Some other parameters
217
myyOrig = myy;
218
% When we start fine-tuning we'll set myy = myyK * myy
219
myyK = 0.01;
220
% How many times do we try for convergence until we give up.
221
failureLimit = 5;
222
223
224
usedNlinearity = gOrig;
225
stroke = 0;
226
notFine = 1;
227
long = 0;
228
229
230
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
231
% Checking the value for initial state.
232
233
switch lower(initState)
234
 case 'rand'
235
  initialStateMode = 0;
236
 case 'guess'
237
  if size(guess,1) ~= size(whiteningMatrix,2)
238
    initialStateMode = 0;
239
    if b_verbose
240
      fprintf('Warning: size of initial guess is incorrect. Using random initial guess.\n');
241
    end
242
  else
243
    initialStateMode = 1;
244
    if size(guess,2) < numOfIC
245
      if b_verbose
246
    fprintf('Warning: initial guess only for first %d components. Using random initial guess for others.\n', size(guess,2)); 
247
      end
248
      guess(:, size(guess, 2) + 1:numOfIC) = ...
249
                         rand(vectorSize,numOfIC-size(guess,2))-.5;
250
    elseif size(guess,2)>numOfIC
251
      guess=guess(:,1:numOfIC);
252
      fprintf('Warning: Initial guess too large. The excess column are dropped.\n');
253
    end
254
    if b_verbose, fprintf('Using initial guess.\n'); end
255
  end
256
 otherwise
257
  error(sprintf('Illegal value [ %s ] for parameter: ''initState''\n', initState));
258
end
259
260
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261
% Checking the value for display mode.
262
263
switch lower(displayMode)
264
 case {'off', 'none'}
265
  usedDisplay = 0;
266
 case {'on', 'signals'}
267
  usedDisplay = 1;
268
  if (b_verbose & (numSamples > 10000))
269
    fprintf('Warning: Data vectors are very long. Plotting may take long time.\n');
270
  end
271
  if (b_verbose & (numOfIC > 25))
272
    fprintf('Warning: There are too many signals to plot. Plot may not look good.\n');
273
  end
274
 case 'basis'
275
  usedDisplay = 2;
276
  if (b_verbose & (numOfIC > 25))
277
    fprintf('Warning: There are too many signals to plot. Plot may not look good.\n');
278
  end
279
 case 'filters'
280
  usedDisplay = 3;
281
  if (b_verbose & (vectorSize > 25))
282
    fprintf('Warning: There are too many signals to plot. Plot may not look good.\n');
283
  end
284
 otherwise
285
  error(sprintf('Illegal value [ %s ] for parameter: ''displayMode''\n', displayMode));
286
end
287
288
% The displayInterval can't be less than 1...
289
if displayInterval < 1
290
  displayInterval = 1;
291
end
292
293
294
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
295
if b_verbose, fprintf('Starting ICA calculation...\n'); end
296
297
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
298
% SYMMETRIC APPROACH
299
if approachMode == 1,
300
301
  % set some parameters more...
302
  usedNlinearity = gOrig;
303
  stroke = 0;
304
  notFine = 1;
305
  long = 0;
306
  
307
  A = zeros(vectorSize, numOfIC);  % Dewhitened basis vectors.
308
  if initialStateMode == 0
309
    % Take random orthonormal initial vectors.
310
    B = orth (randn (vectorSize, numOfIC));
311
  elseif initialStateMode == 1
312
    % Use the given initial vector as the initial state
313
    B = whiteningMatrix * guess;
314
  end
315
  
316
  BOld = zeros(size(B));
317
  BOld2 = zeros(size(B));
318
  
319
  % This is the actual fixed-point iteration loop.
320
  for round = 1:maxNumIterations + 1,
321
    if round == maxNumIterations + 1,
322
      fprintf('No convergence after %d steps\n', maxNumIterations);
323
      fprintf('Note that the plots are probably wrong.\n');
324
      if ~isempty(B)
325
    % Symmetric orthogonalization.
326
    B = B * real(inv(B' * B)^(1/2));
327
328
    W = B' * whiteningMatrix;
329
    A = dewhiteningMatrix * B;
330
      else
331
    W = [];
332
    A = [];
333
      end
334
      return;
335
    end
336
    
337
    if (interruptible & g_FastICA_interrupt)
338
      if b_verbose 
339
        fprintf('\n\nCalculation interrupted by the user\n');
340
      end
341
      if ~isempty(B)
342
    W = B' * whiteningMatrix;
343
    A = dewhiteningMatrix * B;
344
      else
345
    W = [];
346
    A = [];
347
      end
348
      return;
349
    end
350
    
351
    
352
    % Symmetric orthogonalization.
353
    B = B * real(inv(B' * B)^(1/2));
354
    
355
    % Test for termination condition. Note that we consider opposite
356
    % directions here as well.
357
    minAbsCos = min(abs(diag(B' * BOld)));
358
    minAbsCos2 = min(abs(diag(B' * BOld2)));
359
    
360
    if (1 - minAbsCos < epsilon)
361
      if finetuningEnabled & notFine
362
        if b_verbose, fprintf('Initial convergence, fine-tuning: \n'); end;
363
        notFine = 0;
364
        usedNlinearity = gFine;
365
        myy = myyK * myyOrig;
366
        BOld = zeros(size(B));
367
        BOld2 = zeros(size(B));
368
    
369
      else
370
        if b_verbose, fprintf('Convergence after %d steps\n', round); end
371
    
372
        % Calculate the de-whitened vectors.
373
        A = dewhiteningMatrix * B;
374
        break;
375
      end
376
    elseif stabilizationEnabled
377
      if (~stroke) & (1 - minAbsCos2 < epsilon)
378
    if b_verbose, fprintf('Stroke!\n'); end;
379
    stroke = myy;
380
    myy = .5*myy;
381
    if mod(usedNlinearity,2) == 0
382
      usedNlinearity = usedNlinearity + 1;
383
    end
384
      elseif stroke
385
    myy = stroke;
386
    stroke = 0;
387
    if (myy == 1) & (mod(usedNlinearity,2) ~= 0)
388
      usedNlinearity = usedNlinearity - 1;
389
    end
390
      elseif (~long) & (round>maxNumIterations/2)
391
    if b_verbose, fprintf('Taking long (reducing step size)\n'); end;
392
    long = 1;
393
    myy = .5*myy;
394
    if mod(usedNlinearity,2) == 0
395
      usedNlinearity = usedNlinearity + 1;
396
    end
397
      end
398
    end
399
    
400
    BOld2 = BOld;
401
    BOld = B;
402
    
403
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
404
    % Show the progress...
405
    if b_verbose
406
      if round == 1
407
        fprintf('Step no. %d\n', round);
408
      else
409
        fprintf('Step no. %d, change in value of estimate: %.3g \n', round, 1 - minAbsCos);
410
      end
411
    end
412
    
413
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
414
    % Also plot the current state...
415
    switch usedDisplay
416
     case 1
417
      if rem(round, displayInterval) == 0,
418
    % There was and may still be other displaymodes...
419
    % 1D signals
420
    icaplot('dispsig',(X'*B)');
421
    drawnow;
422
      end
423
     case 2
424
      if rem(round, displayInterval) == 0,
425
    % ... and now there are :-)
426
    % 1D basis
427
    A = dewhiteningMatrix * B;
428
    icaplot('dispsig',A');
429
    drawnow;
430
      end
431
     case 3
432
      if rem(round, displayInterval) == 0,
433
    % ... and now there are :-)
434
    % 1D filters
435
    W = B' * whiteningMatrix;
436
    icaplot('dispsig',W);
437
    drawnow;
438
      end
439
     otherwise
440
    end
441
    
442
    switch usedNlinearity
443
      % pow3
444
     case 10
445
      B = (X * (( X' * B) .^ 3)) / numSamples - 3 * B;
446
     case 11
447
      % optimoitu - epsilonin kokoisia eroja
448
      % tämä on optimoitu koodi, katso vanha koodi esim.
449
      % aikaisemmista versioista kuten 2.0 beta3
450
      Y = X' * B;
451
      Gpow3 = Y .^ 3;
452
      Beta = sum(Y .* Gpow3);
453
      D = diag(1 ./ (Beta - 3 * numSamples));
454
      B = B + myy * B * (Y' * Gpow3 - diag(Beta)) * D;
455
     case 12
456
      Xsub=X(:, getSamples(numSamples, sampleSize));
457
      B = (Xsub * (( Xsub' * B) .^ 3)) / size(Xsub,2) - 3 * B;
458
     case 13
459
      % Optimoitu
460
      Ysub=X(:, getSamples(numSamples, sampleSize))' * B;
461
      Gpow3 = Ysub .^ 3;
462
      Beta = sum(Ysub .* Gpow3);
463
      D = diag(1 ./ (Beta - 3 * size(Ysub', 2)));
464
      B = B + myy * B * (Ysub' * Gpow3 - diag(Beta)) * D;
465
      
466
      % tanh
467
     case 20
468
      hypTan = tanh(a1 * X' * B);
469
      B = X * hypTan / numSamples - ...
470
      ones(size(B,1),1) * sum(1 - hypTan .^ 2) .* B / numSamples * ...
471
      a1;
472
     case 21
473
      % optimoitu - epsilonin kokoisia 
474
      Y = X' * B;
475
      hypTan = tanh(a1 * Y);
476
      Beta = sum(Y .* hypTan);
477
      D = diag(1 ./ (Beta - a1 * sum(1 - hypTan .^ 2)));
478
      B = B + myy * B * (Y' * hypTan - diag(Beta)) * D;
479
     case 22
480
      Xsub=X(:, getSamples(numSamples, sampleSize));
481
      hypTan = tanh(a1 * Xsub' * B);
482
      B = Xsub * hypTan / size(Xsub, 2) - ...
483
      ones(size(B,1),1) * sum(1 - hypTan .^ 2) .* B / size(Xsub, 2) * a1;
484
     case 23
485
      % Optimoitu
486
      Y = X(:, getSamples(numSamples, sampleSize))' * B;
487
      hypTan = tanh(a1 * Y);
488
      Beta = sum(Y .* hypTan);
489
      D = diag(1 ./ (Beta - a1 * sum(1 - hypTan .^ 2)));
490
      B = B + myy * B * (Y' * hypTan - diag(Beta)) * D;
491
      
492
      % gauss
493
     case 30
494
      U = X' * B;
495
      Usquared=U .^ 2;
496
      ex = exp(-a2 * Usquared / 2);
497
      gauss =  U .* ex;
498
      dGauss = (1 - a2 * Usquared) .*ex;
499
      B = X * gauss / numSamples - ...
500
      ones(size(B,1),1) * sum(dGauss)...
501
      .* B / numSamples ;
502
     case 31
503
      % optimoitu
504
      Y = X' * B;
505
      ex = exp(-a2 * (Y .^ 2) / 2);
506
      gauss = Y .* ex;
507
      Beta = sum(Y .* gauss);
508
      D = diag(1 ./ (Beta - sum((1 - a2 * (Y .^ 2)) .* ex)));
509
      B = B + myy * B * (Y' * gauss - diag(Beta)) * D;
510
     case 32
511
      Xsub=X(:, getSamples(numSamples, sampleSize));
512
      U = Xsub' * B;
513
      Usquared=U .^ 2;
514
      ex = exp(-a2 * Usquared / 2);
515
      gauss =  U .* ex;
516
      dGauss = (1 - a2 * Usquared) .*ex;
517
      B = Xsub * gauss / size(Xsub,2) - ...
518
      ones(size(B,1),1) * sum(dGauss)...
519
      .* B / size(Xsub,2) ;
520
     case 33
521
      % Optimoitu
522
      Y = X(:, getSamples(numSamples, sampleSize))' * B;
523
      ex = exp(-a2 * (Y .^ 2) / 2);
524
      gauss = Y .* ex;
525
      Beta = sum(Y .* gauss);
526
      D = diag(1 ./ (Beta - sum((1 - a2 * (Y .^ 2)) .* ex)));
527
      B = B + myy * B * (Y' * gauss - diag(Beta)) * D;
528
      
529
      % skew
530
     case 40
531
      B = (X * ((X' * B) .^ 2)) / numSamples;
532
     case 41
533
      % Optimoitu
534
      Y = X' * B;
535
      Gskew = Y .^ 2;
536
      Beta = sum(Y .* Gskew);
537
      D = diag(1 ./ (Beta));
538
      B = B + myy * B * (Y' * Gskew - diag(Beta)) * D;
539
     case 42
540
      Xsub=X(:, getSamples(numSamples, sampleSize));
541
      B = (Xsub * ((Xsub' * B) .^ 2)) / size(Xsub,2);
542
     case 43
543
      % Uusi optimoitu
544
      Y = X(:, getSamples(numSamples, sampleSize))' * B;
545
      Gskew = Y .^ 2;
546
      Beta = sum(Y .* Gskew);
547
      D = diag(1 ./ (Beta));
548
      B = B + myy * B * (Y' * Gskew - diag(Beta)) * D;
549
550
     otherwise
551
      error('Code for desired nonlinearity not found!');
552
    end
553
  end
554
555
  
556
  % Calculate ICA filters.
557
  W = B' * whiteningMatrix;
558
  
559
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
560
  % Also plot the last one...
561
  switch usedDisplay
562
   case 1 
563
    % There was and may still be other displaymodes...
564
    % 1D signals
565
    icaplot('dispsig',(X'*B)');
566
    drawnow;
567
   case 2
568
    % ... and now there are :-)
569
    % 1D basis
570
    icaplot('dispsig',A');
571
    drawnow;
572
   case 3
573
    % ... and now there are :-)
574
    % 1D filters
575
    icaplot('dispsig',W);
576
    drawnow;
577
   otherwise
578
  end
579
end
580
581
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
582
% DEFLATION APPROACH
583
if approachMode == 2
584
  
585
  B = zeros(vectorSize);
586
  
587
  % The search for a basis vector is repeated numOfIC times.
588
  round = 1;
589
  
590
  numFailures = 0;
591
  
592
  while round <= numOfIC,
593
    myy = myyOrig;
594
    usedNlinearity = gOrig;
595
    stroke = 0;
596
    notFine = 1;
597
    long = 0;
598
    endFinetuning = 0;
599
    
600
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
601
    % Show the progress...
602
    if b_verbose, fprintf('IC %d ', round); end
603
    
604
    % Take a random initial vector of lenght 1 and orthogonalize it
605
    % with respect to the other vectors.
606
    if initialStateMode == 0
607
      w = randn (vectorSize, 1);
608
    elseif initialStateMode == 1
609
      w=whiteningMatrix*guess(:,round);
610
    end
611
    w = w - B * B' * w;
612
    w = w / norm(w);
613
    
614
    wOld = zeros(size(w));
615
    wOld2 = zeros(size(w));
616
    
617
    % This is the actual fixed-point iteration loop.
618
    %    for i = 1 : maxNumIterations + 1
619
    i = 1;
620
    gabba = 1;
621
    while i <= maxNumIterations + gabba
622
      if (usedDisplay > 0)
623
    drawnow;
624
      end
625
      if (interruptible & g_FastICA_interrupt)
626
        if b_verbose 
627
          fprintf('\n\nCalculation interrupted by the user\n');
628
        end
629
        return;
630
      end
631
      
632
      % Project the vector into the space orthogonal to the space
633
      % spanned by the earlier found basis vectors. Note that we can do
634
      % the projection with matrix B, since the zero entries do not
635
      % contribute to the projection.
636
      w = w - B * B' * w;
637
      w = w / norm(w);
638
      
639
      if notFine
640
    if i == maxNumIterations + 1
641
      if b_verbose
642
        fprintf('\nComponent number %d did not converge in %d iterations.\n', round, maxNumIterations);
643
      end
644
      round = round - 1;
645
      numFailures = numFailures + 1;
646
      if numFailures > failureLimit
647
        if b_verbose
648
          fprintf('Too many failures to converge (%d). Giving up.\n', numFailures);
649
        end
650
        if round == 0
651
          A=[];
652
          W=[];
653
        end
654
        return;
655
      end
656
      % numFailures > failurelimit
657
      break;
658
    end
659
    % i == maxNumIterations + 1
660
      else
661
    % if notFine
662
    if i >= endFinetuning
663
      wOld = w; % So the algorithm will stop on the next test...
664
    end
665
      end
666
      % if notFine
667
      
668
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
669
      % Show the progress...
670
      if b_verbose, fprintf('.'); end;
671
      
672
      
673
      % Test for termination condition. Note that the algorithm has
674
      % converged if the direction of w and wOld is the same, this
675
      % is why we test the two cases.
676
      if norm(w - wOld) < epsilon | norm(w + wOld) < epsilon
677
        if finetuningEnabled & notFine
678
          if b_verbose, fprintf('Initial convergence, fine-tuning: '); end;
679
          notFine = 0;
680
      gabba = maxFinetune;
681
          wOld = zeros(size(w));
682
          wOld2 = zeros(size(w));
683
          usedNlinearity = gFine;
684
          myy = myyK * myyOrig;
685
      
686
      endFinetuning = maxFinetune + i;
687
      
688
        else
689
          numFailures = 0;
690
          % Save the vector
691
          B(:, round) = w;
692
      
693
          % Calculate the de-whitened vector.
694
          A(:,round) = dewhiteningMatrix * w;
695
          % Calculate ICA filter.
696
          W(round,:) = w' * whiteningMatrix;
697
      
698
          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
699
          % Show the progress...
700
          if b_verbose, fprintf('computed ( %d steps ) \n', i); end
701
      
702
          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
703
          % Also plot the current state...
704
          switch usedDisplay
705
       case 1
706
        if rem(round, displayInterval) == 0,
707
          % There was and may still be other displaymodes...   
708
          % 1D signals
709
          temp = X'*B;
710
          icaplot('dispsig',temp(:,1:numOfIC)');
711
          drawnow;
712
        end
713
       case 2
714
        if rem(round, displayInterval) == 0,
715
          % ... and now there are :-) 
716
          % 1D basis
717
          icaplot('dispsig',A');
718
          drawnow;
719
        end
720
       case 3
721
        if rem(round, displayInterval) == 0,
722
          % ... and now there are :-) 
723
          % 1D filters
724
          icaplot('dispsig',W);
725
          drawnow;
726
        end
727
          end
728
      % switch usedDisplay
729
      break; % IC ready - next...
730
        end
731
    %if finetuningEnabled & notFine
732
      elseif stabilizationEnabled
733
    if (~stroke) & (norm(w - wOld2) < epsilon | norm(w + wOld2) < ...
734
            epsilon)
735
      stroke = myy;
736
      if b_verbose, fprintf('Stroke!'); end;
737
      myy = .5*myy;
738
      if mod(usedNlinearity,2) == 0
739
        usedNlinearity = usedNlinearity + 1;
740
      end
741
    elseif stroke
742
      myy = stroke;
743
      stroke = 0;
744
      if (myy == 1) & (mod(usedNlinearity,2) ~= 0)
745
        usedNlinearity = usedNlinearity - 1;
746
      end
747
    elseif (notFine) & (~long) & (i > maxNumIterations / 2)
748
      if b_verbose, fprintf('Taking long (reducing step size) '); end;
749
      long = 1;
750
      myy = .5*myy;
751
      if mod(usedNlinearity,2) == 0
752
        usedNlinearity = usedNlinearity + 1;
753
      end
754
    end
755
      end
756
      
757
      wOld2 = wOld;
758
      wOld = w;
759
      
760
      switch usedNlinearity
761
    % pow3
762
       case 10
763
    w = (X * ((X' * w) .^ 3)) / numSamples - 3 * w;
764
       case 11
765
    EXGpow3 = (X * ((X' * w) .^ 3)) / numSamples;
766
    Beta = w' * EXGpow3;
767
    w = w - myy * (EXGpow3 - Beta * w) / (3 - Beta);
768
       case 12
769
    Xsub=X(:,getSamples(numSamples, sampleSize));
770
    w = (Xsub * ((Xsub' * w) .^ 3)) / size(Xsub, 2) - 3 * w;
771
       case 13
772
    Xsub=X(:,getSamples(numSamples, sampleSize));
773
    EXGpow3 = (Xsub * ((Xsub' * w) .^ 3)) / size(Xsub, 2);
774
    Beta = w' * EXGpow3;
775
    w = w - myy * (EXGpow3 - Beta * w) / (3 - Beta);
776
    % tanh
777
       case 20
778
    % #########################################################################
779
    % Riccardo Navarra "Mod" 10 Feb 2010 (*)          (r.navarra@itab.unich.it)
780
    % Rewritten matrix product to speed up on multicore CPU (fpica.m)
781
    % #########################################################################
782
    hypTan = tanh(a1 * (X' * w));
783
    % #########################################################################
784
    w = (X * hypTan - a1 * sum(1 - hypTan .^ 2)' * w) / numSamples;
785
       case 21
786
    hypTan = tanh(a1 * X' * w);
787
    Beta = w' * X * hypTan;
788
    w = w - myy * ((X * hypTan - Beta * w) / ...
789
               (a1 * sum((1-hypTan .^2)') - Beta));
790
       case 22
791
    Xsub=X(:,getSamples(numSamples, sampleSize));
792
    hypTan = tanh(a1 * Xsub' * w);
793
    w = (Xsub * hypTan - a1 * sum(1 - hypTan .^ 2)' * w) / size(Xsub, 2);
794
       case 23
795
    Xsub=X(:,getSamples(numSamples, sampleSize));
796
    hypTan = tanh(a1 * Xsub' * w);
797
    Beta = w' * Xsub * hypTan;
798
    w = w - myy * ((Xsub * hypTan - Beta * w) / ...
799
               (a1 * sum((1-hypTan .^2)') - Beta));
800
    % gauss
801
       case 30
802
    % This has been split for performance reasons.
803
    u = X' * w;
804
    u2=u.^2;
805
    ex=exp(-a2 * u2/2);
806
    gauss =  u.*ex;
807
    dGauss = (1 - a2 * u2) .*ex;
808
    w = (X * gauss - sum(dGauss)' * w) / numSamples;
809
       case 31
810
    u = X' * w;
811
    u2=u.^2;
812
    ex=exp(-a2 * u2/2);
813
    gauss =  u.*ex;
814
    dGauss = (1 - a2 * u2) .*ex;
815
    Beta = w' * X * gauss;
816
    w = w - myy * ((X * gauss - Beta * w) / ...
817
               (sum(dGauss)' - Beta));
818
       case 32
819
    Xsub=X(:,getSamples(numSamples, sampleSize));
820
    u = Xsub' * w;
821
    u2=u.^2;
822
    ex=exp(-a2 * u2/2);
823
    gauss =  u.*ex;
824
    dGauss = (1 - a2 * u2) .*ex;
825
    w = (Xsub * gauss - sum(dGauss)' * w) / size(Xsub, 2);
826
       case 33
827
    Xsub=X(:,getSamples(numSamples, sampleSize));
828
    u = Xsub' * w;
829
    u2=u.^2;
830
    ex=exp(-a2 * u2/2);
831
    gauss =  u.*ex;
832
    dGauss = (1 - a2 * u2) .*ex;
833
    Beta = w' * Xsub * gauss;
834
    w = w - myy * ((Xsub * gauss - Beta * w) / ...
835
               (sum(dGauss)' - Beta));
836
    % skew
837
       case 40
838
    w = (X * ((X' * w) .^ 2)) / numSamples;
839
       case 41
840
    EXGskew = (X * ((X' * w) .^ 2)) / numSamples;
841
    Beta = w' * EXGskew;
842
    w = w - myy * (EXGskew - Beta*w)/(-Beta);
843
       case 42
844
    Xsub=X(:,getSamples(numSamples, sampleSize));
845
    w = (Xsub * ((Xsub' * w) .^ 2)) / size(Xsub, 2);
846
       case 43
847
    Xsub=X(:,getSamples(numSamples, sampleSize));
848
    EXGskew = (Xsub * ((Xsub' * w) .^ 2)) / size(Xsub, 2);
849
    Beta = w' * EXGskew;
850
    w = w - myy * (EXGskew - Beta*w)/(-Beta);
851
    
852
       otherwise
853
    error('Code for desired nonlinearity not found!');
854
      end
855
      
856
      % Normalize the new w.
857
      w = w / norm(w);
858
      i = i + 1;
859
    end
860
    round = round + 1;
861
  end
862
  if b_verbose, fprintf('Done.\n'); end
863
  
864
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
865
  % Also plot the ones that may not have been plotted.
866
  if (usedDisplay > 0) & (rem(round-1, displayInterval) ~= 0)
867
    switch usedDisplay
868
     case 1
869
      % There was and may still be other displaymodes...
870
      % 1D signals
871
      temp = X'*B;
872
      icaplot('dispsig',temp(:,1:numOfIC)');
873
      drawnow;
874
     case 2
875
      % ... and now there are :-)
876
      % 1D basis
877
      icaplot('dispsig',A');
878
      drawnow;
879
     case 3
880
      % ... and now there are :-)
881
      % 1D filters
882
      icaplot('dispsig',W);
883
      drawnow;
884
     otherwise
885
    end
886
  end
887
end
888
889
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
890
% In the end let's check the data for some security
891
if ~isreal(A)
892
  if b_verbose, fprintf('Warning: removing the imaginary part from the result.\n'); end
893
  A = real(A);
894
  W = real(W);
895
end
896
897
898
899
900
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
901
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
902
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
903
% Subfunction
904
% Calculates tanh simplier and faster than Matlab tanh.
905
function y=tanh(x)
906
y = 1 - 2 ./ (exp(2 * x) + 1);
907
908
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
909
function Samples = getSamples(max, percentage)
910
Samples = find(rand(1, max) < percentage);