Mapping the neuronal building blocks of human language with language models.
The 16 matches
- [1] § Combinatorial linguistic encoding ↔ analysis.zip/computation/figure/Figure3.ipynb, lines 1–25 · score 0.73 · network layers, word utterance, Swap sentence, peak predictivities, normalized predictivity, population predictivities
- [2] § Methods › Predictivities of neurons across language models › Neural predictivity controls ↔ analysis.zip/computation/code/C1_neuron_predictivity_mean_various_llm_swap_sentence.py, lines 1–43 · score 0.71 · length matched, swap sentence, neuronal population, predictivities, embeddings, models
- [3] § Methods › Predictivities of neurons across language models › Neural predictivity dynamics and mapping ↔ analysis.zip/computation/code/C1_neuron_predictivity_mean_various_llm_by_time_shuffle.py, lines 1–41 · score 0.69 · temporal window, neural activity, neuronal firing rates, shifted, post, dynamics
- [4] § Methods › Predictivities of neurons across language models › Language model predictivity ↔ analysis.zip/computation/code/C1_neuron_predictivity_mean_randtok.py, lines 1–38 · score 0.67 · neuronal firing rates, aligned neuronal, population predictivities, neuronal predictivities, model
- [5] § Linguistic representations by neurons ↔ analysis.zip/computation/code/B1_probe_decoding_single_word.py, lines 1–25 · score 0.64 · Decoding linguistic features, single word, linguistic representations, training, neural, activity
- [6] § Diversity and distribution of neurons ↔ analysis.zip/computation/figure/Figure4.ipynb, lines 1–32 · score 0.64 · anatomical areas, posterior frontal, brain areas, posterior temporal, selective neurons, brightness
- [7] § Methods › Predictivities of neurons across language models › Language model predictivity ↔ analysis.zip/computation/code/C1_neuron_predictivity_mean_various_llm.py, lines 1–35 · score 0.62 · neuronal firing rates, aligned neuronal, population predictivities, temporal, Language, model
- [8] § Methods › Single-neuronal and local field responses to linguistic features › Comparing neuronal activities across hemispheres and cortical areas ↔ analysis.zip/computation/figure/Figure4.ipynb, lines 152–204 · score 0.60 · posterior frontal, anterior temporal, posterior temporal
- [9] § Methods › Predictivities of neurons across language models › Language model predictivity ↔ analysis.zip/computation/code/C1_neuron_predictivity_mean_various_llm_by_time_shuffle.py, lines 1–41 · score 0.59 · randomly permuting, shuffled control, baseline, predictivity, permutation, activities
- [10] § Combinatorial linguistic encoding ↔ analysis.zip/computation/code/C1_neuron_predictivity_mean_various_llm_swap_sentence.py, lines 1–43 · score 0.58 · Swap sentence, population predictivities, Neuronal predictivity, LLaMA, semantic, embeddings
- [11] § Local cortical organization ↔ analysis.zip/computation/figure/Figure5.ipynb, lines 1–25 · score 0.57 · coincidence matrix, LFP response, LFP activities, microelectrode, single neuronal, channels
- [12] § Linguistic representations by neurons ↔ analysis.zip/computation/code/function_code.py, lines 414–440 · score 0.57 · logistic regression, L2, multinomial, classifier, training, Decoding
- [13] § Methods › Single-neuronal and local field responses to linguistic features › Single-neuronal analysis › Modulation of neuronal responses ↔ analysis.zip/computation/code/A2_probe_selectivity_zscore.py, lines 1–26 · score 0.57 · neuronal modulation, neuronal firing rates, magnitude, quantifies, linguistic feature, scores
- [14] § Methods › Predictivities of neurons across language models › Neural predictivity dynamics and mapping ↔ analysis.zip/computation/code/C1_neuron_predictivity_mean_various_llm.py, lines 1–35 · score 0.56 · temporal window, neuronal firing rates, dynamics, mapping, predictivity, population
- [15] § Methods › Neuronal decoding analysis › Decoding linguistic features from neural activity › Decoding model ↔ analysis.zip/computation/code/function_code.py, lines 414–440 · score 0.55 · logistic regression, L2, multinomial, classifier, decode
- [16] § Combinatorial linguistic encoding ↔ analysis.zip/computation/figure/Figure3.ipynb, lines 1–25 · score 0.54 · neurons peak predictivities, exponential fit, population predictivity, sided permutation, utterance, regression
Paper
Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC
The paper is loaded when this pane is shown.
The authors' code
Jupyter notebook · 436 lines · 17 KB · CC-BY-4.0 · 2 matches
- # %% [markdown]
- # # Figure 3: Organization and Temporal Dynamics of Linguistic Information Encoding
- #
- # This section generates the analysis and visualizations for Figure 3, which explores how various models (syntactic, semantic, and contextual) predict neuronal population activity, as well as the temporal dynamics of this predictivity.
- #
- # ### Figure Panels Breakdown:
- # * **Panel b:** Population predictivities. Box plots showing distribution (Q1–Q3), median, and mean, evaluated against chance distributions (1-sided permutation tests).
- # * **Panel c:** Contextual integration analysis. Exponential fit demonstrating the relationship between context length and predictive performance.
- # * **Panel d:** Validation controls. Performance comparison against swap-sentence and pseudo-sentence null models.
- # * **Panel e:** Temporal and layered dynamics. Normalized predictivity heatmaps across time (aligned to word utterance) and network layers.
- # * **Panel f:** Peak predictivity mapping. Relationship between single-neuron peak predictivity, peak timing, DNN layer, and specific linguistic feature selectivity.
- #
- # ### Dependencies & Data Requirements:
- # * Requires Ridge regression outputs (`result_llm/`).
- # * Requires pre-computed predictivity scores (C1/C2/C3/D1).
- # %%
- import numpy as np
- import pandas as pd
- import matplotlib.pyplot as plt
- import copy
- import matplotlib as mpl
- from matplotlib.pyplot import rc
- plt.rcParams['font.size'] = '10'
- mpl.rcParams['pdf.fonttype'] = 42
- # %%
- onehot = np.load('../result_llm/combined/C3_explained_r_syn.npy')
- onehot_shuffle = np.load('../result_llm/combined/C3_explained_r_syn_shuffle.npy')
- onehot_w2v = np.load('../result_llm/combined/C3_explained_r_sem_syn_exclude_oov.npy')
- onehot_w2v_shuffle = np.load('../result_llm/combined/C3_explained_r_sem_syn_exclude_oov_shuffle.npy')
- exp_w2v = np.load('../result_llm/combined/C3_explained_r_word2vec_exclude_oov.npy')
- exp_w2v_shuffle = np.load('../result_llm/combined/C3_explained_r_word2vec_exclude_oov_shuffle.npy')
- exp_r3 = np.load('../result_llm/combined/C1_explained_r_combined_normalize_mean_vicuna7b.npy') # dim = session x time (-2 to 2 second, 0.1 s / bin) x layer
- exp_r3_shuffle = np.load('../result_llm/combined/C1_explained_r_combined_normalize_mean_vicuna7b_by_time_shuffle.npy') # dim = session x time (-2 to 2 second, 0.1 s / bin) x layer
- # %%
- # %% [markdown]
- # # Figure 3b: Comparison of Neuronal Predictivity: Syntactic, Word2Vec, and LLM Models
- # %%
- np.random.seed(10)
- ss = 0
- ee = 3
- plt.figure(figsize=(5,6))
- values = onehot[:,ss:ee,0].mean(1)
- plt.plot(np.random.normal(-4,0.1,14),values,'C0.',alpha=1)
- bp1 = plt.boxplot(values, positions = [-4],sym='', widths=[0.3])
- for median in bp1['medians']:
- median.set(color='C3', linewidth=2)
- # print(values.mean(), '\t',values.std(), '\t',np.median(values))
- plt.plot([-4-0.1,-3.9],[values.mean(), values.mean()],'r-')
- values = onehot_shuffle[:,ss:ee,0].mean(1)
- plt.plot(np.random.normal(-3.5,0.1,14),values,'C0.',alpha=1)
- bp1 = plt.boxplot(values, positions = [-3.5],sym='', widths=[0.3])
- for median in bp1['medians']:
- median.set(color='gray', linewidth=2)
- plt.plot([-3.5-0.1,-3.4],[values.mean(), values.mean()],'r-')
- values = exp_w2v[:,ss:ee,0].mean(1)
- plt.plot(np.random.normal(-2,0.1,14),values,'C0.',alpha=1)
- bp1 = plt.boxplot(values, positions = [-2],sym='', widths=[0.3])
- for median in bp1['medians']:
- median.set(color='C2', linewidth=2)
- # print(values.mean(), '\t',values.std(), '\t',np.median(values))
- plt.plot([-2-0.1,-1.9],[values.mean(), values.mean()],'r-')
- values = exp_w2v_shuffle[:,ss:ee,0].mean(1)
- plt.plot(np.random.normal(-1.5,0.1,14),values,'C0.',alpha=1)
- bp1 = plt.boxplot(values, positions = [-1.5],sym='', widths=[0.3])
- for median in bp1['medians']:
- median.set(color='gray', linewidth=2)
- plt.plot([-1.5-0.1,-1.4],[values.mean(), values.mean()],'r-')
- values = onehot_w2v[:,ss:ee,0].mean(1)
- plt.plot(np.random.normal(0,0.1,14),values,'C0.',alpha=1)
- bp1 = plt.boxplot(values, positions = [0],sym='', widths=[0.3])
- for median in bp1['medians']:
- median.set(color='C1', linewidth=2)
- # print(values.mean(), '\t',values.std(), '\t',np.median(values))
- plt.plot([-0.1,0.1],[values.mean(), values.mean()],'r-')
- values = onehot_w2v_shuffle[:,ss:ee,0].mean(1)
- plt.plot(np.random.normal(0.5,0.1,14),values,'C0.',alpha=1)
- bp1 = plt.boxplot(values, positions = [0.5],sym='', widths=[0.3])
- for median in bp1['medians']:
- median.set(color='gray', linewidth=2)
- plt.plot([0.5-0.1,0.6],[values.mean(), values.mean()],'r-')
- values = exp_r3[:,(ss+17):(ee+17),5].mean(1)
- plt.plot(np.random.normal(2,0.1,14),values,'C0.',alpha=1)
- bp1 = plt.boxplot(values, positions = [2],sym='', widths=[0.3])
- for median in bp1['medians']:
- median.set(color='C0', linewidth=2)
- # print(values.mean(), '\t',values.std(), '\t',np.median(values))
- plt.plot([2-0.1,2.1],[values.mean(), values.mean()],'r-')
- values = exp_r3_shuffle[:,(ss+17):(ee+17),5].mean(1)
- plt.plot(np.random.normal(2.5,0.1,14),values,'C0.',alpha=1)
- bp1 = plt.boxplot(values, positions = [2.5],sym='', widths=[0.3])
- for median in bp1['medians']:
- median.set(color='gray', linewidth=2)
- plt.plot([2.5-0.1,2.6],[values.mean(), values.mean()],'r-')
- plt.yticks(np.arange(-0.1,0.26,0.1))
- plt.xticks(np.arange(-4,3,2),['syn','word2vec','syn_w2v','LLM'])
- plt.ylabel('predictivity')
- plt.ylim([-0.3,0.3])
- plt.legend(['orange: median; red: mean'])
- plt.savefig('figure3/predictivity_by_syn_w2v_llm.pdf')
- # %%
- # %% [markdown]
- # ### Statistical Significance Analysis: Pairwise Model Comparison
- # %%
- from scipy import stats
- def perm_test_boot(vals1_, vals2_):
- pooled = np.hstack([vals1_,vals2_])
- np.random.shuffle(pooled)
- star_in = pooled[:len(vals1_)]
- star_out = pooled[-len(vals2_):]
- return star_in.mean()-star_out.mean()
- def permutation_test_1side(vals1, vals2, nsamp=1000, seed=None):
- if seed is not None:
- np.random.seed(seed)
- vals1 = np.array(vals1)
- vals2 = np.array(vals2)
- delta = vals1.mean()-vals2.mean()
- est = np.array(list(map(lambda x: perm_test_boot(vals1, vals2),range(nsamp))))
- diff_count = len(np.where(est>=delta)[0])
- p2 = float(diff_count)/float(nsamp)
- return p2
- def permutation_test_2side(vals1, vals2, nsamp=1000, seed=None):
- if seed is not None:
- np.random.seed(seed)
- vals1 = np.array(vals1)
- vals2 = np.array(vals2)
- delta = vals1.mean()-vals2.mean()
- est = np.array(list(map(lambda x: perm_test_boot(vals1, vals2),range(nsamp))))
- diff_count = len(np.where(np.abs(est)>=np.abs(delta))[0])
- p = float(diff_count)/float(nsamp)
- return p
- def check_significance(data_array, point):
- # Filter out NaNs to get clean stats
- clean_data = data_array[~np.isnan(data_array)]
- mu = np.mean(clean_data)
- sigma = np.std(clean_data, ddof=1) # Use ddof=1 for sample standard deviation
- # Calculate Z-score: (x - mu) / sigma
- z_score = (point - mu) / sigma
- # Get the two-tailed p-value
- # stats.norm.sf is the survival function (1 - CDF)
- p_value = stats.norm.sf(abs(z_score)) * 2
- return z_score, p_value
- # %%
- # Performs 1-sided permutation testing (n=100,000) to evaluate whether the predictive performance differences between the Contextual (LLM) and Syntactic/Semantic models are statistically significant.
- ss = 0
- ee = 3
- values0 = exp_r3[:,(ss+17):(ee+17),5] # time offsets start from -2,000 s for this dataset.
- values1 = onehot[:,ss:ee,0]
- values2 = exp_w2v[:,ss:ee,0]
- values3 = onehot_w2v[:,ss:ee,0]
- print('contextual v.s. syn; \tp = ',permutation_test_1side(values0.reshape(-1), values1.reshape(-1), nsamp=100000, seed=46))
- print('contextual v.s. sem; \tp = ',permutation_test_1side(values0.reshape(-1), values2.reshape(-1), nsamp=100000, seed=46))
- print('contextual v.s. syn+sem; \tp = ',permutation_test_1side(values0.reshape(-1), values3.reshape(-1), nsamp=100000, seed=46))
- print('syn v.s. sem; \tp = ',permutation_test_1side(values1.reshape(-1), values2.reshape(-1), nsamp=100000, seed=46))
- print('syn v.s. syn+sem; \tp = ',permutation_test_1side(values1.reshape(-1), values3.reshape(-1), nsamp=100000, seed=46))
- print('sem v.s. syn+sem; \tp = ',permutation_test_1side(values2.reshape(-1), values3.reshape(-1), nsamp=100000, seed=46))
- # %%
- # Statistical Validation: Baseline vs. Shuffle Controls
- # Performs 1-sided permutation testing (n=100,000) to verify that the predictivity scores for each model architecture (syntactic, semantic, and combined) significantly outperform their respective shuffled null distributions.
- values1s = onehot_shuffle[:,ss:ee,0]
- values2s = exp_w2v_shuffle[:,ss:ee,0]
- values3s = onehot_w2v_shuffle[:,ss:ee,0]
- print('syn v.s. shuffle; \tp = ',permutation_test_1side(values1.reshape(-1), values1s.reshape(-1), nsamp=100000, seed=20))
- print('sem v.s. shuffle; \tp = ',permutation_test_1side(values2.reshape(-1), values2s.reshape(-1), nsamp=100000, seed=20))
- print('syn+sem v.s. shuffle; \tp = ',permutation_test_1side(values3.reshape(-1), values3s.reshape(-1), nsamp=100000, seed=20))
- # %%
- # %% [markdown]
- # # Figure 3c: Predictivity by preceding words
- # %%
- gram_n = np.array([1,3,5,7,10])
- exp_r3 = np.zeros([14,33,len(gram_n)])
- for ind, i_n in enumerate(gram_n):
- exp_r3[:,:,ind] = np.load('../result_llm/combined/C2_explained_r_combined_vicuna7b_'+str(i_n)+'gram.npy')
- exp_r3.shape
- # %%
- from scipy.optimize import curve_fit
- def exponential_func(x, a, b, c):
- """
- Exponential model function for curve fitting.
- y = a * exp(b * x) + c
- """
- return a * np.exp(b * x) + c
- # %%
- plt.figure(figsize=(3,5))
- maxind = exp_r3.mean(0).reshape(-1,5).argmax(0)
- # plt.bar(gram_n[iinds],exp_r3.mean(0)[25:45,:].max(0).max(0)[iinds],alpha=0.5,color='gray')
- output = []
- for ii in range(exp_r3.shape[2]):
- values = exp_r3[:,:,ii].reshape(14,-1)[:,maxind[ii]]
- mmean = values.mean()
- sstd = values.std()/np.sqrt(values.shape[0])
- output.append(mmean)
- plt.bar(gram_n[ii], mmean, color='C0',alpha=0.5)
- plt.errorbar(gram_n[ii], mmean, sstd, color='gray')
- # for jj in range(exp_r3.shape[0])
- plt.plot(np.random.normal(gram_n[ii], 0.1, 14), values,'C0.')
- plt.xlim([0,11])
- plt.xlabel('# of preceding words')
- plt.ylabel('predictivity')
- popt, pcov = curve_fit(exponential_func, gram_n, output, p0=(-8,-0.08,0.08))
- a_fit, b_fit, c_fit = popt
- # Create a smooth x-range for plotting the fitted curve
- x_fit = np.linspace(min(gram_n), max(gram_n), 100)
- y_fit = exponential_func(x_fit, a_fit, b_fit, c_fit)
- plt.plot(x_fit, y_fit, label=f'Fitted Curve ($y={a_fit:.2f}e^{{{b_fit:.2f}x}}+{c_fit:.2f}$)', color='red', linewidth=2)
- plt.legend(fontsize=10)
- plt.savefig('figure3/predictivity_by_preceding_words_errorbars_scatter.pdf')
- # %%
- # %%
- # %% [markdown]
- # # Figure 3d: Sentence-context specificity of neuronal activity
- # %%
- randtok = np.load('../result_llm/combined/C1_explained_r_combined_vicuna7b_random_token_randtok.npy')
- swap = np.load('../result_llm/combined/C1_explained_r_combined_normalize_mean_swap_sentence_vicuna7b.npy')
- # %%
- plt.figure(figsize=(16,10))
- plt.subplot(2,2,1)
- plt.bar(np.arange(randtok.shape[1]),randtok.mean(axis=0), width=0.5, alpha=0.8,color='C0')
- mmean = randtok.mean(0)
- sstd = randtok.std(0)/np.sqrt(randtok.shape[0])
- plt.errorbar(np.arange(randtok.shape[1]), mmean, sstd, color='gray',fmt='none')
- for ii in range(randtok.shape[1]):
- plt.plot(np.random.normal(ii, 0.1, 14), randtok[:,ii],'.',color='gray', alpha=0.5)
- plt.ylim([-0.3,0.3])
- plt.yticks(np.arange(-30,31,10)/100)
- # plt.xticks(np.arange(5,11,5))
- plt.xlabel('layers')
- plt.ylabel('predictivity')
- plt.title('Pseudo-sentence input control')
- plt.subplot(2,2,2)
- plt.bar(np.arange(swap.shape[1]),swap.mean(axis=0), width=0.5, alpha=0.8,color='C0')
- mmean = swap.mean(0)
- sstd = swap.std(0)/np.sqrt(swap.shape[0])
- plt.errorbar(np.arange(swap.shape[1]), mmean, sstd, color='gray',fmt='none')
- for ii in range(swap.shape[1]):
- plt.plot(np.random.normal(ii, 0.1, 14), swap[:,ii],'.',color='gray', alpha=0.5)
- plt.ylim([-0.3,0.3])
- plt.yticks(np.arange(-30,31,10)/100)
- plt.xlabel('layers')
- plt.ylabel('predictivity')
- plt.title('swap')
- plt.savefig('figure3/vicuna7b_pseudoSentence_Swapping_controls_bars_scatter.pdf')
- # %%
- # %% [markdown]
- # # Figure 3e: Temporal structure of neuronal activity
- # %%
- folder_all = ['p1_1', 'p1_2', 'p2_1', 'p2_2', 'p3_1', 'p3_2', 'p4_1', 'p5_1', 'p5_2', 'p6_1', 'p7_1', 'p7_2', 'p8_1', 'p8_2']
- nn = 0
- ww = 0
- neuron_nums = []
- for folder in folder_all:
- neuron_data= np.load('../../../data_processed/'+folder+'/self_FR_aligned2word.npy')
- # print(folder, neuron_data.shape[:2])
- nn += neuron_data.shape[0]
- ww += neuron_data.shape[1]
- neuron_nums.append(neuron_data.shape[0])
- neuron_nums = np.array(neuron_nums)
- # %%
- exp_r3 = np.load('../result_llm/combined/C1_explained_r_combined_normalize_mean_vicuna7b.npy')
- weights_normalized = neuron_nums / np.sum(neuron_nums)
- weights_reshaped = weights_normalized[:, np.newaxis, np.newaxis]
- weighted_exp_r3 = exp_r3 * weights_reshaped
- weighted_average = np.sum(weighted_exp_r3, axis=0)
- # %%
- plt.imshow(weighted_average.transpose()/(weighted_average.max()),vmin=0, vmax=1, cmap='magma')
- plt.colorbar(orientation='horizontal')
- plt.xticks(np.arange(0,41,10),(np.arange(-20,21,10)/10).astype(int))
- # plt.xlim([0,80])
- plt.xlabel('time (s)')
- plt.ylabel('layer')
- plt.savefig('figure3/population_predictivity_weight_mean.pdf')
- # %%
- # This provides an additional non-weighted version for comparison.
- plt.imshow(exp_r3.mean(0).transpose()/(exp_r3.mean(0).max()),vmin=0, vmax=1, cmap='magma')
- plt.colorbar(orientation='horizontal')
- plt.xticks(np.arange(0,41,10),(np.arange(-20,21,10)/10).astype(int))
- # plt.xlim([0,80])
- plt.xlabel('time (s)')
- plt.ylabel('layer')
- # %%
- exp_r3_indiv = np.load('../result_llm/combined/D1_explained_r_combined_indiv_vicuna7b.npy')
- plt.imshow(np.nanmean(exp_r3_indiv,0).T/np.nanmean(exp_r3_indiv,0).max(),vmin=0,vmax=1,cmap='magma')
- plt.colorbar(orientation='horizontal')
- plt.xticks(np.arange(0,41,10),(np.arange(-20,21,10)/10).astype(int))
- # plt.xlim([-1,39])
- plt.xlabel('time (s)')
- plt.ylabel('layer')
- plt.savefig('figure3/explained_r_image_vicuna_indiv_magma.pdf')
- # %%
- # %% [markdown]
- # # Figure 3f: Population organization of linguistic representations
- # %%
- probe_all = ['Constituency_level','Closing_depth','Constituents','Parts_of_speech','Dependency_depth','Dependencies','Word_position','Word_pitch']
- neuron_n = 579
- all_probes = np.zeros([0,neuron_n])
- for i in range(len(probe_all)):
- temp_method = 'ranksum'
- temp = np.load('../result_feature/combined/A1_'+probe_all[i]+'_self_fdr_p_'+temp_method+'.npy')
- all_probes = np.vstack((all_probes, temp[:neuron_n].reshape([1,-1])))
- trans_ind = np.load('trans_ind.npy')
- all_probes = all_probes[:,trans_ind]
- # %%
- layer = exp_r3_indiv.shape[2]
- mmap = np.zeros([10, layer, 40]) # feature x layer x time
- for dt3 in range(40):
- exp_floor = copy.deepcopy(exp_r3_indiv)
- exp_floor[exp_floor<0] = 0
- for i in range(8):
- sel_neu = (all_probes[i,:]<0.05)
- mmap[i,:,dt3] = np.nanmean(exp_floor[sel_neu, dt3, :],axis=0)
- i += 1
- sel_neu = (all_probes.min(axis=0)>0.05)
- mmap[i,:, dt3] = np.nanmean(exp_floor[sel_neu, dt3, :], axis=0)
- # %%
- from matplotlib.patches import Ellipse
- # reorder = np.array([2, 3,1,4,5, 0,6,7,8])
- reorder = np.array([1,2,4,3,0,5,6,7,8])
- scale_factor = 25
- xy_scale_factor = 2.25
- fig, ax = plt.subplots(1)
- for i in range(len(reorder)-3):
- argm = np.argmax(mmap[reorder[i]][:,5:20])
- argx, argy = np.unravel_index(argm, mmap[reorder[i]][:,5:20].shape)
- # ax.plot(argy, argx, 'o', alpha=0.5, markersize = mmap[reorder[i]][:,5:20][argx, argy]*500)
- width = (0 + mmap[reorder[i]][:,5:20][argx, argy])*scale_factor
- height = (0 + mmap[reorder[i]][:,5:20][argx, argy])*scale_factor*xy_scale_factor
- ellipse = Ellipse((argy, argx), width, height, angle=0,
- edgecolor='none', facecolor='C'+str(i), lw=2, alpha=0.5)
- ax.add_patch(ellipse)
- width = (mmap[reorder[i]][:,5:20].std(0)[argy] + mmap[reorder[i]][:,5:20][argx, argy]*2)*scale_factor
- height = (mmap[reorder[i]][:,5:20].std(1)[argx] + mmap[reorder[i]][:,5:20][argx, argy]*2)*scale_factor*xy_scale_factor
- ellipse = Ellipse((argy, argx), width, height, angle=0,
- edgecolor='C'+str(i), facecolor='C'+str(i), lw=1, alpha=0.1,label='_nolegend_')
- ax.add_patch(ellipse)
- ww = 0.05*scale_factor
- hh = ww*xy_scale_factor
- stand1 = Ellipse((15,10), ww, hh, angle=0, edgecolor='none', facecolor='gray', lw=2, alpha=0.5)
- ax.add_patch(stand1)
- ww = 0.1*scale_factor
- hh = ww*xy_scale_factor
- stand1 = Ellipse((15,10), ww, hh, angle=0, edgecolor='gray', facecolor='gray', lw=1, alpha=0.1)
- ax.add_patch(stand1)
- ax.set_ylim([0,35])
- ax.set_xlim([0,20])
- ax.set_xticks(np.arange(0,16,5),(np.arange(-15,1,5)/10))
- ax.set_yticks(np.arange(0,35,5))
- plt.text(15,5,'scale: 0.05, 0.1')
- plt.legend(np.array(probe_all)[reorder[:6]])
- plt.xlabel('time (s)')
- plt.ylabel('layer')
- plt.savefig('figure3/max_predictivity_by_layer_time_probe.pdf')
- # %%
Figure3.ipynb, under CC-BY-4.0 · at the source
Overview
- Department of Neurosurgery, Massachusetts General Hospital, Harvard Medical School, Boston, MA USA
- Department of Neurology, Massachusetts General Hospital, Harvard Medical School, Boston, MA USA
- Center for Neurotechnology and Neurorecovery, Department of Neurology, Massachusetts General Hospital, Boston, MA USA
- Harvard-MIT Division of Health Sciences and Technology, Boston, MA USA
- Harvard Medical School, Program in Neuroscience, Boston, MA USA
Abstract
The abstract is not reproduced here: the paper's license (CC BY-NC-ND) does not allow it. Read it in the paper, at the publisher or on Europe PMC.
Repository
Its files are read in the Code ↔ Paper reader above, with 16 matches between paragraphs and lines of code.
Zenodo 20128462
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
- 27 September 2026: the link answers (HTTP 200)
23 files
- analysis.zip/
computation/ , Python, 90 linescode/ A1_probe_selectivity.py - analysis.zip/
computation/ , Python, 74 lines, 1 matchcode/ A2_probe_selectivity_zsc ore.py - analysis.zip/
computation/ , Python, 92 linescode/ A3_probe_selectivity_lfp .py - analysis.zip/
computation/ , Python, 82 linescode/ A4_probe_selectivity_zsc ore_lfp.py - analysis.zip/
computation/ , Python, 94 lines, 1 matchcode/ B1_probe_decoding_single _word.py - analysis.zip/
computation/ , Python, 97 lines, 1 matchcode/ C1_neuron_predictivity_m ean_randtok.py - analysis.zip/
computation/ , Python, 91 lines, 2 matchescode/ C1_neuron_predictivity_m ean_various_llm.py - analysis.zip/
computation/ , Python, 100 lines, 2 matchescode/ C1_neuron_predictivity_m ean_various_llm_by_time_ shuffle.py - analysis.zip/
computation/ , Python, 152 lines, 2 matchescode/ C1_neuron_predictivity_m ean_various_llm_swap_sen tence.py - analysis.zip/
computation/ , Python, 96 linescode/ C2_neuron_predictivity_m ean_length.py - analysis.zip/
computation/ , Python, 73 linescode/ C3_onehot_predictivity.p y - analysis.zip/
computation/ , Python, 77 linescode/ C3_onehot_predictivity_s huffle.py - analysis.zip/
computation/ , Python, 88 linescode/ C3_word2vec_onehot_predi ctivity_exclude_oov.py - analysis.zip/
computation/ , Python, 90 linescode/ C3_word2vec_onehot_predi ctivity_exclude_oov_shuf fle.py - analysis.zip/
computation/ , Python, 84 linescode/ C3_word2vec_predictivity _exclude_oov.py - analysis.zip/
computation/ , Python, 88 linescode/ C3_word2vec_predictivity _exclude_oov_shuffle.py - analysis.zip/
computation/ , Python, 72 linescode/ D1_neuron_predictivity_i nd_various_llm.py - analysis.zip/
computation/ , Python, 440 lines, 2 matchescode/ function_code.py - analysis.zip/
computation/ , Jupyter, 233 linesfigure/ Figure2.ipynb - analysis.zip/
computation/ , Jupyter, 436 lines, 2 matchesfigure/ Figure3.ipynb - analysis.zip/
computation/ , Jupyter, 466 lines, 2 matchesfigure/ Figure4.ipynb - analysis.zip/
computation/ , Jupyter, 165 lines, 1 matchfigure/ Figure5.ipynb - Readme.txt, Text, 57 lines
Code availability statement
The paper has a code availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:
- it points to the authors' code: Zenodo 20128462
Read it in the paper: doi.org/10.1038/s41586-026-10691-5.
Tracing map
Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.
What the map holds:
- 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
- 22 scripts, each with its path and the digest of its content;
- 16 matches between paragraphs of the paper and lines of the code (method lexical-v1);
- neither the text of the paper nor the code itself.
Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.
Data
No dataset and no data link were found in the paper.
Data availability statement
The paper has a data availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:
- no repository, dataset or request procedure was recognized in it
Read it in the paper: doi.org/10.1038/s41586-026-10691-5.
Versions
The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.
Version 2, 28 September 2026
- Publisher: n/a → Nature Portfolio
Version 1, 27 September 2026: the first record
Recorded: type, language, journal, volume, issue, pages, dates, 7 authors, 2 keywords, 13 MeSH terms, 108 references.
Cite
This paper
Cai, J., Kfir, Y., Jamali, M., Huang, H., Kim, Y. J., Cash, S. S., & Williams, Z. M. (2026). Mapping the neuronal building blocks of human language with language models. Nature, 656(8127), 425-433. https://
BibTeX
@article{cai2026mapping,
author = {Cai, Jing and Kfir, Yoav and Jamali, Mohsen and Huang, Hesen and Kim, Young Joon and Cash, Sydney S and Williams, Ziv M},
title = {{Mapping the neuronal building blocks of human language with language models}},
journal = {Nature},
year = {2026},
month = jun,
volume = {656},
number = {8127},
pages = {425--433},
publisher = {Nature Portfolio},
issn = {0028-0836},
doi = {10.1038/
url = {https://
pmid = {42310453},
pmcid = {PMC13468166}
}
RIS
TY - JOUR
AU - Cai, Jing
AU - Kfir, Yoav
AU - Jamali, Mohsen
AU - Huang, Hesen
AU - Kim, Young Joon
AU - Cash, Sydney S
AU - Williams, Ziv M
TI - Mapping the neuronal building blocks of human language with language models
T2 - Nature
J2 - Nature
PY - 2026
DA - 2026/
VL - 656
IS - 8127
SP - 425
EP - 433
SN - 0028-0836
PB - Nature Portfolio
DO - 10.1038/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1038/
"type": "article-journal",
"title": "Mapping the neuronal building blocks of human language with language models",
"container-title": "Nature",
"author": [
{
"family": "Cai",
"given": "Jing"
},
{
"family": "Kfir",
"given": "Yoav"
},
{
"family": "Jamali",
"given": "Mohsen"
},
{
"family": "Huang",
"given": "Hesen"
},
{
"family": "Kim",
"given": "Young Joon"
},
{
"family": "Cash",
"given": "Sydney S"
},
{
"family": "Williams",
"given": "Ziv M"
}
],
"container-title-short":
"volume": "656",
"issue": "8127",
"page": "425-433",
"DOI": "10.1038/
"PMID": "42310453",
"PMCID": "PMC13468166",
"ISSN": "0028-0836",
"publisher": "Nature Portfolio",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
6,
17
]
]
}
}
The tracing map gets a citation of its own once an author has validated it and it has a DOI.
Similar papers
The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.
- [1] doi:10.1038/s41467-026-75745-8 [code]
- A language network in the individualized functional connectomes of 1199 human brains doing arbitrary tasks.Journal: Nature communicationsIn common: scikit-learn, pandas, SciPy, 2 other tools, cognitive, 12 references
- [2] doi:10.1038/s41586-026-10448-0 [code]
- Plasticity and language in the anaesthetized human hippocampus.Journal: NatureIn common: SciPy, Matplotlib, NumPy, cognitive, 3 references, 2 authors
- [3] doi:10.1038/s41586-026-10653-x [code]
- A mosaic of whole-body representations on the human precentral gyrus.Journal: NatureIn common: scikit-learn, SciPy, Matplotlib, 1 other tool, 3 references, 2 authors
- [4] doi:10.1038/s41467-026-75455-1 [code]
- Shared latent representations of speech production for cross-patient speech decoding.Journal: Nature communicationsIn common: statsmodels, scikit-learn, pandas, 3 other tools, cognitive, 7 references
- [5] doi:10.1126/sciadv.aec0518 [code]
- Hybrid spatial organization and evidence for magnitude-independent neural coding of linguistic information during sentence production.Journal: Science advancesIn common: 10 references
- [6] doi:10.1162/imag.a.1283 [code]
- The language network responds robustly to sentences across tasks.Journal: Imaging neuroscience (Cambridge, Mass.)In common: statsmodels, scikit-learn, pandas, 3 other tools, 7 references
- [7] doi:10.1038/s41467-026-72253-7 [code]
- Spurious alignment between large language models and brains can emerge from non-robust methods and overlooked confounds.Journal: Nature communicationsIn common: scikit-learn, pandas, SciPy, 2 other tools, 7 references
- [8] doi:10.7554/elife.109400 [code]
- High-fidelity neural speech reconstruction through an efficient acoustic-linguistic dual-pathway framework.Journal: eLifeIn common: SciPy, Matplotlib, NumPy, cognitive, 8 references
- [9] doi:10.1038/s41467-026-76598-x
- Preserved topography, lateralization, selectivity, and functional connectivity of the language network in older brains.Journal: Nature communicationsIn common: cognitive, 8 references
- [10] doi:10.1038/s41593-026-02258-4 [code]
- Laminar organization of cellular microcircuits modulating human interictal epileptiform discharges.Journal: Nature neuroscienceIn common: statsmodels, scikit-learn, pandas, 3 other tools, 5 references
Contribute
The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.
Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 1 repository of the authors' code, each at its verified commit and with its license, 22 scripts, and 16 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:6b0459ffe7f19f9e…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[.
Discussion, reproductions, activity
Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.
Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.
Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.
