如何分析实验数据?

Note

正在开发中: 本指南正在积极开发中,未来将通过更详细的示例和工作流程进行扩展。内容可能会在未来版本中更新。

目标: 学完本指南后,您将了解如何将 CANN 分析工具应用于实验神经数据。

预计阅读时间: 10 分钟

简介

上一指南展示了如何分析 模型生成的 数据。但如果您拥有 真实的实验记录 ——神经脉冲序列、行为轨迹或来自训练模型的 RNN 动力学,该怎么办?

数据分析器提供了将受 CANN 启发的分析应用于实验数据的工具,帮助您:

  • 在神经记录中检测类似吸引子的活动模式

  • 将波包模型拟合到群体活动

  • 对时间序列执行拓扑数据分析 (TDA) [15, 16]

  • 分析 RNN 的不动点和慢速流形

与模型分析的关键区别: 您从 观测数据 入手,而非仿真输出。其工作流程有着根本性的不同。

实验数据分析工作流

与您可以控制一切的模型仿真不同,分析实验数据遵循以下模式:

加载数据 → 预处理/格式化 → 应用分析 → 可视化结果

让我们通过一个具体示例来逐步讲解。

示例: 1D 波包拟合

最常见的分析是 波包拟合 ——在神经群体数据中检测和跟踪局部化的活动波包。

第 1 步: 加载示例数据

该库通过 canns.data 提供示例数据集:

[ ]:
from canns.data import load_example_data

# Load example 1D neural activity data
data_dict = load_example_data('bump_1d_example')

print(f"Available keys: {data_dict.keys()}")
print(f"Activity shape: {data_dict['activity'].shape}")
print(f"Time points: {data_dict['time'].shape}")

预期输出:

可用键: dict_keys(['activity', 'time', 'positions'])
活动形状: (500, 128)  # 500 个时间点,128 个神经元
时间点: (500,)

数据结构:

  • activity: 神经发放率或脉冲计数(时间 × 神经元)

  • time: 每个样本的时间戳

  • positions: 神经元的空间位置(如果可用)

第 2 步: 检查数据

在分析之前,先可视化原始数据:

[ ]:
import matplotlib.pyplot as plt
import jax.numpy as jnp  # :cite:p:`jax2018github`

# Plot activity heatmap
plt.figure(figsize=(10, 4))
plt.imshow(data_dict['activity'].T, aspect='auto', cmap='viridis')
plt.xlabel('Time step')
plt.ylabel('Neuron index')
plt.title('Neural Population Activity')
plt.colorbar(label='Activity')
plt.show()

# Plot activity at one time point
plt.figure(figsize=(8, 3))
plt.plot(data_dict['positions'], data_dict['activity'][100])
plt.xlabel('Position (rad)')
plt.ylabel('Activity')
plt.title('Activity snapshot at t=100')
plt.grid(True)
plt.show()

需要关注的内容:

  • 您是否能看到局部化的活动波包?

  • 它们是否随时间移动?

  • 是有多个波包还是只有一个?

第 3 步: 应用波包拟合

现在使用数据分析器来拟合波包模型:

[ ]:
from canns.analyzer.data import BumpAnalyzer1D

# Create analyzer
analyzer = BumpAnalyzer1D(positions=data_dict['positions'])

# Fit bumps to all time points
results = analyzer.fit_bumps(data_dict['activity'])

print(f"Detected bump centers: {results['centers'][:10]}")  # First 10
print(f"Bump widths: {results['widths'][:10]}")
print(f"Bump amplitudes: {results['amplitudes'][:10]}")

结果字典包含:

  • centers: 每个时间点的估计波包中心位置

  • widths: 波包宽度(空间扩散范围)

  • amplitudes: 波包峰值高度

  • fit_quality: R² 或拟合优度指标

第 4 步: 可视化拟合的波包

绘制检测到的波包轨迹:

[ ]:
plt.figure(figsize=(10, 4))
plt.plot(data_dict['time'], results['centers'], linewidth=2)
plt.xlabel('Time (ms)')
plt.ylabel('Bump Position (rad)')
plt.title('Decoded Bump Trajectory')
plt.grid(True)
plt.show()

# Plot bump width over time
plt.figure(figsize=(10, 4))
plt.plot(data_dict['time'], results['widths'], linewidth=2, color='orange')
plt.xlabel('Time (ms)')
plt.ylabel('Bump Width (rad)')
plt.title('Bump Width Dynamics')
plt.grid(True)
plt.show()

解读:

  • 稳定的波包位置 → 稳定的吸引子状态

  • 平滑的轨迹 → 连续跟踪

  • 变化的宽度 → 动态调谐或状态转换

第 5 步: 验证拟合

检查拟合的质量:

[ ]:
# Plot fit quality over time
plt.figure(figsize=(10, 4))
plt.plot(data_dict['time'], results['fit_quality'], linewidth=2)
plt.axhline(y=0.8, color='r', linestyle='--', label='Quality threshold')
plt.xlabel('Time (ms)')
plt.ylabel('Fit Quality (R²)')
plt.title('Bump Fit Quality')
plt.legend()
plt.grid(True)
plt.show()

