如何分析实验数据?

⚠️ 正在开发中: 本指南正在积极开发中,将扩展更多详细示例和工作流程。内容可能在未来版本中更新。

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

预计阅读时间: 10 分钟


介绍

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

数据分析器提供工具来应用 CANN 启发的分析到实验数据,帮助您:

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

  • 将凸起模型拟合到群体活动

  • 对时间序列执行拓扑数据分析 (TDA)

  • 分析 RNN 不动点和缓慢流形

与模型分析的关键差异: 您从观察到的数据开始,而不是模拟输出。工作流从根本上是不同的。

实验数据分析工作流

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

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

让我们通过一个具体的例子来演练这个过程。

示例: 1D 凸起拟合

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

第 1 步: 加载示例数据

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

[ ]:
from canns.data import load_example_data

# 加载示例 1D 神经活动数据
data_dict = load_example_data('bump_1d_example')

print(f"可用键: {data_dict.keys()}")
print(f"活动形状: {data_dict['activity'].shape}")
print(f"时间点: {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

# 绘制活动热图
plt.figure(figsize=(10, 4))
plt.imshow(data_dict['activity'].T, aspect='auto', cmap='viridis')
plt.xlabel('时间步')
plt.ylabel('神经元索引')
plt.title('神经群体活动')
plt.colorbar(label='活动')
plt.show()

# 绘制一个时间点的活动
plt.figure(figsize=(8, 3))
plt.plot(data_dict['positions'], data_dict['activity'][100])
plt.xlabel('位置 (rad)')
plt.ylabel('活动')
plt.title('t=100 处的活动快照')
plt.grid(True)
plt.show()

要查找的内容:

  • 您是否看到局部活动凸起?

  • 它们随时间移动吗?

  • 有多个凸起还是只有一个?

第 3 步: 应用凸起拟合

现在使用数据分析器来拟合凸起模型:

[ ]:
from canns.analyzer.data import BumpAnalyzer1D

# 创建分析器
analyzer = BumpAnalyzer1D(positions=data_dict['positions'])

# 将凸起拟合到所有时间点
results = analyzer.fit_bumps(data_dict['activity'])

print(f"检测到的凸起中心: {results['centers'][:10]}")  # 前 10 个
print(f"凸起宽度: {results['widths'][:10]}")
print(f"凸起振幅: {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('时间 (ms)')
plt.ylabel('凸起位置 (rad)')
plt.title('解码凸起轨迹')
plt.grid(True)
plt.show()

# 绘制凸起宽度随时间的变化
plt.figure(figsize=(10, 4))
plt.plot(data_dict['time'], results['widths'], linewidth=2, color='orange')
plt.xlabel('时间 (ms)')
plt.ylabel('凸起宽度 (rad)')
plt.title('凸起宽度动力学')
plt.grid(True)
plt.show()

解释:

  • 稳定的凸起位置 → 稳定的吸引子状态

  • 光滑轨迹 → 连续跟踪

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

第 5 步: 验证拟合

检查拟合的质量:

[ ]:
# 绘制拟合质量随时间的变化
plt.figure(figsize=(10, 4))
plt.plot(data_dict['time'], results['fit_quality'], linewidth=2)
plt.axhline(y=0.8, color='r', linestyle='--', label='质量阈值')
plt.xlabel('时间 (ms)')
plt.ylabel('拟合质量 (R²)')
plt.title('凸起拟合质量')
plt.legend()
plt.grid(True)
plt.show()

# 识别低质量拟合
low_quality_indices = jnp.where(results['fit_quality'] < 0.8)[0]
print(f"拟合质量差的时间点: {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. 加载数据
data = load_example_data('bump_1d_example')

# 2. 创建分析器
analyzer = BumpAnalyzer1D(positions=data['positions'])

# 3. 拟合凸起
results = analyzer.fit_bumps(data['activity'])

# 4. 可视化轨迹
plt.figure(figsize=(12, 6))

# 子图 1: 活动热图及拟合中心叠加
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='拟合凸起中心')
plt.ylabel('位置 (rad)')
plt.title('带检测凸起轨迹的神经活动')
plt.legend()
plt.colorbar(label='活动')

# 子图 2: 凸起位置随时间的变化
plt.subplot(2, 1, 2)
plt.plot(data['time'], results['centers'], linewidth=2)
plt.xlabel('时间 (ms)')
plt.ylabel('凸起中心 (rad)')
plt.title('解码位置轨迹')
plt.grid(True)

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

print("分析完成!结果已保存。")

其他数据分析工具

除了凸起拟合,数据分析器还提供:

拓扑数据分析 (TDA)

[ ]:
from canns.analyzer.data import TopologyAnalyzer

# 分析神经动力学中的拓扑特征
tda = TopologyAnalyzer()
persistence = tda.compute_persistence(data['activity'])

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

RNN 动力学分析

[ ]:
from canns.analyzer.data import RNNAnalyzer

# 在训练的 RNN 模型中找到不动点和缓慢流形
rnn_analyzer = RNNAnalyzer(model=my_rnn)
fixed_points = rnn_analyzer.find_fixed_points()

用例: 理解训练递归网络的计算结构

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

方面

模型分析

实验数据分析

输入

模拟输出

神经记录,轨迹

控制

完全控制(参数,输入)

仅观察

目标

验证模型行为

发现数据中的模式

挑战

参数调节

噪声,缺失数据,伪影

工作流

模拟 → 分析

加载 → 预处理 → 分析

何时使用各种方法:

  • 模型分析: 测试假设,探索参数空间,验证实现

  • 数据分析: 解释实验,检测记录中的吸引子,比较模型与生物学

加载您自己的数据

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

[ ]:
import jax.numpy as jnp

# 从 numpy 数组,CSV 或其他格式加载
my_activity = jnp.load('my_experiment.npy')  # 形状: (time, neurons)
my_positions = jnp.linspace(-3.14, 3.14, num_neurons)

# 使用您的神经元位置创建分析器
analyzer = BumpAnalyzer1D(positions=my_positions)

# 分析
results = analyzer.fit_bumps(my_activity)

数据要求:

  • 活动应为 (time_points, num_neurons) 形状

  • 位置应匹配神经元数量

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

常见问题

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

在分析前进行预处理:

[ ]:
import jax.numpy as jnp

# 移除包含 NaN 的行
valid_indices = ~jnp.isnan(activity).any(axis=1)
clean_activity = activity[valid_indices]

问: 结果没有意义

检查这些:

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

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

  3. 活动形状((time, neurons) 而不是 (neurons, time)

问: 拟合质量总是很低

可能的原因:

  • 数据中没有清晰的凸起结构

  • 需要调整凸起模型参数

  • 数据太嘈杂(先尝试平滑)

后续步骤

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

  1. 训练脑启发模型 - 学习记忆网络的海布学习

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

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


快速参考:

[ ]:
# 实验数据分析模板
from canns.data import load_example_data
from canns.analyzer.data import BumpAnalyzer1D

# 加载数据
data = load_example_data('bump_1d_example')

# 分析
analyzer = BumpAnalyzer1D(positions=data['positions'])
results = analyzer.fit_bumps(data['activity'])

# 可视化
plt.plot(data['time'], results['centers'])

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

有问题?查看*`核心概念: 数据分析器 <link>`__*或*`GitHub Discussions <https://github.com/routhleck/canns/discussions>`__*。