function [error, freq_predV, freq_predA, simVA, sV_hat]=PeerJModelSample(paras,Ntrials,data,selection) %%%%%%%%%%%%%%%%%%%%%%%%%%%% %A sample modeling file for Odegaard, Wozny, & Shams (2017). %Can be combined with fminsearch or fminsearchbnd to optimize parameters %for a given subject. This represents one way of implementing the causal %inference model. Other versions use analytic solutions, which run MUCH %faster and usually contain fewer parameters. This code is based on previous %model versions used by the lab, but includes more comments and does things %in a way that makes the comptuations more explicit for people hoping %to learn from this (equations are from the manuscript). This also makes it %slower to optimize the parameters. MUCH slower. %Should be run on something that has a lot of computing power. %Note that the lab will be releasing a modeling toolbox in 2017 that includes %full documentation + files with the analytic solution that can be fit to new %experimental data, as well as a GUI interface to visualize parameters. %Inputs: %paras: Put in values for the eight parameters. These can be randomly %initialized in a fitting procedure. %Ntrials: 10000 should work fine. %data: An individual subject's data file. %Selection: choose the strategy: % -1 = Probability matching % 0 = Model Averaging % 1 = Model selection %initialize random number generator for optimization %otherwise optimization becomes very difficult as simulated data changes s1 = rand('state'); s2 = randn('state'); rand('state',13); randn('state',13); warning off MATLAB:divideByZero warning off MATLAB:logofZero %%%%%%%%%%%%%%%%%% %N=max(max(conditions))+1; N=6; range=-50:50; p_cutoff = 0.5; freq_dataV=zeros(N,N,length(range)); freq_dataA=zeros(N,N,length(range)); freq_predV=zeros(N,N,length(range)); freq_predA=zeros(N,N,length(range)); %Free Parameters p_common = paras(1); %a.k.a. the "binding tendency" sigV = paras(2); %Visual likelihood sigA = paras(3); %Auditory likelihood deltaV = paras(4); %Visual likelihood mean delta deltaA = paras(5); %Auditory likelihood mean delta deltasigV = paras(6); %Visual likelihood variance delta xPu = paras(7); %Spatial prior mean sigPu = paras(8); %Spatial prior variance %Variances of the Visual and Auditory Likelihoods varV = sigV^2; varA = sigA^2; varPu = sigPu^2; %Load the degrees, speakers used, the different stim locations, and another %speaker vector to be used for the shifts in likelihood means degs=(unique(data(find(~isnan(data(:,4))),4))); speakers=(unique(data(find(~isnan(data(:,1))),1))); sourcevec=[NaN; degs]; speakervec=[NaN; speakers]; %Create the matrix that will hold simulated data simVA=[]; %Create the error functions that will sum the error splineV=0; splineA=0; %Modeling the bimodal trials for sVind = 1:N for sAind = 1:N %This section grabs trials from all 25 AV conditions if sVind > 1 & sAind > 1 condIdx=find(data(:,1)==sVind-4 & data(:,9)==sAind-4); respV = data(condIdx,7); respA = data(condIdx,15); %Create histograms of V and A responses, %and normalize them by dividing by the sum h=hist(respV, range); freq_dataV(sVind, sAind, :) = h/sum(h); h=hist(respA, range); freq_dataA(sVind, sAind, :) = h/sum(h); %Grab the locations of the stimuli in both degrees and integer sV = sourcevec(sVind); sA = sourcevec(sAind); speakerV = speakervec(sVind); speakerA = speakervec(sAind); % Generation of simulated data xVall = sV + (speakerV*deltaV) + (abs(speakerV*deltasigV) + sigV) * randn(1, Ntrials); xAall = sA + (speakerA*deltaA) + sigA * randn(1, Ntrials); x=range; for i=1:Ntrials % This part of the file grabs likelihood means one at a time, % builds distributions around the mean, and then completes the % other steps necessary for causal inference xV=xVall(1,i); xA=xAall(1,i); %Create ways to keep all of the distributions separate: expvisnum = ((x-xV).^2); expaudnum = ((x-xA).^2); expcprinum = ((x-xPu).^2); %The equations for the two distributions, to be either combined %for the C=1 scenario, or kept separate for the C=2 %scenario: vlike=(exp(-expvisnum/(2*(varV)))/(sqrt(2*pi*varV))); alike=(exp(-expaudnum/(2*(varA)))/(sqrt(2*pi*varA))); cprior=(exp(-expcprinum/(2*(varPu)))/(sqrt(2*pi*varPu))); %Multiply distributions together, normalize, and take the max to find %the optimal solutions for the C=1 and C=2 scenarios CommonSolution=vlike.*alike.*cprior/sum(vlike.*alike.*cprior); VisualSolution=vlike.*cprior/sum(vlike.*cprior); AuditorySolution=alike.*cprior/sum(alike.*cprior); [CommonMAP I] = max(CommonSolution); [VisualMAP J] = max(VisualSolution); [AuditoryMAP K] = max(AuditorySolution); s_hat_common(1,i)=x(I); sV_hat_indep(1,i)=x(J); sA_hat_indep(1,i)=x(K); %Thus, we now have the optimal estimates for each causal %structure, but the causal structure isn't known, and must %be inferred. likelihood_common(1,i) = sum(vlike.*alike.*cprior); likelihoodV_indep(1,i) = sum(vlike.*cprior); likelihoodA_indep(1,i) = sum(alike.*cprior); likelihood_indep(1,i)=likelihoodV_indep(1,i).*likelihoodA_indep(1,i); end %Now that we have integrated over the likelihoods to get a single %value, you can multiply that by p_common to compute the posterior %probability of a common cause or independent causes. Down below, %this posterior probability of a common cause will be combined %with the optimal estimates in various ways to implement %the 3 strategies post_common = likelihood_common * p_common; post_indep = likelihood_indep * (1-p_common); pC = post_common./(post_common + post_indep); %Implementing probability matching . . . match=1-rand(1,Ntrials); %The three potential perceptual strategies if selection>0 %model selection sV_hat=(pC>p_cutoff).*s_hat_common + (pC<=p_cutoff).*sV_hat_indep; sA_hat=(pC>p_cutoff).*s_hat_common + (pC<=p_cutoff).*sA_hat_indep; elseif selection<0 %matching sV_hat=(pC>match).*s_hat_common + (pC<=match).*sV_hat_indep; sA_hat=(pC>match).*s_hat_common + (pC<=match).*sA_hat_indep; else %model averaging sV_hat = pC .* s_hat_common + (1-pC) .* sV_hat_indep; sA_hat = pC .* s_hat_common + (1-pC) .* sA_hat_indep; end %Load the 25 bimodal conditions, and then load the %simulated data in a matrix sim(1:Ntrials,1)=sVind-4; sim(1:Ntrials,2)=sAind-4; sim(1:Ntrials,3)=sV_hat; sim(1:Ntrials,4)=sA_hat; simVA=[simVA; sim]; %Normalize the simulated responsesin the same way we did %for the actual responses in the earlier part of the file h=hist(sV_hat, range); freq_predV(sVind, sAind, :) = h/sum(h); h=hist(sA_hat, range); freq_predA(sVind, sAind, :) = h/sum(h); %Compute the error (may want to look at alternative ways %of computing this . . . it ain't the only way) splineV = splineV + sum( log(max(spline(range,freq_predV(sVind, sAind, :),respV),0.00001)) ); splineA = splineA + sum( log(max(spline(range,freq_predA(sVind, sAind, :),respA),0.00001)) ); %Now do the modeling work for the unimodal visual trials elseif sVind > 1 & sAind == 1 condIdx=find(data(:,1)==sVind-4 & isnan(data(:,9))); respV = data(condIdx,7); %Create and normalize the response historgrams for the V-only %conditions h=hist(respV, range); freq_dataV(sVind, sAind, :) = h/sum(h); %Grab the location of the stimuli in both degrees and integer sV = sourcevec(sVind); speakerV = speakervec(sVind); % Generation of simulated data xVall = sV + (speakerV*deltaV) + (abs(speakerV*deltasigV) + sigV) * randn(1, Ntrials); x=range; for i=1:Ntrials % This part of the file grabs likelihood means one at a time, % builds distributions around the mean, and then completes the % other steps necessary for causal inference xV=xVall(1,i); %Create ways to keep all of the distributions separate: expvisnum = ((x-xV).^2); expcprinum = ((x-xPu).^2); %The equations for the visual estimate: vlike=(exp(-expvisnum/(2*(varV)))/(sqrt(2*pi*varV))); cprior=(exp(-expcprinum/(2*(varPu)))/(sqrt(2*pi*varPu))); %Multiply the visual likelihood and spatial prior, and %normalize. VisualSolution=vlike.*cprior/sum(vlike.*cprior); %Take the max of the posterior [VisualMAP J] = max(VisualSolution); sV_hat(1,i)=x(J); end %Load the vis-only conditions, and simulated vis-only %responses into the simulated data matrix sim(1:Ntrials,1)=sVind-4; sim(1:Ntrials,2)=NaN; sim(1:Ntrials,3)=sV_hat; sim(1:Ntrials,4)=NaN; simVA=[simVA; sim]; %Create a histogram of the simulated data and normalize h=hist(sV_hat, range); freq_predV(sVind, sAind, :) = h/sum(h); %Compute the error for the vis-only conditions splineV = splineV + sum( log(max(spline(range,freq_predV(sVind, sAind, :),respV),0.00001)) ); %Now do the modeling work for the unimodal auditory trials elseif sVind == 1 & sAind > 1 condIdx=find(isnan(data(:,1)) & data(:,9)==sAind-4); respA = data(condIdx,15); %Create and normalize the response historgrams for the A-only %conditions h=hist(respA, range); freq_dataA(sVind, sAind, :) = h/sum(h); %Grab the location of the stimuli in both degrees and integer sA = sourcevec(sAind); speakerA = speakervec(sAind); % Generation of simulated data . . . xAall = sA + (speakerA*deltaA) + sigA * randn(1, Ntrials); x=range; for i=1:Ntrials % This part of the file grabs likelihood means one at a time, % builds distributions around the mean, and then completes the % other steps necessary for causal inference xA=xAall(1,i); %Create ways to keep all of the distributions separate: expaudnum = ((x-xA).^2); expcprinum = ((x-xPu).^2); %The equations for the auditory estimate: alike=(exp(-expaudnum/(2*(varA)))/(sqrt(2*pi*varA))); cprior=(exp(-expcprinum/(2*(varPu)))/(sqrt(2*pi*varPu))); %Multiply the auditory likelihood and spatial prior %together, and normalize AuditorySolution=alike.*cprior/sum(alike.*cprior); %Take the max of the posterior [AuditoryMAP K] = max(AuditorySolution); sA_hat(1,i)=x(K); end %Load the aud-only conditions, and simulated aud-only %responses into the simulated data matrix sim(1:Ntrials,1)=NaN; sim(1:Ntrials,2)=sAind-4; sim(1:Ntrials,3)=NaN; sim(1:Ntrials,4)=sA_hat; simVA=[simVA; sim]; %Create a histogram of the simulated data and normalize h=hist(sA_hat, range); freq_predA(sVind, sAind, :) = h/sum(h); %Compute the error for the aud-only conditions splineA = splineA + sum( log(max(spline(range,freq_predA(sVind, sAind, :),respA),0.00001)) ); end end end error = -(splineV+splineA); %go back to old initialization rand('state',s1); randn('state',s2);