# Identify low-quality fits
low_quality_indices = jnp.where(results['fit_quality'] < 0.8)[0]
print(f"Time points with poor fits: {len(low_quality_indices)} / {len(data_dict['time'])}")

低质量的拟合可能表明:

  • 不存在清晰的波包

  • 多个重叠的波包

  • 数据有噪声或不可靠

完整工作流示例

以下是完整的流程:

[ ]:
from canns.data import load_example_data
from canns.analyzer.data import BumpAnalyzer1D
import matplotlib.pyplot as plt

# 1. Load data
data = load_example_data('bump_1d_example')

# 2. Create analyzer
analyzer = BumpAnalyzer1D(positions=data['positions'])

# 3. Fit bumps
results = analyzer.fit_bumps(data['activity'])

# 4. Visualize trajectory
plt.figure(figsize=(12, 6))

# Subplot 1: Activity heatmap with fitted centers overlaid
plt.subplot(2, 1, 1)
plt.imshow(data['activity'].T, aspect='auto', cmap='viridis', extent=[0, len(data['time']), data['positions'][0], data['positions'][-1]])
plt.plot(range(len(results['centers'])), results['centers'], 'r-', linewidth=2, label='Fitted bump center')
plt.ylabel('Position (rad)')
plt.title('Neural Activity with Detected Bump Trajectory')
plt.legend()
plt.colorbar(label='Activity')

# Subplot 2: Bump position over time
plt.subplot(2, 1, 2)
plt.plot(data['time'], results['centers'], linewidth=2)
plt.xlabel('Time (ms)')
plt.ylabel('Bump Center (rad)')
plt.title('Decoded Position Trajectory')
plt.grid(True)

plt.tight_layout()
plt.savefig('experimental_bump_analysis.png', dpi=150)
plt.show()

print("Analysis complete! Results saved.")

其他数据分析工具

除了波包拟合,数据分析器还提供:

拓扑数据分析 (TDA)

[ ]:
from canns.analyzer.data import TopologyAnalyzer

# Analyze topological features in neural dynamics
tda = TopologyAnalyzer()
persistence = tda.compute_persistence(data['activity'])

用例: 检测高维活动中的环形或环面结构

RNN 动力学分析

[ ]:
from canns.analyzer.data import RNNAnalyzer

# Find fixed points :cite:p:`sussillo2013opening,golub2018fixedpointfinder` and slow manifolds in trained RNN models
rnn_analyzer = RNNAnalyzer(model=my_rnn)
fixed_points = rnn_analyzer.find_fixed_points()

用例: 理解训练好的循环网络的计算结构

关键差异: 模型分析 vs. 实验数据分析

方面

模型分析

实验数据分析

输入

仿真输出

神经记录、轨迹

控制

完全控制(参数、输入)

仅观察

目标

验证模型行为

发现数据中的模式

挑战

参数调优

噪声、缺失数据、伪影

工作流

仿真 → 分析

加载 → 预处理 → 分析

何时使用:

  • 模型分析: 检验假设、探索参数空间、验证实现

  • 数据分析: 解读实验、在记录中检测吸引子、将模型与生物学进行比较

加载您自己的数据

要分析您自己的实验数据:

[ ]:
import jax.numpy as jnp  # :cite:p:`jax2018github`

# Load from numpy array, CSV, or other format
my_activity = jnp.load('my_experiment.npy')  # Shape: (time, neurons)
my_positions = jnp.linspace(-3.14, 3.14, num_neurons)

# Create analyzer with your neuron positions
analyzer = BumpAnalyzer1D(positions=my_positions)

# Analyze
results = analyzer.fit_bumps(my_activity)

数据要求:

  • 活动数据的形状应为 (时间点数, 神经元数)

  • 位置数据应与神经元数量匹配

  • 值应为非负数(发放率或脉冲计数)

常见问题

问: 我的数据有缺失值或 NaN

在分析前进行预处理:

[ ]:
import jax.numpy as jnp  # :cite:p:`jax2018github`

# Remove NaN rows
valid_indices = ~jnp.isnan(activity).any(axis=1)
clean_activity = activity[valid_indices]

问: 结果不合理

请检查以下几点:

  1. 数据单位(发放率是以 Hz 为单位还是归一化的?)

  2. 位置范围(应与神经元布局匹配,例如角度范围为 -π 到 π)

  3. 活动数据的形状(应为 (时间, 神经元) 而非 (神经元, 时间)

问: 拟合质量总是很低

可能的原因:

  • 数据中没有清晰的波包结构

  • 需要调整波包模型参数

  • 数据噪声过大(请先尝试平滑处理)

后续步骤

现在您可以分析实验数据了!继续学习:

  1. 训练脑启发模型——学习用于记忆网络的 Hebbian 训练

  2. 核心概念:数据分析器——深入了解分析方法

  3. 完整 API 参考:数据分析器——所有分析工具的完整文档

Note

欢迎反馈: 本指南正在积极完善中。如果您有此处未涵盖的实验数据分析用例,请在 GitHub Discussions 中分享!

如有疑问?请查看”核心概念:数据分析器”或访问 GitHub Discussions