-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
change fixation plot color to be default and random over plots AND ch…
…ange the transition matrix image color(color gray --> colormap default)
- Loading branch information
Showing
166 changed files
with
10,894 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
%If you use this toolbox, please cite Coutrot et al., | ||
%"Scanpath modeling and classification with Hidden Markov Models", Behavior | ||
%Research Methods, 2017 | ||
% Classify tasks from Coutrot's dataset (conversational videos, 2 auditory conditions) with HMM-based gaze descriptors | ||
clear | ||
close all | ||
load HMM_descriptor_Coutrot %computed with exemple_Compute_HMM_descriptors.m | ||
all_stim=fieldnames(example_HMM_descriptor_Coutrot); | ||
|
||
%LDA 1st Eigen Vector | ||
%ini_stim=char(all_stim(1)); | ||
%ini_descriptor=example_HMM_descriptor_Coutrot.(ini_stim).with_os.gaze_descriptor; | ||
%LDA_1st_Eigen_vect=NaN(size(ini_descriptor,2),length(all_stim)); | ||
|
||
%Correct classification vector | ||
correct_classif=NaN(length(all_stim),1); | ||
|
||
% For each stimulus, a correct classification score is computed | ||
for istim=1:length(all_stim) | ||
|
||
im_name=char(all_stim(istim)); | ||
|
||
%% Load HMM-based gaze descriptors from HMM_descriptor_Coutrot.mat | ||
gaze_descriptor_ws=example_HMM_descriptor_Coutrot.(im_name).with_os.gaze_descriptor; | ||
gaze_descriptor_wos=example_HMM_descriptor_Coutrot.(im_name).without_os.gaze_descriptor; | ||
|
||
%% Normalization to zero mean and unit std | ||
norm_gaze_descriptor_ws=zscore(gaze_descriptor_ws')'; | ||
norm_gaze_descriptor_wos=zscore(gaze_descriptor_wos')'; | ||
|
||
%% Regularization | ||
all_task = [norm_gaze_descriptor_ws;norm_gaze_descriptor_wos]; | ||
lambda_I_all=0.00001*eye(size(all_task)); | ||
regul_gaze_descriptor_all = all_task - lambda_I_all.*all_task + lambda_I_all ; | ||
regul_gaze_descriptor_ws=regul_gaze_descriptor_all(1:size(norm_gaze_descriptor_ws,1),:); | ||
regul_gaze_descriptor_wos=regul_gaze_descriptor_all(size(norm_gaze_descriptor_ws,1)+1:... | ||
size(norm_gaze_descriptor_ws,1)+size(norm_gaze_descriptor_wos,1),:); | ||
|
||
|
||
%% Choose classes to classify | ||
gaze_descriptors={regul_gaze_descriptor_ws, regul_gaze_descriptor_wos}; | ||
categoric_var={'with_os', 'without_os'}; | ||
|
||
%% Select type of classifier | ||
classifier_type='LDA'; | ||
% classifier_type='diagquadratic'; | ||
% classifier_type='mahalanobis'; | ||
%classifier_type='SVMBinary'; | ||
%classifier_type='SVMMultiClass'; | ||
%classifier_type='AdaBoostBinary'; | ||
%classifier_type='AdaBoostMultiClass'; | ||
% classifier_type='RVM';%Only for 2-class problems | ||
% classifier_type='AdaBoost';%Only for 2-class problems | ||
% classifier_type= 'RandomForest'; | ||
|
||
%% k-fold cross-validation | ||
cross_validation=1; | ||
% % if cross_validation==1 | ||
% % leave-one-out | ||
% % else | ||
% % 'k'-cross_validation | ||
% % end | ||
try | ||
[lda_stats, success_rate] = classifier(categoric_var, gaze_descriptors,classifier_type,cross_validation); | ||
|
||
% %LDA 1st Eigen vector: absolute values and normalization | ||
% lda_stats.eigenvec(:,1)=abs(lda_stats.eigenvec(:,1)); | ||
% LDA_1st_Eigen_vect(:,istim)=lda_stats.eigenvec(:,1)/sum(lda_stats.eigenvec(:,1)); | ||
catch | ||
fprintf('stimuli %u could not be classified\n',istim) | ||
success_rate=NaN; | ||
manova_stats=NaN; | ||
end | ||
|
||
if ~mod(istim,1) | ||
fprintf('stimuli %u success_rate %d\n',istim, success_rate) | ||
end | ||
|
||
correct_classif(istim)=success_rate; | ||
end | ||
|
||
fprintf('average correct classification score over %u stimuli is %3.1f %% (chance = %3.1f %%)\n',length(all_stim), 100*nanmean(correct_classif),100/length(categoric_var)) | ||
hist(correct_classif) | ||
xlabel('Correct Classification Rate','FontSize',12,'FontWeight','bold') | ||
ylabel('Frequency','FontSize',12,'FontWeight','bold') | ||
|
||
% errorbar(squeeze(nanmean(abs(LDA_1st_Eigen_vect),2)),nanstd(abs(LDA_1st_Eigen_vect),0,2)/sqrt(length(all_stim)),'.') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
%If you use this toolbox, please cite Coutrot et al., | ||
%"Scanpath modeling and classification with Hidden Markov Models", Behavior | ||
%Research Methods, 2017 | ||
% Classify tasks from Koehler's dataset (static images, 3 tasks) with HMM-based gaze descriptors | ||
clear | ||
close all | ||
load HMM_descriptor_Koehler %computed with exemple_Compute_HMM_descriptors.m | ||
all_stim=fieldnames(example_HMM_descriptor); | ||
ini_stim=char(all_stim(1)); | ||
ini_descriptor=example_HMM_descriptor.(ini_stim).freeview.gaze_descriptor; | ||
%LDA 1st Eigen Vector | ||
%LDA_1st_Eigen_vect=NaN(size(ini_descriptor,2),length(all_stim)); | ||
%Correct classification vector | ||
correct_classif=NaN(length(all_stim),1); | ||
|
||
% For each stimulus, a correct classification score is computed | ||
for istim=1:length(all_stim) | ||
|
||
im_name=char(all_stim(istim)); | ||
|
||
%% Load HMM-based gaze descriptors from example_HMM_descriptor.mat | ||
gaze_descriptor_free=example_HMM_descriptor.(im_name).freeview.gaze_descriptor; | ||
gaze_descriptor_sal=example_HMM_descriptor.(im_name).salview.gaze_descriptor; | ||
gaze_descriptor_obj=example_HMM_descriptor.(im_name).objsearch.gaze_descriptor; | ||
|
||
%% Normalization to zero mean and unit std | ||
norm_gaze_descriptor_free=zscore(gaze_descriptor_free')'; | ||
norm_gaze_descriptor_sal=zscore(gaze_descriptor_sal')'; | ||
norm_gaze_descriptor_obj=zscore(gaze_descriptor_obj')'; | ||
|
||
%% Regularization | ||
all_task = [norm_gaze_descriptor_free;norm_gaze_descriptor_sal;norm_gaze_descriptor_obj]; | ||
lambda_I_all=0.00001*eye(size(all_task)); | ||
regul_gaze_descriptor_all = all_task - lambda_I_all.*all_task + lambda_I_all ; | ||
regul_gaze_descriptor_free=regul_gaze_descriptor_all(1:size(norm_gaze_descriptor_free,1),:); | ||
regul_gaze_descriptor_sal=regul_gaze_descriptor_all(size(norm_gaze_descriptor_free,1)+1:size(norm_gaze_descriptor_free,1)+size(norm_gaze_descriptor_sal,1),:); | ||
regul_gaze_descriptor_obj=regul_gaze_descriptor_all(size(norm_gaze_descriptor_free,1)+size(norm_gaze_descriptor_sal,1)+1:size(norm_gaze_descriptor_free,1)+size(norm_gaze_descriptor_sal,1)+size(norm_gaze_descriptor_obj,1),:); | ||
|
||
|
||
%% Choose classes to classify | ||
% categoric_var={'free', 'sal', 'obj'}; | ||
% gaze_descriptors={regul_gaze_descriptor_free, regul_gaze_descriptor_sal, regul_gaze_descriptor_obj}; | ||
|
||
gaze_descriptors={regul_gaze_descriptor_free, regul_gaze_descriptor_sal, regul_gaze_descriptor_obj}; | ||
categoric_var={'free', 'sal', 'obj'}; | ||
|
||
%% Select type of classifier | ||
classifier_type='LDA'; | ||
% classifier_type='diagquadratic'; | ||
% classifier_type='mahalanobis'; | ||
%classifier_type='SVMBinary'; | ||
%classifier_type='SVMMultiClass'; | ||
%classifier_type='AdaBoostBinary'; | ||
%classifier_type='AdaBoostMultiClass'; | ||
% classifier_type='RVM';%Only for 2-class problems | ||
% classifier_type='AdaBoost';%Only for 2-class problems | ||
% classifier_type= 'RandomForest'; | ||
|
||
%% k-fold cross-validation | ||
cross_validation=1; | ||
% % if cross_validation==1 | ||
% % leave-one-out | ||
% % else | ||
% % 'k'-cross_validation | ||
% % end | ||
try | ||
[lda_stats, success_rate] = classifier(categoric_var, gaze_descriptors,classifier_type,cross_validation); | ||
|
||
% %LDA 1st Eigen vector: absolute values and normalization | ||
% lda_stats.eigenvec(:,1)=abs(lda_stats.eigenvec(:,1)); | ||
% LDA_1st_Eigen_vect(:,istim)=lda_stats.eigenvec(:,1)/sum(lda_stats.eigenvec(:,1)); | ||
catch | ||
fprintf('stimuli %u could not be classified\n',istim) | ||
success_rate=NaN; | ||
manova_stats=NaN; | ||
end | ||
|
||
if ~mod(istim,10) | ||
fprintf('stimuli %u success_rate %d\n',istim, success_rate) | ||
end | ||
|
||
correct_classif(istim)=success_rate; | ||
end | ||
|
||
fprintf('average correct classification score over %u stimuli is %3.1f %% (chance = %3.1f %%)\n',length(all_stim), 100*nanmean(correct_classif),100/length(categoric_var)) | ||
hist(correct_classif,40) | ||
xlabel('Correct Classification Rate') | ||
ylabel('Frequency') | ||
|
||
% errorbar(squeeze(nanmean(abs(LDA_1st_Eigen_vect),2)),nanstd(abs(LDA_1st_Eigen_vect),0,2)/sqrt(length(all_stim)),'.') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
%If you use this toolbox, please cite Coutrot et al., | ||
%"Scanpath modeling and classification with Hidden Markov Models", Behavior | ||
%Research Methods, 2017 | ||
|
||
% Compute HMM-based gaze descriptors for Koehler's dataset (static images, 3 tasks) | ||
clear | ||
close all | ||
addpath ./stimuli/Frames_Coutrot/ % where the stimuli are stored | ||
addpath(genpath('emhmm-toolbox')) | ||
load EyeData_Coutrot % contains eye positions from Coutrot & Guyader, JoV 2014 | ||
|
||
% variational approach: automatically selects optimal state number from K = 1 to 3 | ||
K = 1:3; | ||
% [priors transition_matrix_coeff state_centre state_cov] | ||
param_nb=max(K)+max(K)^2+max(K)*2+max(K)*2; | ||
%plot the HMM states on the stimuli | ||
isplotHMM=1; | ||
|
||
nstim=size(example_EyeData_Coutrot.with_os.x_pos,2); %number of stimuli | ||
for istim=1:nstim | ||
fprintf('stim %u\n',istim) | ||
%close all | ||
|
||
% Read stimuli | ||
im_name=['clip_' num2str(istim) '.jpg']; | ||
im_name_struct=['clip__' num2str(istim)]; | ||
im= imread(im_name); | ||
|
||
% Maximum number of observer per task | ||
maxsub=max([size(example_EyeData_Coutrot.with_os.x_pos,1),size(example_EyeData_Coutrot.without_os.x_pos,1)]); | ||
% Initialize gaze descriptor vector | ||
gaze_descriptor_ws=NaN(maxsub,param_nb); | ||
gaze_descriptor_wos=NaN(maxsub,param_nb); | ||
|
||
% Loop on subjects | ||
for isub=1:maxsub | ||
|
||
%% Auditory Condition 1: With Orginal Soundtrack | ||
|
||
% Extract current scanpath | ||
scanpath_ws = extract_scanpath(example_EyeData_Coutrot,'with_os',isub,istim,K); | ||
if ~isempty(scanpath_ws{1,1}) | ||
% Compute corresponding HMM | ||
vbopt=initialize_HMM_computation(im); | ||
[hmm_ws,~] = vbhmm_learn(scanpath_ws, K, vbopt); | ||
|
||
% sort states from left to right | ||
hmm_ws = sort_hmm_state(hmm_ws); | ||
|
||
% add 'ghost states' if K < Kmax so all gaze descriptor vectors have the same dimension | ||
hmm_ws=pad_with_ghost_states(hmm_ws,max(K),im); | ||
|
||
%Extract gaze_descriptor vector from HMM parameters: priors, transition matrix coefficients, state centres and state covariances | ||
gaze_descriptor_ws(isub,:) =extract_hmm_parameters(hmm_ws); | ||
|
||
if isplotHMM | ||
subplot(1,3,1) | ||
plot_hmm_state(hmm_ws,scanpath_ws,im) | ||
title WithSound | ||
end | ||
end | ||
%% Auditory Condition 2: Without Orginal Soundtrack | ||
|
||
% Extract current scanpath | ||
scanpath_wos = extract_scanpath(example_EyeData_Coutrot,'without_os',isub,istim,K); | ||
if ~isempty(scanpath_wos{1,1}) | ||
% Compute corresponding HMM | ||
vbopt=initialize_HMM_computation(im); | ||
vbopt.do_constrain_var=1; | ||
[hmm_wos,~] = vbhmm_learn(scanpath_wos, K, vbopt); | ||
|
||
% sort states from left to right | ||
hmm_wos = sort_hmm_state(hmm_wos); | ||
|
||
% add 'ghost states' if K < Kmax so all gaze descriptor vectors have the same dimension | ||
hmm_wos=pad_with_ghost_states(hmm_wos,max(K),im); | ||
|
||
%Extract gaze_descriptor vector from HMM parameters: | ||
%priors, transition matrix coefficients, state centres and state covariances | ||
gaze_descriptor_wos(isub,:) =extract_hmm_parameters(hmm_wos); | ||
|
||
if isplotHMM | ||
subplot(1,3,2) | ||
plot_hmm_state(hmm_wos,scanpath_wos,im) | ||
title WithoutSound | ||
pause(0.1) | ||
end | ||
end | ||
end | ||
|
||
gaze_descriptor_ws(isnan(gaze_descriptor_ws(:,1)),:)=[]; | ||
gaze_descriptor_wos(isnan(gaze_descriptor_wos(:,1)),:)=[]; | ||
|
||
HMM_descriptor_Coutrot.(im_name_struct).with_os.gaze_descriptor=gaze_descriptor_ws; | ||
HMM_descriptor_Coutrot.(im_name_struct).without_os.gaze_descriptor=gaze_descriptor_wos; | ||
|
||
end | ||
save('HMM_descriptor_Coutrot','HMM_descriptor_Coutrot') | ||
|
||
|
Oops, something went wrong.