NSCS Week 2

Assignment 2: Modeling a full experiment

*** Due date: Start of class in Week 3 ***

Part 1: Create a function for one decision (2 points)

Note you can output the accuracy by just typing a single line:
accuracy
without the semi colon at the end.

Part 2: Create a function to make many decisions (3 points)

for i = 1:nDecisions
accuracy(i) = makeOneDecision(D, T, f);
end

Part 3: Create a script to simulate behavior for many different values of T and f (3 points)

Note: Depending on how fast your computer is, your code may take a while to run. If it's taking a very long time (more than 5 minutes) you can speed things up by reducing nDecisions to 50 or less.
Note: If you want to stop the code running before it's done, click on the Command Window and press control+C (on mac and on windows).

Part 4: Compare the behavior of your model with the behavior of the monkeys from Gold and Shadlen (2 points)

goldShadlen.mat
load goldShadlen
hold on
l2 = plot(dataX, dataY, '.');
set(l2(1), 'color', AZ_chili)
set(l2, 'markersize', 30)

Part 5: Speed up your code and improve the model (2 extra credit bonus points)

Note: This extra credit item is more for expert coders, feel free to try it if you are a novice, but you might need to reach out the instructors for help.
You may have noticed that the code we wrote this week runs pretty slow. The reason for this is that Matlab does pretty badly with for loops. However, there are ways to speed things up (by up to a factor of 500 times!) by replacing the for loops with vectors and matrices.
Let's start with our makeOneDecision function. First of all let's find out what lines are slowing us down by timing our code. To do this, go to the EDITOR tab on the toolbar and hit "Run and Time."
After it's run (which takes slightly longer than to run your code without timing) you'll get something like this pop up ...
Screen Shot 2020-08-06 at 8.38.53 AM.png
This is the code profiler that let's you see which lines of code are taking the longest ... if you click on the link for "makeOneDecision" and scroll down, you'll see something like this ...
Screen Shot 2020-08-06 at 8.39.04 AM.png
This is a line-by-line breakdown of the makeOneDecision function with the time taken to run each line. From this you can clearly see that it's the binornd line that's taking so long - 4.158 seconds on my machine, or about 99% of the entire running time!
The reason this line takes so long is because we are calling it so many times (220,000 times). It's likely that we can speed things up considerably if we can avoid calling binornd quite so many times ...
To do this we need to use a vector version of binornd, to generate all the random numbers we need in one go, which turns out to be way quicker than generating one random number at a time. We can do this like this ...
dot_direction = binornd(1, f, T*D, 1);
This will generate a vector of dot directions, one for each dot. We can then compute N_correct as
N_correct = sum(dot_direction);
and N_wrong as
N_wrong = sum( 1 - dot_direction );
Note: the sum function just sums up all the elements of a vector.
Have a play around with this and see how much it speeds up your code.
Then, if you are feeling brave, have a go at speeding up makeManyDecisions by bypassing makeOneDecision entirely and generating a matrix of dot directions, one for each dot on each trial using
dot_direction = binornd(1, f, T*D, nDecisions);
You'll then need to use the sum function to sum over the first dimension of dot_direction to get a vector of N_corrects and N_wrong.
N_correct = sum(dot_direction);
If you manage to speed up makeManyDecisions, try running your code with a much bigger number for nDecisions, (1000 or even 10,000 is good) and more T_vals so you can really map out each line. This will really let you see where the model fails to capture the data.
Finally, see if you can get the model fit to be even better by including one more variable - a dead time in which the monkey ignores the input stimulus. This means that for a given viewing time, the actual time the monkey sees the stimulus is reduced by a constant amount. See if you can include this dead time into your simulations. If you can, you'll find you can fit the data almost perfectly!