def summarize_rec_data(data): """Return summary stats of recorded data.""" # Warning: not all collectible data has a summary stats implemented below! # See get_rec_stats() above! stats = {} if 'hc_ro' in data: # Entropy across HC units average over samples. hc_ro_arr = np.array(list(data['hc_ro'].values())) stats['H HC ro'] = utils.entropy(hc_ro_arr.T).mean() if 'vs_state' in data: # Sum of vS reward estimates change (from first to last sample). vs_state = data['vs_state'] stats['d vS'] = sum(vs_state[max(vs_state.keys())] - vs_state[0]) if 'co_occs' in data: # Mean entropy of real location and HC state co-occurance frequencies. co_occs = data['co_occs'][max(data['co_occs'].keys())] stats['H HC co'] = np.nanmean(get_hc_co_occ_entropy(co_occs)) stats['H loc co'] = np.nanmean(get_loc_co_occ_entropy(co_occs)) return stats
def record_learning(village, s, GS, HC, hc_ro, dVC_HC, dGS_HC, co_occs, norm): """Collect data from a single step of connectivity learning.""" # Animal's real and estimated position and location + uncertainty. x, y = village.animal_coords() gs_x, gs_y = analysis.GS_pos_mean(GS.P, GS.xvec, GS.yvec, GS.circular) gs_h = utils.entropy(GS.P.flatten()) hc_ml = HC.s_names[hc_ro.argmax()] hc_h = utils.entropy(hc_ro) # Entropy between real state and HC state during last n steps. s_real_h = get_loc_co_occ_entropy(co_occs) s_hc_h = get_hc_co_occ_entropy(co_occs) # Connectivity stats. vc_hc_snr = np.mean(np.abs(HC.VC_HC), 1) / np.std(np.abs(HC.VC_HC), 1) gs_hc_pos = analysis.GS_HC_conn_mean(HC.GS_HC, GS.xvec, GS.yvec, GS.circular) # Entropy calculation below takes a lot of time --> approximated by max. # gs_hc_h = utils.entropy(HC.GS_HC.reshape((len(HC.s_names), -1)).T) gs_hc_max = HC.GS_HC.max(axis=(1, 2)) # Connectivity change. dVC_HC_max = analysis.VC_HC_norm(dVC_HC, norm).max() dGS_HC_max = analysis.GS_HC_norm(dGS_HC, norm).max() # Compensate for the magnitude difference between VC and GS input (GS is a # PD, VC is not). dVC_HC_max /= dVC_HC.shape[1] res = {'s': s, 'x': x, 'y': y, 'gs_x': gs_x, 'gs_y': gs_y, 'gs_h': gs_h, 'hc_ro': hc_ro, 'hc_ml': hc_ml, 'hc_h': hc_h, 's_real_h': s_real_h, 's_hc_h': s_hc_h, 'vc_hc_snr': vc_hc_snr, 'gs_hc_pos': gs_hc_pos, 'gs_hc_max': gs_hc_max, 'dVC_HC_max': dVC_HC_max, 'dGS_HC_max': dGS_HC_max} return res
def format_GS_HC_rec(res, s_hc, GS_HC): """Format recordings of GS - HC connectivity.""" # GS - HC x-y mean position per HC unit. gs_hc_pos = pd.concat({i: pd.DataFrame(kv, index=['x', 'y'], columns=s_hc) for i, kv in res['gs_hc_pos'].items()}).unstack() # GS - HC entropy per HC unit. gs_hc_h = pd.Series([utils.entropy(gs_hc.flatten()) for gs_hc in GS_HC], index=s_hc) # GS - HC maximum value per HC unit. gs_hc_max = pd.Series([gs_hc.max() for gs_hc in GS_HC], index=s_hc) return gs_hc_pos, gs_hc_h, gs_hc_max
def GS_pos_estimate(gs_state, gs_circular): """ Return GS position estimate and inverse precision (entropy) over simulation time. """ # Init params and grouping. g = gs_state.groupby(level=0) xvec = np.array(gs_state.columns) yvec = np.sort(np.array(gs_state.index.get_level_values('y').unique())) # Weighted mean position estimate. mpos = g.apply(lambda x: GS_pos_mean(x, xvec, yvec, gs_circular)) mpos = pd.concat( {i: pd.Series(mp, index=['x', 'y']) for i, mp in mpos.items()}).unstack() # Inverse precision (entropy) of location estimate. H = g.apply(lambda x: utils.entropy(x.stack())) return mpos, H
def curious_exploration(GS, HC, village, u_list, mot_sig): """Return action determined by curiousity-drivent exploration.""" # TODO: remove dependence on village and make this part of an internal # PFC - MC - GS - HC loop. gs_p = GS.P.copy() # save current GS activity # Go through each action, roll GS, infer HC, check uncertainty (entropy). s_uncertain = {} for u in u_list: umot, emot, vmot = village.motor_feedback(u, mot_sig) GS.motor_update(umot) HC.grid_input(GS.P) s_uncertain[u] = utils.entropy(HC.s['GS']) GS.P = gs_p # restore original GS activity # Select action leading to maximally uncertain state. u_max_uncert = max(s_uncertain, key=s_uncertain.get) return u_max_uncert