Changelog
Source:NEWS.md
XSLmodels (development version)
New Features
- Added
uncfam_general(), a single biased associative model that nests theuncfam()family, so variants can be compared as nested models (fix or free parameters) rather than as separate functions. A pair’s share of the trial’s weight isM^gamma * exp(B * (U(w) + U(o)))(normalized over the trial), plusepstimes elimination support, and the trial’s weight is scaled by(relative object entropy)^kappa; finiteKreplaces deterministic allocation with sampled attention. Its defaults reproduceuncfam(). Settinggamma = 0,uncertainty = "novelty", a freegamma, a freeeps,kappa = 1or a finiteKreproduces, respectively,uncfam(variant = "uncertainty-only"),uncfam(variant = "novelty"),uncfam_gamma(),uncfam_elimination(),uncfam_attention()anduncfam_sampling(). Each reproduces the original exactly (to the last bit, and draw for draw for sampling) on all 47xsl_datasetsconditions; this is checked intests/testthat/test-uncfam_general.R.uncfam_predictive()is not nested, since its prediction-error update is unnormalized. Registered inshow_models()/xsl_model_registry(), fittingX, B, C, gamma, eps, kappawithK = Inf. It also has an optional short-term trace: withrho > 0, every update also goes into a second matrix that decays byCsper trial, and familiarity becomes(M + rho * S)^gamma, so recently strengthened pairings draw extra attention. Uncertainty, elimination and test performance still useM, andrho = 0(the default) is unchanged - Every
xsl_datasetscondition now carries aresponse_matrix: for each test item, the number of participants choosing each object. This is the full confusion matrix behindaccuracy, which it reproduces exactly, so models can be fit to which objects learners chose (e.g. by multinomial likelihood) rather than only to proportion correct. It is extracted from the raw response files (data-raw/raw_responses.R,data-raw/fix_freqcd_add_responses.R).data-raw/extract_response_matrices.Rreports how each condition was matched to its raw data
Bug Fixes
-
tilles()now follows Tilles & Fontanari (2013) in three places where it departed from the paper. It matches an independent, literal transcription of the paper’s eqs 1-13 and procedure (tests/testthat/helper-tilles-literal.R) to 1e-12 on all 47xsl_datasetsconditions, including at the parameter bounds. This changes alltilles()results and fits.- Eq 7’s
alphais recomputed before every trial for every word seen so far, as the paper’s procedure (p. 4) specifies. Words absent from a trial use it in eqs 12-13. They used to keep thealphafrom the last trial they appeared on, and a word seen only on trial 1 keptalpha_0. - Eqs 1 and 2 count objects. The paper’s contexts have C words and C objects. In the conditions with more objects than words (19 of 47,
201-222), eq 1 divided by the number of words and eq 2 by the number of new words, so a word’s associations summed to as much as 3.95 rather than 1 (eq 10). When a new word appears with no new objects (73 trials in 15 conditions, where its referent was shown earlier as a foil), eq 2’sbshare now goes to all of the trial’s objects; it used to be dropped. - When a word has no association with any of the objects that eq 5 (or eq 11) is proportional to, the flux is distributed evenly over them, as the paper first describes eq 5. It used to be dropped, so the word’s associations summed to less than 1 (in condition
206at any parameters, and in most of the 3x4-type conditions atb = 1). - Every word’s associations now sum to 1 at all parameters in [0, 1], bounds included, so
b = 1andx = alpha_0 = 1no longer stop with “no associations left”. - At the v05 group-fit parameters (x = .129, b = .124,
alpha_0= .9855), SSE over the 47 conditions is .6466 (.6399 with only the eq 7 normalization fix below, .6125 before either), and model accuracy changes by up to .135 for a word. Refitting with v05’s settings gives SSE .6061 at x = .124, b = .129,alpha_0= .979, the same as with only the eq 7 fix (.6060).
- Eq 7’s
tilles()’s eq 7 now normalizes the entropy of a word’s associations to [0, 1], as Tilles & Fontanari (2013) specify, by dividingshannon_entropy()(in bits) bylog2(n_o)rather than bylog(n_o)in nats. The mismatch came from the original 2013 implementation, so the publishedtilles()results ran on it too. This changes alltilles()results and fits, except atalpha_0 = 1, where eq 7’s alpha is 1 whatever the entropy. Because alpha now stays in [alpha_0, 1],tilles()gives valid probabilities at every interior parameter vector. On all 47xsl_datasetsconditions at 1682 parameter vectors, all 72944 runs with x, b andalpha_0in (0, 1) were valid, including the 23808 that had stopped with “associations became negative” (see below), and no association went negative even transiently. The only remaining stops were the boundary casesb = 1andx = alpha_0 = 1, which no longer occur (see above). At the v05 group-fit parameters (x = .129, b = .124,alpha_0= .985), SSE over the 47 conditions rises from .6125 to .6399. Refitting gives .6060 at almost the same parameters (x = .129, b = .126,alpha_0= .979). When only one object has been seen, eq 7’s normalized entropy is now 0 instead of 0/0.tilles()no longer returns NaN, or fails with “missing value where TRUE/FALSE needed” insideshannon_entropy(), at smallalpha_0. Instead it stops with a clear error,tilles(): associations became negative by trial .... The cause is eq 7, carried over from the original 2013 implementation: it normalizes entropy in bits (log2) bylog(n_o)in nats. Its uncertainty term can then reach1/log(2)(about 1.44) rather than 1, soalphafalls below 0 whenalpha_0is below about .31. Eqs 8-13 can then push associations negative, and the next eq 7 entropy of a negative row is NA.tilles()now stops when a word’s associations are negative at its next eq 7 (where NaN used to start), or when final associations are negative (previously returned silently as negative probabilities). Separately, at the boundary valuesb = 1(a novel word appearing with no novel objects gets no association) andx = alpha_0 = 1, a word could be left with no associations, giving the same NA (no longer, see above); this stopped withtilles(): word ... has no associations left by trial .... Every run that returned finite, nonnegative associations is unchanged, bit for bit. This was checked on all 47xsl_datasetsconditions at 553 parameter vectors, including every one in the v05 refit’s error log. Fitting already scored errors and NA results as an infinitely bad fit, so fits change only wheretilles()previously returned negative probabilities, which are now also scored as infinitely bad. The normalization itself is corrected in the entry above, so smallalpha_0no longer causes this; the checks remain for parameters outside [0, 1] and for the boundary cases.bayesian_decay()’s choice exponentch_decwas ignored on conditions with atest(the 4AFC conditions 211-214 and the 12 filtering conditions):xsl_run()applied it as a power choice rule only on theget_perf()path, whilemafc_test()scored test trials with plain Luce choice.predict_referent()andmafc_test()gain adargument (the choice exponent;NULL, the default, leaves associations unchanged), andxsl_run()passes a model’sch_decto both paths. This changesbayesian_decay()fits involving any of these 16 conditions. Models withoutch_decare unchanged, bit for bit.-
Two 4AFC conditions in
xsl_datasetslisted test alternatives that participants were not shown. This changes fits of every model involving conditions 211 and 214. Seedata-raw/fix_4afc_tests.R-
214(3x4 6/8 4AFC): 175 of its 648 human responses, on all 18 words, were to objects not among the listed alternatives. All of them are among condition213’s alternatives for the same word (and no other condition’s), so 214’s participants were evidently tested with 213’s displays. 214’stestis now 213’s. Itsaccuracyandresponse_matrixare unchanged. -
211(1x3 6/18 4AFC), word 17: the alternatives listed object 17 twice and omitted foil 2, which participants chose; nowc(17, 16, 5, 2). - Every human response in
xsl_datasetsis now to one of its item’s listed alternatives (checked intests/testthat/test-data.R).
-
-
The frequency / contextual-diversity conditions in
xsl_datasetsare rebuilt from the original analysis data (data-raw/data/freqCD_item_data.Rdata), giving exact accuracies and correct sample sizes. This changes fits involving these conditions.- The stored accuracies were right, but
n_subjhad been attached to the wrong conditions. It is now 104 (was 26) forfreq369-3x3hiCD, 66 (62) forfreq369_36mx, 40 (66) forfreq369_39mxand 62 (40) forcont_div6-12. -
3_x8_369_4x4andfreq369-3x3loCDhad been pooled with the first test block of the “priming” experiments. Those participants trained on the same sequences but were tested four times, and the pooled values could not be reproduced. Both conditions now hold only their original experiments:n_subj30 (was 74) and 34 (was 102), with item accuracies changing by up to .27 and .51. - Two duplicate conditions are dropped, leaving 54 conditions (was 56; 47 after the move below):
-
orig_3x3was condition224(same training, identical accuracies from the same 36 participants) withn_subj104. -
orig_4x4’s 26 original participants are a subset of condition223’s 77, and its training sequence differs from223’s only in words 4 and 16 trading places between trials 11 and 24.
-
- See
data-raw/fix_freqcd_add_responses.R.
- The stored accuracies were right, but
The Suanda, Mugwanya & Namy (2014) and Koehne, Trueswell & Gleitman (2013) conditions moved from
xsl_datasetsto new standalone held-out datasets,suanda2014andkoehne2013, registered inxsl_holdout_datasets, as in the original CogSci bake-off. Only their condition-level mean accuracies are available, so they can’t inform item-level group or cross-validated fits; they’re for testing generalization of mean accuracy.xsl_datasetsnow has 47 conditions, all with item-level accuracy and aresponse_matrix. Seedata-raw/move_condition_means_to_holdout.RxslData‘s validator now expects oneaccuracyvalue (and oneresponse_matrixrow) per test item, i.e. per test trial whentestis given, rather than per word. The filtering conditions’ 24-item tests failed the old check.The 12 filtering conditions in
xsl_datasets(filt*E_*L; Kachergis, Yu, & Shiffrin, 2012) were scored wrongly, and held only half their tests. Each word co-occurs in training with both its own object and its partner’s object (e.g. w1 with o1 and o7). It was tested twice, once with the partner object absent (AtoA, measuring w1-o1) and once with its own object absent (AtoB, measuring w1-o7).xsl_datasetsheld only the AtoA accuracies, scored as a choice among all 12 objects, so a model’s association with the absent partner object counted against it, andfilt0E_*(symmetric pairs) was capped at .5. Each condition now has 24 test items scored bymafc_test(): the 12 AtoA items, then the 12 AtoB items. In the raw data, no participant ever chose the absent object on either test. Two participants in each*_6Lcondition had test codes shifted by 6, and are now excluded (n_subj27 -> 23; the stored 27 was a per-word count inflated by the miscoding), which changes those conditions’ AtoA accuracies slightly. This changes all fits involving these conditions. Seedata-raw/fix_filtering_tests.Rand?xsl_datasetsmafc_test()(andxslDatatest specifications) accept an optionalcorrectelement giving each test trial’s correct object; it defaults to the tested word’s own object, as before
XSLmodels 0.4.0
New Features
- Added
uncfam_elimination(), a variant ofuncfam()with learning by elimination (mutual exclusivity). Each on-trial pair’s mutual confidenceP(o|w) * P(w|o)is computed from the current associations, and a pair gets elimination support to the extent that the trial’s other words and objects are already accounted for by each other. That support, weighted by a free parametereps, is added touncfam()’s familiarity-and-uncertainty share of the trial’s associative weight before renormalizing;eps = 0reproducesuncfam()exactly. Inuncfam(), an already-known pair on a trial draws weight away from the trial’s other pairs; with elimination, knowing one word directs learning to the remaining word-object pairing. Motivated by the initial-accuracy experiment, where learners were more accurate on an initially mis-paired word the more of its study trials it shared with an initially accurate word. Registered inshow_models()/xsl_model_registry() - Added
uncfam_gamma(), a variant ofuncfam()that decouples familiarity’s contribution to a trial’s attentional allocation from uncertainty’s.uncfam()’s allocation weight isexp(B * entropy) * assocs– entropy gets a free exponent (B), but familiarity (assocs) enters linearly with an implicit weight of 1 and no free parameter of its own.uncfam_gamma()adds one parameter,gamma, raising familiarity to a free power instead (assocs^gamma);gamma = 1reproducesuncfam()exactly. Cross-validated against all ofxsl_datasets, it beats plainuncfam()in every fold of a 5-fold split (mean test SSE 0.48 vs. 0.56), with a best-fitgammaaround 0.3 (familiarity’s pull dampens with diminishing returns). A separate analysis fitting this same free-gammasubstrate to active cross-situational word learning (learners choosing which items to see named next, rather than a fixed passive sequence) instead found a best-fitgammaaround 2 (amplified, not dampened) – see?uncfam_gammafor the full comparison - Added
minerva2(),todam(), andrem(), three distributed/episodic memory models ported from standalone prototypes that predated this package (Hintzman’s MINERVA2, 1984/1986; Murdock’s TODAM, 1982; Shiffrin & Steyvers’ REM, 1997) and were never wired into it or tested. All three represent words/objects as random feature vectors rather than tallying a single word-by-object association, and turn their native similarity/odds score into a Luce-choice-ready matrix via an exponentiated (X-temperature) or likelihood-ratio-based choice rule so they plug intoget_perf()/mafc_test()like every other model here. Porting surfaced real bugs in the prototypes, fixed along the way (see each model’s@details/source comments):minerva2()‘s prototype compared a 2D echo-content vector against D-dim object vectors (silent recycling, not an error) instead of just the echo’s object half;todam()’s prototype computed trial-1 attention weights ascos_sim(item, 0)= NaN, poisoning memory from the first trial on, and bothtodam()prototypes called the long-removedas.real();rem()’s prototype never actually implemented REM at all (it declared a geometric feature-vector generator but its model/test functions were an unmodified copy of the MINERVA2 prototype’s continuous-Gaussian code) –rem()here is a fresh adaptation of Shiffrin & Steyvers’ storage/odds equations to this package’s associative task. Benchmarking (see?minerva2/?todam/?remperformance notes) foundrem()’s raw per-simulation likelihood-ratio odds span several orders of magnitude (a lucky match on one rare feature value can dominate), which would otherwise let a single lucky simulation hijackxsl_run()’s sum-across-simulations aggregation;rem()now row-normalizes each simulation’s choice weights before returning them. All three are registered inshow_models()/xsl_model_registry(), fitting only their choice-rule temperature (X) or storage parameters (g,u,c) by default –D/w(feature-vector dimensionality) are fixed representational hyperparameters, not free cognitive parameters. Speed varies widely: on the fullxsl_datasets(53 conditions) atn_sim = 500,minerva2()takes ~30s,todam()~8 min, andrem()~20 min –todam()/rem()are impractical toxsl_fit()at full DEoptim settings (NP = 100, itermax = 100would be tens of thousands of evaluations) without sharply reducingn_sim/NP/itermax, as the package’s own fitting examples already do for slow models - Added 3 more temporal-contiguity conditions to
xsl_datasetsfrom Kachergis, Yu, & Shiffrin (2009) – the same paper behind the existing1_max_temp_spat_cont_orig/4_no_spat_orig_max_tcconditions.data-raw/XSL-dataset-fields.csvdocumented 6 “overlap” conditions (3 matched pairs of a control and non-control order at the same overlap degree) that were never pulled in; only the 3 control-order ones (1olap3tr_contr,temp_cont_1olap2tr_contr,temp_cont_2olap2tr_contr) have real subject-level accuracy data findable anywhere in the repo (indata-raw/agg_data/x13_1-21.txt, perexport_data.R’s own comments mapping its generic condition labels to these named orders). The other 3 have order files but no discoverable human data, and are deliberately left out rather than guessed. Seedata-raw/add_temporal_contiguity_overlap.R - Added a fifth standalone dataset,
benitez2020(a named list of 7xslDataobjects, one per condition x age-group combination) from Benitez et al. (2020), “The temporal structure of naming events differentially affects children’s and adults’ cross-situational word learning” (data: osf.io/2hmxr).data-raw/Benitez2020-rep/Benitez2020_XSLdata_extraction.Ralready extracted training orders, 2AFC test trials, and response-count matrices from the raw OSF data but stopped short of buildingxslDataobjects (a literal# ToDoin the file);data-raw/add_benitez2020.Rpicks up from there. 8 symmetric word-object pairs, 12 training trials, 8-item 2AFC test; unlike the other standalone datasets, real per-word accuracy is recoverable directly from the provided response matrices (not just an overall mean) – structurally it could joinxsl_datasetsdirectly, but is kept standalone by choice, as held-out generalization-test data (seexsl_holdout_datasets) - Added
xsl_holdout_datasets, a registry of every dataset in the package that is not part ofxsl_datasetsand therefore never seen byget_group_model_fit()/get_crossvalidated_model_fit()– i.e. everything available for testing a fitted model’s generalization to genuinely held-out data, along with how to score each one (most need a different scoring approach thanxsl_datasets’s standard diagonal convention, which is exactly why they’re standalone;benitez2020andkachergis_initial_accuracyare the two directly-scorable exceptions, kept out of the fitting pool specifically to serve as held-out data) - Added a fourth standalone dataset,
vlach_debrock2017(Vlach & DeBrock, 2017, Journal of Memory and Language, “Remember dax? Relations between children’s cross-situational word learning, memory, and language abilities”). 12 symmetric word-object pairs, 2 pairs per training trial, 36 trials, with pairs varying in whether their 6 repetitions are massed or spaced (n = 47 children, ages 2-5). The source only reports an overall mean/SD across all pairs and participants, not a per-word breakdown, soaccuracyisNAthroughout rather than fabricated – kept standalone (not part ofxsl_datasets) for the same reason askachergis2012_highlighting/gangwani2011_category. See?vlach_debrock2017anddata-raw/add_vlach_debrock2017.R - Added a third standalone dataset,
gangwani2011_category(Experiment 1 of Gangwani, Kachergis & Yu, “Simultaneous Cross-situational Learning of Category and Object Names”; an undergraduate-journal version is Gangwani & Kachergis, Indiana Undergraduate Journal of Cognitive Science 5, 2010). A hierarchical design: each training trial shows 2 objects and names 3 words – the two objects’ own 1-to-1 names plus one 1-to-many “category” label naming those two objects and two others seen on other trials – so every object carries both a basic name and a category label, and the paper’s finding is that learners violate mutual exclusivity by learning both. A named list of threexslDataobjects (one per training block: ad hoc / natural / ad hoc), sharing one 36-trial co-occurrence schedule. Its 15 x 12 (word x object) association matrix breaksxslData’s diagonal-scoring convention the same waykachergis2012_highlightingdoes, so it is kept standalone; score it withscore_gangwani2011_category()in the newtests/bakeoff_comparison/gangwani2011_category_fit.R, which reads 12-AFC name accuracy, 3-AFC category accuracy, and the paper’s headline ME-violation measure straight off any model’s matrix. See?gangwani2011_categoryanddata-raw/add_gangwani2011_category.R
Other changes
-
control$start_matrixis no longer silently ignored. Only some models initialized from it; the rest dropped it without warning (so e.g. a familiarization phase passed as a start matrix simply vanished for them). Models now declaresupports_start_matrixinxslMod(), andxsl_run()errors if a start matrix is given to one that doesn’t, or if it doesn’t match the training data’s dimensions.baseline(),decay(),rescorla_wagner(),softmax_rl(),uncfam_sampling(), andmulti_sampling()now support it, joining theuncfam()family,propose_but_verify(), andpursuit(). The remaining models (fazly(),guess_and_test(),tilles(),bayesian_decay(),kalman_filter(),fgt2009()/fgt2009_rsa(),minerva2()/todam()/rem()) have no single association matrix a start matrix maps onto (or would need a model-specific convention, e.g. a variance as well as a mean), so prior learning should be passed to them as training trials, askachergis_initial_accuracydoes. A custom model built withxslMod()must setsupports_start_matrix = TRUEto receive one. Runs without a start matrix are unchanged
Documentation
- The main vignette now covers every model and dataset added since 0.3.0 (
uncfam_gamma(),uncfam_elimination(),minerva2()/todam()/rem();vlach_debrock2017,benitez2020,xsl_holdout_datasets), and adds two sections: passing prior learning to a model as training trials vs. astart_matrix, and testing a fitted model’s generalization on the held-out datasets. Its description of the dataset structure used field names (trials,objs,perf) that no longer exist – so itscreate_cooc_matrix()example was silently printing an empty matrix – and said words/objects must be referred to by index, which no longer holds
Bug Fixes
-
xsl_fit()with a parallel DEoptim backend (DEoptim.control(parallelType = "parallel")) silently returnedbestval = Infwhencontrolwas passed as a variable (e.g.ctrl <- xslControl(n_sim = 100); xsl_fit(..., control = ctrl)):controlwas never forced, so the objective shipped to the worker processes carried an unevaluated promise that each worker tried to evaluate in its own empty global environment, every evaluation errored, and the error was converted toInf.controlis now forced before fitting, andxsl_fit()warns when every evaluation of a fit failed instead of returning an all-Infresult silently. Serial fits were unaffected. -
create_cooc_matrix()looped over the number of distinct words rather than the number of trials: with more words than trials it errored, and with fewer (e.g. its own documented example,xsl_datasets[[1]]: 18 words, 36 trials) it silently tallied only the first trials. It also indexed by raw label (the same issue as #14). Both fixed;plot_training_trials()now indexes by label too. No model uses either function, so no fits change -
propose_but_verify()andpursuit()drew new hypotheses withsample(tr_o, ...). On a trial with a single object,tr_ois one value, and when that value is an integerk, R’ssample(k, n)draws from1:krather than returningk– so a word seen alone with an object usually hypothesized a different object, one not even on the trial (propose_but_verify()hypothesized the right object ~1/8 of the time in an 8-object toy). Both now index intotr_o(tr_o[sample.int(length(tr_o), n, replace = TRUE)], asguess_and_test()already did). Noxsl_datasetscondition has single-object trials, so fits to it are unchanged;kachergis_initial_accuracy(18 single-object familiarization trials per condition),kachergis2012_highlighting’s words-as-cues condition (28 trials naming two words with one object), and the naturalistic corpora (rollins_corpus,fm_corpus) are affected. Integer-labelled data (e.g.kachergis_initial_accuracy) was affected before this release too; the corpora were not – they reached these models as string labels, for whichsample()behaves as intended – until #14 began handing models integer positions, so for the corpora this is a regression in 0.4.0. - Models indexed their association matrices by raw word/object value (
m[tr_w, tr_o]) rather than by position in the sorted vocabulary, which is only correct for labels that are exactly1..N(#14): a vocabulary with a gap crashed (“subscript out of bounds”), and a raw value that still fell in range silently updated the wrong row. Fixed once, inxsl_run(): models now receive each dataset’s words/objects as positions, and the original labels are restored on the returned matrix,perf, and trajectory. Test trials are scored by label, and astart_matrixwith dimnames is aligned to the data by label. Checked against every registry model on every bundled dataset (23 models x 75 datasets, fixed seed): 1721 of 1725 runs are bit-identical, including all ofxsl_datasetsand the standalone datasets, whose labels are already1..N. The 4 that differ arepropose_but_verify()andpursuit()onrollins_corpus/fm_corpus, where the fix corrects a real error: both compared a column position against the trial’s object labels, which can never match for character labels, so on the corpora every hypothesis was treated as disconfirmed and none was ever verified. (Handing these models integer positions also exposed the single-objectsample()bug above on the same corpora; both fixes are needed for correct corpus results.) Thepropose_but_verifyandpursuitresults previously intests/bakeoff_comparison/corpus_report.mdwere therefore invalid (including pursuit’s reported collapse on FM); the report andvignette("corpora")have been rerun on the fixed code -
uncfam_predictive()now caps associations atbeta(1), its stated maximum, as well as flooring them at 0. Its unnormalized update could overshoot far abovebetaon a word’s first exposure: the prediction error is then ~beta, and it is scaled byexp(B * entropy)of the word’s row, whichupdate_known()spreads over every object seen so far – so a word first seen after many others could reach an association in the thousands in a single trial (e.g. ~4600 for the 18th of 18 sequentially introduced words at X = .8, B = 1.6, C = .7). That association then dominated the word’s row and collapsed its entropy, locking in the first pairing it was seen with; in the initial-accuracy study this made the model predict learners would choose an initially inaccurate word’s familiarization referent 3-4x as often as they did. This changesuncfam_predictive()’s fits wherever the overshoot occurred, including the corpus-fit gains reported for it intests/bakeoff_comparison/corpus_report.md(not rerun here) -
get_perf()now treats negative associations as 0 before applying the Luce choice rule (aspredict_referent()already did), and answers a word whose associations are then all 0 at chance (1 / ncol(m)) rather than returningNaN. Error-driven models (rescorla_wagner(),kalman_filter()) can learn negative associations, for whichdiag(m) / rowSums(m)gave per-item “probabilities” outside [0, 1] – which DEoptim could exploit when fitting. In the initial-accuracy study, fittedrescorla_wagner()had negative associations for about half of participants and out-of-range predictions for 25 of 61. This changes those models’ fits wherever negative associations occurred -
kachergis_initial_accuracyput the familiarization pairing on the diagonal (thexslData“correct referent” slot), but the experiment’s test-correct answer is always the study pairing. For every initially inaccurate item these differ, so any model’s accuracy on those items was actually its probability of choosing the wrong, familiarization object. Its per-itemaccuracywas also keyed byinit_word_ind(the word originally familiarized with the tested word’s correct object) rather than by the tested word. Both are fixed: objects are now indexed by the word they are studied with, so the study pairing is the diagonal and an initially inaccurate word’s familiarization object is off-diagonal, andaccuracyis keyed by the tested word. It now also excludes the 4 participants whose median test response time was under 400 ms (as the accompanying manuscript does), leaving 34 High IA and 27 Low IA participants.tests/bakeoff_comparison/kachergis_initial_accuracy_fit.Randkachergis_initial_accuracy_persubject_fit.Rare updated and rerun accordingly -
kachergis_initial_accuracy’s familiarization trials were in word-index order; they now follow the order participants actually saw them (the same for every participant, recovered from the raw familiarization records). Order matters for theuncfam()family, whose first-exposure update depends on how many objects have already been seen viaupdate_known()– foruncfam_predictive()it determined how far a word’s familiarization association overshotbetabefore the cap above. The bakeoff scripts are rerun accordingly
XSLmodels 0.3.0
New Features
- Added two new model variants of
uncfam():uncfam_attention()(BAM+Attention), which scales a trial’s learning rate by that trial’s object uncertainty relative to the running mean (implementing Fitneva & Christiansen 2015’s system-level attention account), anduncfam_predictive()(BAM+Prediction), which replaces the normalized update rule with an item-level, Rescorla-Wagner-style prediction-error term (floored at 0 to prevent the unnormalized update from diverging over trials) - Added two standalone datasets, documented but deliberately not appended to
xsl_datasets:kachergis2012_highlighting(Kachergis, 2012, CogSci) andkachergis_initial_accuracy(an unpublished MTurk initial-accuracy manipulation).kachergis2012_highlighting‘s training trials are genuine simultaneous 2-cue trials (2 words + 1 object, or 2 objects + 1 word, per trial, matching the paper’s Figure 2), read directly from the real per-trial ordering file for the real N=67 dataset behind the paper’s published statistics – confirmed by reproducing its exact reported response proportions and chi-square values (an earlier version of this dataset, built from a different, superficially similar file before that real data was located, did not reproduce them, and has been replaced). Each condition replicates the classic 3-role highlighting structure (PE, PL, I) twice; words-as-cues’ PL items have their real target at a different index than their own word index, and its I items have two legitimate targets – neither fitsxslData’s one-correct-object-per-wordaccuracyconvention, so only its two PE items get a real accuracy value (the rest areNA). Objects-as-cues has no such issue and gets a real accuracy value for all 4 of its items. Because of the partial-NA accuracy vector,kachergis2012_highlightingis kept standalone: anNAwould silently poison every other dataset’s aggregate fit inget_group_model_fit()/get_crossvalidated_model_fit(), which sum/average SSE across all ofxsl_datasets.kachergis_initial_accuracyhas no such blocker but is kept standalone for now. See their?helppages anddata-raw/add_kachergis2012_highlighting.R/add_kachergis_initial_accuracy.Rfor full construction details, andtests/bakeoff_comparison/kachergis2012_highlighting_fit.Rfor a custom scorer that fits a model against all four of the paper’s reported proportions (PE-E, PL-L, I-E, I-L) directly off the association matrix, the way the paper’s own (non-package) fitting procedure did - Added
kalman_filter(), a Kalman-filter generalization ofrescorla_wagner()’s error-driven update: each word-object association is tracked as a Gaussian belief (mean and variance), giving an adaptive learning rate that starts high under uncertainty and shrinks with confidence, rather than a fixed rate (Dayan & Kakade, 2000; Kruschke, 2008) - Added
softmax_rl(), a Q-learning-style reinforcement learning model. Unlike every other model in the package (which updates every word-object pair presented together on a trial), it makes a discrete choice per word – sampling a candidate referent from a softmax policy over its current values, then updating only that guess via a TD/delta-rule reward (1 if the guess was present in the scene, 0 otherwise). This mirrorspropose_but_verify()/pursuit()’s propose-and-verify logic but replaces their threshold-based keep/discard rules with graded value learning and explicit softmax exploration - Added two naturalistic corpora imported from the wurwur package (github.com/mcfrank/wurwur), as standalone objects (not appended to
xsl_datasets, which is scored by SSE against a human accuracy vector these don’t have):rollins_corpus– the CHILDES/Rollins corpus the Frank, Goodman & Tenenbaum (2009) model was fit to (619 mother-infant utterances, 416 words, 22 objects) – andfm_corpus– the larger Frank, Tenenbaum & Fernald corpus (4763 utterances, 1122 words, 30 objects), which additionally carries the speaker’s hand-coded referential intention per utterance (fm_corpus$intents). Each is a list bundling the trainingxslData($data) with a gold-standard lexicon ($gold, plus$gold_variantsfor FM) to be scored withget_fscore()/get_roc()/get_tp()rather than SSE. Gaze/hand attentional cues in the FM source are not imported. Seedata-raw/add_wurwur_corpora.R - Added
predict_referent(), a model-agnostic trial-level prediction: given any model’s word-object matrix, a heard word, and the objects present, it returns the probability distribution over those objects (P(object | word) proportional to m[word, object] * prior(object), normalized over the objects present) – the quantity to compare against a participant’s choice on a referent-selection trial. Supports a non-uniformprior(set an entry to 0 to remove an object the speaker has no epistemic access to) and apragmatic = TRUEmode that resolves the objects with a one-step Rational Speech Act pragmatic listener (rsa_listener()/rsa_speaker(), also exported), yielding strong mutual exclusivity when a heard word is lexically ambiguous and a competitor word names one of the candidates.mafc_test()is now a thin wrapper over it (behavior unchanged; gains a...passthrough forpragmatic/threshold) - Added
fgt2009()andfgt2009_rsa(), a pure-R port of the intentional Bayesian word-learning model of Frank, Goodman & Tenenbaum (2009) and its Rational Speech Act (RSA) pragmatic extension, from the Python packagewordlearn(github.com/mcfrank/wurwur). Unlike every other model in the package – which tally word-object associations incrementally, trial by trial – this is a batch model: it does joint MCMC inference (blocked per-object Gibbs plus MI-biased single-edge Metropolis moves) over the whole corpus at once, asking which lexicon best explains all the data, soxslFit$matrixholds posterior edge marginalsP(word names object | corpus)rather than a running tally. It therefore has no learning trajectory and ignorescontrol$reps. The scoring kernel is verified to match the Python reference to numerical precision.gamma/kappadefault to the values used for the analogous cross-situational simulation in the source package (gamma = 1, since every word in a controlled XSL experiment is a referential label). The lexicon-size prioralphascales with corpus size and its fit-vs-alphacurve is single-peaked, so it is not wired intoxsl_model_registry()’s DEoptim bounds like the other models; use the newfgt2009_sweep_alpha()helper instead (which takes an optionalgoldargument to report the best-threshold F-score against a gold lexicon at eachalpha, for corpora with no human accuracy vector) - Added a vignette, “Running and fitting models on naturalistic corpora”, covering how to run any model on
rollins_corpus/fm_corpus, score the learned matrix against a gold lexicon withget_fscore()/get_roc()/get_roc_max(), and choosefgt2009()’salphaby sweeping. It ends with a quick model comparison (bayesian_decayandfazlyrecover the gold lexicon best on both corpora, withfgt2009close behind and highest-precision). The comparison script and its outputs are intests/bakeoff_comparison/corpus_gold_comparison.R(every model at registry defaults); a companion,corpus_gold_fits.R, fits each model’s parameters to each corpus (parallel DEoptim maximizing gold-lexicon F, since these corpora have no accuracy vector;fgt2009()by analphasweep). Fitting lifts every model – dramatically for the ones whose registry defaults were tuned on controlled experiments (tilles+0.34,uncfam_predictive+0.15/+0.32) – andbayesian_decayfit to the FM corpus reaches F = 0.56.tests/bakeoff_comparison/corpus_report.mdis a rendered write-up of all of this
Other changes
-
xsl_run()is now far more memory-frugal on long inputs (corpora). Previously it built the full list of every simulation’sxslFit– each carrying a word-by-object matrix per training trial – and only reduced them at the end, so a stochastic model on the 4763-utterance FM corpus atn_sim = 50needed tens of GB and simply failed. Now: (1) the per-trial trajectory (xslFit$traj) is only recorded whenxslControl(keep_traj = TRUE)– it is off by default and is not used by any function in the package; (2)xsl_run()accumulates the summed matrix one simulation at a time rather than holding alln_simat once; (3) the full per-simulation list (fits[[i]]$sims) is dropped unlessxslControl(keep_sims = TRUE), replaced byfits[[i]]$responses, a compactn_simx n-words matrix of each simulated participant’s final per-word accuracy.matrix,perf, andsseare numerically unchanged.
Performance
-
uncfam_sampling()/multi_sampling(): every trial was allocating two fullvoc_sz x ref_szmatrices and computing a full outer product, even though only the handful of cells at[tr_w, tr_o]are ever nonzero. Entropy, weighting, and the update are now computed on that small per-trial submatrix instead. Behaviour-preserving – thesample()call’s probability vector is still built at fullref_szlength (zero outsidetr_o), so the RNG draw sequence, and therefore every existing fit, is unchanged. 1.17x faster on a small lab condition, 1.97x onrollins_corpus(bigger vocabularies benefit more, since that’s the dimension the fix targets) -
shannon_entropy()computedsum(p)twice (once for the<= 0check, again for normalization); now computed once and reused -
update_known()’swhich(...)-based zero-filling replaced with direct logical-vector indexing, removing fivewhich()calls per trial
Bug Fixes
-
update_known()computedwhich(m[w, fam_objects] == 0)– positions within thefam_objects-filtered subset – and then indexedm[w, zeros]as if those were absolute column positions, silently fillingstartvalinto the wrong cell wheneverfam_objects(orfam_words, for the symmetric object-side fill) was a proper subset of all columns/rows – i.e. whenever some word or object was still wholly unfamiliar. Affects all 5 models that call it (uncfam(),uncfam_attention(),uncfam_predictive(),uncfam_sampling(),multi_sampling()). In practice this only ever mis-set a handful of near-zero cells during early training that get overwritten by real learning signal soon after – verified to make no difference to the final matrix on any ofxsl_datasets’ 53 conditions orfm_corpus, and a single cell’sstartvalonrollins_corpus. Fixed as part of the logical-indexing rewrite above. -
guess_and_test()errored (ifwith a zero- or multiple-length condition at the disconfirmation step) on any utterance that repeats a word – common in a naturalistic corpus, impossible in a controlled trial – because the repeated word was visited twice and the first pass could clear or double-set its hypothesis. It now de-duplicates a trial’s words and objects. Its disconfirmation check also compared a column position to the object labels (only equivalent when objects are labelled1..N), and it applied new hypotheses toneed_hypoths[w]rather than the actual stored wordstore[w](setting hypotheses for the wrong words whenever only a subset rolled below the storage threshold); both are fixed. -
tilles()coerced each trial’s words/objects withas.integer()(it indexes its state by position), turning any non-integer label intoNAand leaving the matrix all-zero; it also never setdimnameson its matrix, so the result could not be scored against a gold lexicon by label. It now maps labels to positions withmatch()and names its matrix.xsl_datasetsresults are unchanged (the labels there are already1..N). -
softmax_rl()checked its sampled guess against the trial’s objects withproposal %in% tr_o, comparing a column position (1..ref_sz) against the objects’ labels. Forxsl_datasetsthe object labels are1..Nso it happened to work, but on any dataset whose objects have non-integer (or non-contiguous) labels – e.g. either bundled corpus – every reward was 0 and the learned Q-matrix stayed identically zero. It now maps the objects present to positions (match(tr_o, ref)) before the check, and skips a trial with no objects present.xsl_datasetsresults are unchanged. -
uncfam_sampling()andmulti_sampling()errored (sample(): “too few positive probabilities”) on any dataset containing an utterance with no objects present – e.g. the ~320 non-referential utterances infm_corpus, which made both models unable to run on a naturalistic corpus. Such a trial now leaves the association matrix unchanged apart from decay (asuncfam()already did), by skipping the per-word sampling when its weights are all zero and only applying the normalized update when something was sampled. Behaviour on datasets without objectless trials (all ofxsl_datasets) is unchanged. -
tilles()was essentially unfittable – three separate bugs (not the single one originally suspected) made a quick DEoptim search returnInffor every draw: (1) itsalphaterm was recomputed fresh every trial instead of persisting per-word across trials, so words absent from the current trial (needed by the “other old words” update) always hadalpha = NA; (2) an internal matrix was sizedvoc_sz x voc_szinstead ofvoc_sz x ref_sz, a copy-paste bug that only breaks on asymmetric datasets (word count != object count); (3) a flux computation divided by a quantity that can legitimately be zero (a previously-seen word paired with an entirely new-to-it set of objects), producingInf * 0 = NaN. One dataset failed on 100% of a 40-draw sweep regardless of parameters before these fixes; after them, a 100-draw sweep shows a residual ~2% failure rate confined to extreme parameter-space tails, on par with other models’ known numerical edges
XSLmodels 0.2.0
New Features
- Added helper functions
show_models(),show_datasets(),get_group_model_fit(), andget_crossvalidated_model_fit()(now actually exported and working) - Re-implemented k-fold cross-validation (
cross_validated_group_fits(),get_train_test_split()) for the currentxslMod/xslDataarchitecture - Added 9 new conditions to
xsl_datasets(44 -> 53): 2 from Kachergis, Yu, & Shiffrin (2009) (temporal contiguity), 3 from Suanda, Mugwanya, & Namy (2014), and 4 from Koehne, Trueswell, & Gleitman (2013)
Bug Fixes
-
xslData()no longer rejects data with noresponse_matrixsupplied – this was breaking the vignette, most function examples, andget_example_ambiguous_condition()/get_example_unambiguous_condition() -
get_group_model_fit()/get_crossvalidated_model_fit()calleduncfam_sampling(),multi_sampling(),tilles(), andfazly()with incorrect parameter names, causing them to error for those models -
update_params()was dropping the parameter list’s names/type, which madexsl_run()error for every model exceptbayesian_decay()whenever it was called after fitting (e.g. fromxsl_fit()or cross-validation) -
xsl_fit()now treats a model erroring or returningNA/NaNSSE for a given parameter draw as an infinitely bad fit instead of aborting the whole optimization run - Fixed
tilles()mislabeling its model name as"rescorla_wagner" -
create_cooc_matrix()test had an incorrect expected value -
plot_training_trials()now gives an informative error if the optionalviridis/gganimatepackages aren’t installed, instead of a raw namespace-loading error -
xsl_run()checked!is.null(dat$test)to decide whether to usemafc_test(), butxslData()’stestdefaults tolist()(notNULL), so any dataset built without explicit test trials – including the package’s ownget_example_ambiguous_condition()/get_example_unambiguous_condition()– was silently routed throughmafc_test(mat, list()). That returnednumeric(0)rather than erroring (an R quirk:1:0counts down instead of being empty, andvec[i] <- numeric(0)truncates the vector rather than erroring), producing a falsesse = 0“perfect fit” with no warning. Now checkslength(dat$test) > 0. -
guess_and_test()had an inverted guard clause (if (length(which(m[w,]==1))) next) that made its hypothesis-disconfirmation step permanently unreachable, since it was only reached for words that already have a stored hypothesis (guaranteeing the guard’s condition was always true). Hypotheses were therefore never disconfirmed once formed, silently disabling a core part of the model (“…on later encounters, learners attempt to retrieve this hypothesis from memory and test it against a new context, updating it only if it is disconfirmed”). Found by comparing the package’s fits against the original pre-package research code’s fits for the same 44-condition dataset.