Wong-Wang Decision Model#

The (reduced) Wong-Wang model is a two-variable attractor network for two-alternative perceptual decision making. The state variables \(S_1, S_2\) are the NMDA gating fractions of two competing, mutually inhibiting selective populations. Stimulus coherence biases the inputs toward one population; recurrent excitation and cross-inhibition then drive a winner-take-all transition to one of two stable attractors (the ‘decision’).

Reference: Wong & Wang (2006), A recurrent network mechanism of time integration in perceptual decisions, Journal of Neuroscience 26(4):1314-1328.

Build the model#

node = brainmass.WongWangStep(in_size=1)
node
WongWangStep(
  in_size=(1,),
  out_size=(1,),
  tau_S=Const(
    fit=False,
    t=IdentityT(),
    reg=None,
    val=Quantity(0.1, "s")
  ),
  gamma=Const(
    fit=False,
    t=IdentityT(),
    reg=None,
    val=Array(0.641, dtype=float32)
  ),
  a=Const(
    fit=False,
    t=IdentityT(),
    reg=None,
    val=Quantity(270., "Hz / nA")
  ),
  theta=Const(
    fit=False,
    t=IdentityT(),
    reg=None,
    val=Quantity(0.31, "nA")
  ),
  J_N11=Const(
    fit=False,
    t=IdentityT(),
    reg=None,
    val=Quantity(0.2609, "nA")
  ),
  J_N22=Const(
    fit=False,
    t=IdentityT(),
    reg=None,
    val=Quantity(0.2609, "nA")
  ),
  J_N12=Const(
    fit=False,
    t=IdentityT(),
    reg=None,
    val=Quantity(0.0497, "nA")
  ),
  J_N21=Const(
    fit=False,
    t=IdentityT(),
    reg=None,
    val=Quantity(0.0497, "nA")
  ),
  J_A_ext=Const(
    fit=False,
    t=IdentityT(),
    reg=None,
    val=Quantity(0.0002243, "nC")
  ),
  mu_0=Const(
    fit=False,
    t=IdentityT(),
    reg=None,
    val=Quantity(30., "Hz")
  ),
  I_0=Const(
    fit=False,
    t=IdentityT(),
    reg=None,
    val=Quantity(0.3255, "nA")
  )
)

Run a simulation#

A positive coherence biases the evidence toward population 1. We watch the two gating variables compete.

sim = brainmass.Simulator(node, dt=0.5 * u.ms)
res = sim.run(2000. * u.ms, inputs=lambda i, t: 25.6,
              monitors=['S1', 'S2'])
res['S1'].shape
(4000, 1)

Visualize#

The winning population’s gating variable rises to a high stable value while the loser is suppressed — a categorical decision.

fig, ax = plt.subplots(figsize=(8, 4))
brainmass.viz.plot_timeseries(
    jnp.concatenate([res['S1'], res['S2']], axis=1), ts=res['ts'],
    labels=['S1 (pop 1)', 'S2 (pop 2)'], ax=ax)
ax.set_title('Wong-Wang decision dynamics (coherence = +25.6%)')
plt.show()
../../_images/dff1c2309c9d17ae9b65f534d5daf2d101d6a75f9b559d816db26162975931e3.png

Try it: vary the stimulus coherence#

Stronger coherence speeds and sharpens the decision; near-zero coherence makes the outcome slow and noise-sensitive.

fig, ax = plt.subplots(figsize=(8, 4))
for coh in [0.0, 12.8, 51.2]:
    m = brainmass.WongWangStep(in_size=1)
    r = brainmass.Simulator(m, dt=0.5 * u.ms).run(
        2000. * u.ms, inputs=lambda i, t, c=coh: c, monitors=['S1'])
    ax.plot(u.get_magnitude(r['ts']), u.get_magnitude(r['S1'])[:, 0],
            label=f'coherence = {coh}%')
ax.set_xlabel('time (ms)'); ax.set_ylabel('S1'); ax.legend()
ax.set_title('Coherence sweep')
plt.show()
../../_images/b15b2e61d824b12fd7cc80f58a5312277897c3e09e4d0e2ce1c592c62b26d2cb.png