petejonze / QuestPlus

QuestPlus: a MATLAB implementation of the QUEST+ adaptive psychometric method
Other
11 stars 3 forks source link

getParamEsts('median') seems to be depend on the order of parameters of psychometric function. #2

Open kurokida opened 3 years ago

kurokida commented 3 years ago

Thank you for great scripts!

I'm a developer of jsQUEST which is a JavaScript library for the QUEST method in online experiments.

During the development of jsQUEST, we noticed the following.

getParamEsts('median') seems to be depend on the order of parameters of psychometric function.


% This demonstration corresponds to Contrast sensitivity function {2, 3, 2}
% in Watson (2017).

F1 = @(freq, contrast, threshold, c0, cf)([test(freq, contrast, threshold, c0, cf), 1-test(freq, contrast, threshold, c0, cf)]);
stimDomain1 = {0:2:40, -50:2:0};
paramDomain1 = {-50:2:-30, -60:2:-40, 0.8:0.2:1.6};

F2 = @(contrast, freq, cf, c0, threshold)([test(freq, contrast, threshold, c0, cf), 1-test(freq, contrast, threshold, c0, cf)]);
stimDomain2 = {stimDomain1{2}, stimDomain1{1}}; % just swapping the order of stimDomain1.
paramDomain2 = {paramDomain1{3}, paramDomain1{2}, paramDomain1{1}}; % just swapping the order of paramDomain1.

respDomain = [0 1];

QP1 = QuestPlus(F1, stimDomain1, paramDomain1, respDomain, [], 2.5);
QP1.initialise();

QP2 = QuestPlus(F2, stimDomain2, paramDomain2, respDomain, [], 2.5);
QP2.initialise();

simulated_answers = [1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1];

for i = 1:length(simulated_answers)    
    targ = QP1.getTargetStim();
    QP1.update(targ, simulated_answers(i));

    targ = QP2.getTargetStim();
    QP2.update(targ, simulated_answers(i));

end

% QP1_mode is the same as QP2_mode
QP1_mode = QP1.getParamEsts('mode')
QP2_mode = QP2.getParamEsts('mode')

% QP1_mean1 is the same as QP2_mean1
QP1_mean1 = QP1.getParamEsts('mean')
QP2_mean1 = QP2.getParamEsts('mean')

% QP1_mean2 is the same as QP2_mean2
QP1_mean2 = QP1.getParamEsts('mean', false)
QP2_mean2 = QP2.getParamEsts('mean', false)

% These are not the same.
QP1_median = QP1.getParamEsts('median') % The threshold estimate is -38 
QP2_median = QP2.getParamEsts('median') % The threshold estimate is -32

function L = weibull(x, threshold, slope, guess, lapse)
    L = lapse - (guess + lapse - 1)*exp(-10^(slope*(x - threshold)/20));
end

function L = test(freq, contrast, threshold, c0, cf)
    maxvalue = max(threshold, c0 + cf*freq);
    L = weibull(contrast, maxvalue, 3, 0.5, 0.01);
end

The above code demonstrates the Contrast sensitivity function {2, 3, 2} example in Watson (2017). F1 and F2 are essentially the same thing, just with a different order of parameters. I don't think that changing the order of the parameters should change the estimated values, but the values estimated from the median are slightly different.

I checked your code regarding the median and noticed that your method depends on the order of the parameters. I do not have an alternative. Rather, I don't think we can define the median in the above case.

petejonze commented 3 years ago

Thank you for this detailed comment. I must admit I've never actually used the 'median' flag, so it's never been properly tested. Let me look into it, and if necessary will just remove the offending code.