CSYS5030 Week 06 Information-theoretic Estimators 讲课总结

CSYS5030 Week 06 讲课总结:Information-theoretic Estimators

课程:CSYS5030 — Information Theory and Self-Organisation 讲师:Associate Professor Joseph Lizier 对应模块:Module 6 - Information-theoretic estimators(Contents: Estimators for information-theoretic measures on continuous-valued variables) 来源:Week 06 seminar 字幕 + Canvas Module 6 页面(含 sample solution 图) Tutorial 覆盖:Items 3、7、8(A、B 部分);Item 5 在 lecture 里讲(Item 7 在 lecture 末尾开头);Item 8C 挪到 Week 7 做

这周是第二板块的理论核心。老师明确说这周会比平时花多得多的时间展开视频里没讲深的部分——尤其是 differential entropy 的推导。本周目标:理解几种估计器类型,并能通过 JIDT AutoAnalyser 使用、扩展它们的代码。 这周活动非常满,老师自己也说「你们大概做不完」,可以去第二个 tutorial 继续做。


零、Admin:作业时间线(重要)

事项 时间 说明
Optional calculation exercises 已截止,sample solutions 周一已发布 不计分,但是考试的重要练习——tutorial 偏计算,这份偏概念与手算。老师下周会留时间讲解(lecture 还是 tutorial 待定),先自己做、找出看不懂的地方
Project Proposal(20%) 9 月 30 日;用 simple extension 则 10 月 5 日 本周刚开放。先读 Stage 2(presentation)的要求再写 proposal,因为 proposal 要为最终项目铺路
Project Presentation(40%) 11 月 8 日(Week 13 末) 视频提交到专属讨论区——这些讨论区还没建好,不用慌

老师关于 proposal 的几条「规矩」:

  • 通用问题发 discussion forum,不要发邮件;只有非常个人化、没人关心的问题才走邮件。提问前先搜论坛,重复提问「不会得到友好回复」。
  • proposal 之前不提供个人化反馈——proposal 本身就是给反馈的环节。
  • 问题要具体:「我能不能用 X 方法做 Y?」可以;「这个数据集合不合适?」「我的项目做 X 行不行?」这种泛泛的评估不回答。
  • 老师顺带吐槽:calculation exercises 不再正式打分,因为「现在整份丢给 Copilot 就做完了」——练它的意义是把概念真正搞懂,考试时用得出来。

一、Bias 与 Variance:正式定义

前几周一直在「暗示」这个概念(老师原话:we have hinted the hell out of these),这周正式定义。

核心认知:从样本算出来的是「估计」,不是「计算」

回顾前四周自建工具库的结构,每个度量都写了两个函数:

输入 做的事 性质
概率分布表 直接代公式 计算(接受概率表就是真的)
一组样本 先数出概率表,再代公式 估计(样本概率本身就是估计)

例子(抛 10 次硬币):理论上熵是 1 bit,但 10 次可能得到 6:4 或 7:3,算出来就不是 1 bit。

定义

  • Bias:在固定样本量 下,估计值的期望与真值之差。取决于估计器类型和样本数——样本越多,bias 越小。
  • Variance:给你 10 个样本、再 10 个、再 10 个……每组分别估计,估计值在这些同样大小的样本集之间波动多大。

理想估计器:低 bias + 低 variance。现实里两者都有,好的估计器两者都更少。

典型偏差方向

量 有限样本下通常
Entropy 低估(underestimate)
Mutual Information 高估(overestimate)

⚠️ 不是绝对的。老师特意提到:之前 tutorial 里「硬币 + 它的拷贝」算 MI,结果是低估。「MI 通常高估」说的是现实中大多数关系都是弱关系,弱关系在有限数据下容易被高估。


二、离散数据的估计器:Plug-in / Maximum Likelihood

我们前四周一直在用的就是它,这周正式命名:

  • 数每个符号出现次数,,直接插进熵/互信息公式 → plug-in estimator
  • 给定这批样本,这样算出的值是最可能的值 → 也叫 maximum likelihood estimator

偏差可以修正。上周有同学问到的 Miller–Madow 修正:plug-in 熵估计的偏差有解析近似,

即把已知的(负)偏差加回去。

  • JIDT 目前没有内置这个修正——老师说 JIDT 里有的功能都是他自己最常用的,这个很好加,但他「没时间了」。
  • 离散数据还有很多更高级的方法(比如各种 Bayesian 技术),但本课不深入,尽快转向连续值数据——因为真实世界数据大多是连续的(EEG / MEG / fMRI 测的脑区活动都是连续值,不是 0/1、不是 0–4)。

三、连续值数据:最简单的做法——Binning(离散化)

做法:在 、 各自的取值范围上画网格,每个区间给一个标签(0、1、2……),把每个数据点变成离散符号,然后直接用离散估计器。

  • 可以等宽分箱(JIDT 默认:比如 0–100 均分)
  • 也可以 max-entropy binning(让每个箱里样本数大致相等,比如 100 个样本分 4 箱,每箱约 25 个)——JIDT 能做但没有下拉选项,要问老师怎么设

JIDT 操作:AutoAnalyser 里选 Binned 估计器,这时参数的含义变了——之前 base 是告诉 JIDT「数据已经是几进制」,现在是告诉它「你想把每个变量离散成几个符号」。生成的代码里会多出一段 Python 离散化代码,然后照常计算。

Binning 的问题

  1. 对分箱方式敏感,对箱数敏感——3 个?4 个?5 个?答案会随之变化,而且没有标准答案。
  2. 丢失细节:两个在联合空间里明明挨得很近的点,若恰好落在分界线两侧,会被当成完全不同;而同一个箱里相距较远的两个点却被当成完全相同。

这是能做的最简单的事,能用,但不是最好的。要正确处理连续值,需要 differential entropy。


四、Differential Entropy(本周理论重点)

定义

和离散熵长得很像:求和变积分,概率质量函数(PMF)变概率密度函数(PDF)。

4.1 先复习:概率密度函数(PDF)是什么

  • 连续变量没有「符号」,问 没有意义。
  • 有意义的问题是:落在某个区间里的概率,比如随机数落在 之间:

  • PDF 是「单位变量长度上的概率质量」。前四周离散变量用的全部是 PMF。
  • 如果非要谈「某个点附近」的概率,就取一个宽度 的小区间:

两边除以 ,就是「密度 = 单位长度上的概率质量」的含义。

4.2 推导:离散化后取极限,会发生什么

把连续变量切成宽度为 的小块,每块当一个符号,算普通 Shannon 熵:

代入:

  • 第二项里 对求和是常数,提出来;剩下的 在 时就是整条密度曲线下的面积 = 1。
  • 第一项在 时,,求和变积分,正是 。

于是:

即

4.3 怎么理解这个结果

这一项会发散: 时 ,前面的负号使它 ,所以离散化熵本身在极限下趋于无穷。

这其实是合理的:一个真正的实数(不是计算机里 16 位浮点那种有限精度的数),可以被指定到任意精度,本来就包含无穷多的不确定性。只是这个无穷大「合理但没用」。

两种理解 differential entropy 的方式:

  1. 它是 Shannon 熵在极限下「不发散」的那部分。
  2. (老师更推荐)它的价值在于「比较」:两个分布的离散化熵相减时, 完全抵消,所以

「我对变量 1 的随机抽样比变量 2 多多少不确定性?」——直接比较 differential entropy 就能正确回答。

课上有同学问:它是不是只在比较时有用?老师:「一般来说是的——我不想说这是唯一用处,但对我来说,基本上就是唯一用处。用于比较,单独看不太有意义。」

4.4 Differential entropy 的「怪」性质

操作 结果 是否符合直觉
平移 ✅ 合理:平移不改变对抽样的不确定性
缩放 部分合理:拉伸分布 → 可能取值更多 → 更不确定
缩得足够小() , 可以变成负数 ❌ 很怪:「负的不确定性」是什么意思?

解释:还是回到「比较」——负值只意味着「比另一个 differential entropy 更大的分布,不确定性更少」。

另一个参照点:

所以任何分布的 differential entropy 都可以理解为「它的不确定性相对于 上均匀分布的差值」。

4.5 好消息:互信息在连续变量上「一切照旧」

之前所有的量都能写成熵的和与差:

做和与差时,发散项全部抵消(联合熵那边会出现 之类的项,但同样会消掉)。因此:

  1. 连续变量的 MI、CMI、条件熵,形式与离散版完全一样,只是熵换成 differential entropy。
  2. MI 仍然非负——不像 differential entropy 本身会出现负值。
  3. MI 对缩放不变——缩放只是一个一一映射,不改变两者共享的信息。
  4. 用 differential entropy 算出的 MI,正好等于「离散化后令 取极限」得到的 MI。

老师反复强调的主线:互信息比熵有用得多。熵只是通往互信息的手段,这一点在连续变量上更加明显——我们关心的大多数问题都是变量之间的关系,而这可以沿用离散变量上完全相同的直觉。


五、三种连续值 MI 估计器总览

关键问题:如何估计底层的概率密度函数(有时会走捷径绕开它)。JIDT 里重点讲三种(不是全部,比如还有新兴的神经网络估计器,本课不涉及):

估计器 思路 优点 缺点 输出单位
Linear-Gaussian 假设数据是多元高斯 快;模型对时极准;数据需求少 只能捕捉线性关系;模型错则估计错 nats
Box Kernel 固定半径 的邻域计数估密度 model-free,能捕捉非线性 对 极度敏感; 太小严重偏差;慢 bits(例外)
KSG (Kraskov) 动态邻域宽度 + digamma 偏差修正 非线性 + 偏差修正 + 对参数稳定,「best of breed」 比 Gaussian 慢;可能输出负值 nats

六、估计器 1:Linear-Gaussian 模型

原理

假设 ( 维)服从多元高斯,则 differential entropy 有闭式解:

其中 是协方差矩阵的行列式。一旦假定高斯,协方差矩阵就包含了分布的全部信息。

直观图像:单变量是熟悉的钟形曲线;两个相关变量的样本散点会沿一条斜线拉长,联合密度是一个被拉伸的二维高斯。

Model-based 估计器的本质

模型对,估计极好;模型错,估计出错;模型错得越多,估计越差。

用在 MI 上时,它实际在问:「如果这是一个均值、方差都与数据相同的线性高斯关系,MI 会是多少?」所以:

  • 只检测到交互的线性分量
  • 对 MI:Gaussian 估计值是真实 MI 的下界(可证明,超出本课范围)
  • 对 CMI:不一定是下界,情况更复杂

Item 3 推导:高斯变量的 MI 与相关系数

设 为高斯变量,方差 ,相关系数 。

Step 1:边际熵

Step 2:协方差矩阵(用 )

Step 3:联合熵()

Step 4:代入 , 全部抵消:

这个结果的几点解读

  1. 与相关系数的符号无关: 和 给出相同的 MI。 信息论上完全合理——相关为负时,知道 照样能同样好地预测 ,只是预测方向反过来。信息论是「无语义」(semantic free)的:它只衡量关系有多强,不告诉你关系是什么。需要符号的话可以回到底层概率分布去看。

  2. 即使关系是线性的,MI 也比相关系数多做了事:

    • 能推广到多变量 、(用更高阶的协方差矩阵),相关系数基本只处理两两关系;
    • MI 有链式法则,相关系数没有。
  3. 时 MI :,。 合理:完全相关意味着知道 就能精确知道 ,而精确确定一个实数需要无穷多信息。

    ⚠️ 实战警示:在真实数据里如果看到 MI 爆到无穷大,通常意味着出错了——比如某一列被复制了。

JIDT 演示

数据:2coupledRandomCols-1.txt(第 1 列是第 0 列高斯变量的带噪声滞后拷贝)

设置 结果
Gaussian,TIME_DIFF = 0 0.0219 nats
Gaussian,TIME_DIFF = 1 0.37 nats

(老师演示时先选错成 2randomCols,得不到预期值——注意文件名是 coupled。)

  • Gaussian 估计器现在在 entropy、conditional entropy、MI、CMI 的 AutoAnalyser 里都可用。
  • 鼠标悬停在属性名上可以看说明。
  • 想知道某个属性在代码里插在哪:改一下它,重新生成,看代码哪里变了——通常在一个 set properties 的代码块里。

单位惯例

离散变量惯用 bits(),连续变量惯用 nats()——老师说「很怪,但就是惯例」。忘了就看 AutoAnalyser 输出,它会写明单位,报告时照着写。

换算:,所以 (老师课上心算说「大约 0.55 或 0.6 bits」,精确值约 0.53)。


七、连续值估计器的代码使用范式(Part 3 视频要点)

AutoAnalyser 会帮你生成,但扩展代码时需要知道这些变化:

  1. 数据类型:连续值变量在 Java 端是 double,Python 里 numpy 数组是浮点数,转换到 Java 也按 double 处理。
  2. 属性(properties)变得更重要,并且总是以字符串形式设置和读取:calc.setProperty("KERNEL_WIDTH", str(width))。
  3. 属性只有在调用 initialise() 时才真正生效 ⟹ 改完属性必须重新 initialise()。 循环复用 calculator 的正确结构:构造对象一次 → 循环内:setProperty → initialise → 设数据 → compute。
  4. 设数据:AutoAnalyser 对连续估计器生成的是 setObservations()(只有一组数据时用)。有多组数据时:先告诉它准备接收多组(startAddObservations()),逐组 addObservations(),最后告诉它结束(finaliseAddObservations())。
  5. 默认参数不会出现在生成的代码里。想看某个参数的占位代码,先把它改成非默认值再生成(老师演示:把 kernel width 改成 0.4,代码里就出现了对应的 setProperty 行)。
  6. 所有估计器都支持多变量,只是 tutorial 基本只用单变量。想做多变量→单变量的 MI,tutorial 上问助教。
  7. 本周不提供 notebook,建议试试用普通 Python 脚本跑(换种体验);脚本里画图要加 plt.show()。

八、估计器 2:Box Kernel 估计器

老师开宗明义:Kernel 估计器只是「过渡工具」。AutoAnalyser 里有,但我们不会一直用它——要先理解它,才能理解后面更高级的 KSG。它是超越线性模型的第一步。

原理

对每个样本点 ,估计它周围半径 内的概率质量:

即「 个样本里有多少个落在 的半径 内」, 是阶跃函数。除以区间大小变成密度:一维除以 ,二维联合空间除以 。

老师提到讲义这页有两处错:分母应该是 ,前面还少了一个负号。论坛上有人指出了,他还没来得及改。

熵的估计:外面的 不再显式出现,而是对所有样本点取平均:

原理:原公式 是对符号按 加权求和,等价于对样本求和再乘 (样本本身就按 出现)。老师说这是个支线细节,可以看参考资料说服自己。

MI 估计( 的因子会抵消):

几何图像

对每个样本点,逐个看:

  • :数落在竖条带( 方向宽 )里的点
  • :数落在横条带( 方向宽 )里的点
  • :数落在方盒()里的点

它在问的问题:知道 (精确到半径 内)能多大程度帮助预测 (精确到半径 内)?

本质上是一种离散化——但是动态的离散化:以每个数据点为中心,而不是固定网格。

优缺点

  • ✅ Model-free:能捕捉非线性关系(比如 U 形分布,线性模型完全抓不到)
  • ❌ 对 非常敏感
  • ❌ 太小或样本太少时严重偏差
  • ❌ 运行慢得多

JIDT 参数

  • KERNEL_WIDTH:盒子半径 ,默认 0.25
  • NORMALISE:默认开启,把每个变量标准化为均值 0、标准差 1,所以 kernel width 的单位是「标准化单位」。好处:多变量中方差差异很大时,把它们放到同一尺度。(原理上缩放不影响 MI 真值。)

Item 5 结果:Kernel width 扫描

Step 1:Kernel,TIME_DIFF = 1,KERNEL_WIDTH = 0.25(默认)→ 结果约 1 bit(注意 kernel 输出是 bits)。 真值参考:Gaussian 给出 0.37 nats ≈ 0.53 bits,kernel 结果高出将近一倍。

为什么不同? 同学们说对了两点——对参数敏感、依赖于参数设置;老师要引出的关键词是 bias。 > 一般而言,kernel 值更大也可能是真的(存在非线性关系)。但这个数据集确定是线性高斯关系,真值就在 0.53 bits 左右,所以高出的部分就是偏差。

Step 2:kernel width 从 0.1 扫到 1.0,步长 0.05。

老师的代码改法(写循环):

import numpy as np
# ... 前面是 JVM 启动、读数据、构造 calc 对象(只做一次)
for width in np.arange(0.1, 1.05, 0.05):
calc.setProperty("KERNEL_WIDTH", str(width)) # 属性必须转成字符串
calc.initialise() # 改属性后必须重新 initialise
calc.setObservations(source, destination)
result = calc.computeAverageLocalOfObservations()
print("Kernel width %.2f: MI = %.4f bits" % (width, result))

Sample solution 图的趋势(MI in bits vs kernel width):

Kernel width 0.1 0.15 0.25 0.4 0.55–0.65 1.0
MI(bits,读图约值) ~1.95 ~1.45 ~1.0 ~0.75 ~0.55(≈真值) ~0.4

单调下降,没有平台期。

解读:估计器在问的问题随参数改变

估计器问的问题永远取决于它的参数:「知道 在 kernel width 内,能提供多少关于 在 kernel width 内的信息?」

  • width 太小 → 每个盒子里点太少,欠采样 → bias 急剧上升,严重高估
  • width 逐渐增大 → 欠采样缓解
  • width 太大 → 分辨率太粗,看不到分布的细节 → 开始低估
  • 只有中间某个宽度大致碰对真值——但你事先不知道是哪个,没有一个「显然该用」的宽度

九、估计器 3:KSG(Kraskov–Stögbauer–Grassberger)估计器

又叫 Kraskov 估计器 或 nearest-neighbour 估计器。

它解决什么问题

Kernel 估计器卡在两难之间: 太小 → 欠采样/偏差; 太大 → 丢细节,而且不知道该设多少。

KSG 的解法:不再对所有点用同一个固定宽度,而是根据每个点周围的样本密度,动态设置盒子宽度。

原理

参数不再是宽度,而是 近邻数 :

  1. 对每个点,在联合空间 里找它的第 个最近邻,以此确定盒子大小(距离一般用 max-norm)。
    • 比如 :这个点的两个最近邻很近,盒子就小;另一个点的两个最近邻很远,盒子就大。
  2. 联合空间里永远正好 个邻居;然后看这个宽度下,边际空间 、 里分别有多少邻居 、——这个数会变。
  3. 把邻居数代入 digamma 函数 ,得到带偏差修正的 MI。

标准形式(Kraskov et al., 2004):

其中 表示对所有样本点平均。

为什么用 digamma:老师没展开数学,只说——已知基于近邻计数估计 log 概率时,log 概率的期望值正好是这些 digamma 值的函数,由此提供了比 kernel 估计器更好的偏差修正。细节看视频(Module 页面还链接了他以前学生 Leonardo Novelli 做的交互演示,需要 Mathematica 或 Wolfram CDF Player)。

动态宽度的好处

  • 数据稀疏的区域:不会放大得太细,分辨率自动匹配数据量(通常取 避免欠采样)
  • 数据密集的区域:可以放大,捕捉关系里的细节

两种算法

Bias Variance 适用
Algorithm 1 较大 较小 需要一致性、便于和其他值比较
Algorithm 2 较小 较大 需要更接近真值(本课默认用它)

两者都很好,差别不大。

优缺点

  • ✅ 内置偏差修正
  • ✅ 捕捉非线性
  • ✅ 对参数更稳定(「much more parameter free」)——减少了人为选择
  • ✅ 总体是 best of breed
  • ❌ 比 Gaussian 慢(比 kernel 也慢一些,虽然 JIDT 里有快速近邻搜索)

JIDT 演示

  • 选 Kraskov (KSG) alg. 2,参数 k 默认 4,一般保持不变。
  • 2coupledRandomCols-1,TIME_DIFF = 1 → 结果比 kernel 接近 Gaussian 的 0.37 nats 多得多(sample solution 图上 k=4 约 0.42 nats)——因为有偏差修正。
  • 每次点 Compute 结果会略有不同:JIDT 为保持 KSG 数值稳定,会给数据加一点随机噪声。

⚠️ KSG 可以输出负的 MI

演示:同一数据集,TIME_DIFF = 0 → −0.05 nats。

不代表答案错了。 来源是偏差修正:修正的目标是让变量间无关系时,估计值的期望为 0。但被移到 0 的是期望,单次估计仍然会在 0 附近波动。 MI 理论上不能为负——但我们拿到的是估计值,负值只是在真值附近的波动,不是说平均得到了 misinformation。 看到负值,就理解为「与 0 一致」(consistent with 0)——具体什么叫「与 0 一致」,下周统计显著性会讲。

Item 7 结果:k 的参数扫描

k 从 4 扫到 15(同样要 setProperty 后 initialise)。

Sample solution 图的趋势(MI in nats vs k):

k 4 5 6 7–9 10–12 13 15
MI(nats,读图约值) ~0.42 ~0.42 ~0.40 ~0.38 ~0.34 ~0.32 ~0.31
  • 变化幅度远小于 kernel(kernel 在 0.1–1.0 之间差了近 5 倍;KSG 在 4–15 之间只差约 25%),对参数稳定得多。
  • 越大 → 盒子越大 → 分辨率越粗,和 kernel width 增大一样,缓慢地低估。
  • 这验证了讲义里「k=4 是好的默认值」的建议:足够大避免欠采样,又足够小保留细节。

Item 7 的思考题:已知数据是线性耦合的高斯变量,哪个估计器最好?——Gaussian。模型正确时,model-based 估计器最准、最快、最省数据。


十、用 Gaussian + KSG 组合解读关系类型(四象限框架)

这是老师在课末补充的一个分析实践框架(他说以后要加进讲义,目前只在录像里)。

做法:对同一数据集同时跑 Gaussian 和 KSG 两个估计器,按结果组合解读:

KSG ≈ 0 KSG > 0
Gaussian ≈ 0 ① 没有关系,或关系太弱、以现有样本量测不出来 ② 只有非线性关系
Gaussian > 0 ④ 有线性关系,但 KSG 数据不够还「没追上」;非线性分量要么不存在,要么太弱暂时测不到 ③ 有线性关系;若 KSG > Gaussian,差值来自非线性分量

逐条说明

  • ①:得到 0 不等于没有关系,只是现有数据里证据不够。下周会看到:关系越弱,需要越多样本才能可靠检测。

  • ②:线性估计器看不到,非线性估计器看到了 → 非线性关系的证据。

  • ③:两者都 > 0,KSG 更大的那部分就是非线性贡献。

  • ④(最反直觉):之前说 Gaussian 估计是 MI 的下界,怎么会 Gaussian 测到了、KSG 反而测不到?

    原因:model-based 估计器能非常快地「锁定」符合其模型的关系;model-free 估计器要考虑所有类型的关系,需要更多数据才能以同样精度识别出线性关系,而且因为大力做偏差修正,它很保守。 结论:可以确定有线性关系;KSG 看不到只是数据还不够让它「up to speed」,不说明出了问题。


十一、Item 8:心跳-呼吸交互分析(A、B 部分)

数据:demos/data/SFI-heartRate_breathVol_bloodOx-extract.txt——一位睡眠呼吸暂停患者睡眠时的数据,三列分别是心率、胸腔容积(呼吸)、血氧浓度。画出心率时序图,能看到心率剧烈升降的地方就是呼吸暂停事件。

研究问题:心率与呼吸之间有没有关系?

A. Linear-Gaussian 估计器

  • source = 第 0 列(心率),destination = 第 1 列(呼吸),Compute → 结果单位 nats
  • 用散点图验证:plt.scatter(data[:,0], data[:,1], c='red', marker='x')
  • 扫描 TIME_DIFF 0–15,找滞后关系

Sample solution 图(MI Gaussian vs time delay):纵轴量级是 nats——

  • lag 1 附近一个峰 ≈ 0.0033 nats
  • lag 9–10 附近第二个峰 ≈ 0.0028 nats
  • 其余多数 lag 几乎为 0

所有值都在千分之几 nats 量级,几乎就是 0。线性估计器的结论:基本看不到线性关系。 题目追问:「能否得出变量之间完全没有关系?」——不能,线性估计器只能说明没有线性关系。

B. KSG 估计器

  • 选 KSG alg. 2,TIME_DIFF 改回 0,k = 4
  • 注意速度:短数据集上可能感觉不出;在完整版 SFI-heartRate_breathVol_bloodOx.txt 上两个估计器都跑一下对比
  • 把生成的代码存成脚本,Part C(Week 7)要在上面扩展

对比结果(结合 Part C sample solution 图,KSG 在 lag 0 约 0.13 nats,lag 0–15 大致在 0.08–0.145 nats 之间波动):

KSG 比 Gaussian 高出约两个数量级 → 落在四象限的 ② 区:Gaussian ≈ 0、KSG > 0 ⟹ 心率与呼吸之间存在非线性关系。 回头再看散点图,并加上非零滞后的散点图——能不能找出心率的哪些区间提供了关于呼吸的信息?

C. Pointwise MI 与滞后分析(Week 7 做,先预览)

JIDT 里算每个样本的局部(pointwise)MI——AutoAnalyser 不会生成这段,需要在设置 observations 之后手动加:

localMIs = calc.computeLocalOfPreviousObservations()  # 每个样本的 local MI
import matplotlib.pyplot as plt
plt.figure()
plt.scatter(data[:,0], data[:,1], c=localMIs, marker='o', s=8)
plt.title('Heart-breath samples (lag 0) coloured by local MI')
plt.xlabel('Heart rate'); plt.ylabel('Breath rate')
plt.colorbar(label='Local MI (nats)')
plt.show()

Sample solution 图的观察:lag 0 散点里,高 local MI(黄色)集中在心率较高(约 85–92)的区域,对应呼吸值偏离中心的点;KSG MI 随滞后扫描的最大值在 lag 7 附近(约 0.144 nats)。

留给 Week 7 的问题:MI 在好几个 TIME_DIFF 上都很大,意味着什么?这些更早的心率值提供的是相同还是不同的信息?(可选扩展:用多变量 MI 或条件互信息来研究——正好呼应 Week 4 的冗余/协同。)


十二、参考阅读(非必读)

主题 来源(从简到深)
Differential entropy Lizier (JIDT) Appendix A.4 → Bossomaier et al. §2.5.3、§3.2.5(3.2.5.1 之前)→ Cover & Thomas Ch. 8(最全面)
信息论估计器 Lizier (JIDT) Appendix A.4 → Bossomaier et al. §3.2.5(3.2.5.1 起)与 §3.4

Module 页面提示:估计器技术的阅读,对理解文献综述里别人论文用的方法会有帮助。


十三、考点重点

  1. Bias ,取决于估计器类型 + 样本数;Variance 是同样大小样本集之间的波动。熵通常低估,MI 通常高估(弱关系),但不绝对。
  2. Plug-in = maximum likelihood estimator;Miller–Madow 修正 。
  3. Binning 的问题:对箱数/分箱方式敏感,丢失联合空间里的邻近关系。
  4. Differential entropy ;推导 , 发散,所以 只在比较时有意义。
  5. 性质:平移不变;;可以为负; 的 (可作参照)。
  6. MI 由熵的和差构成,发散项抵消 ⟹ 连续 MI 非负、缩放不变、等于离散化取极限的结果。
  7. 高斯熵 ;必会推导 。
    • 与 符号无关(信息论 semantic free)
    • 时 MI (实战中通常意味着列被复制之类的错误)
    • 比相关系数强:可推广到多变量、有链式法则
  8. Gaussian 估计器只抓线性分量;对 MI 是下界,对 CMI 不一定。
  9. Kernel 估计器:固定半径邻域计数,model-free,对 极敏感; 小 → 欠采样高估, 大 → 丢细节低估。
  10. KSG:动态宽度(第 近邻)+ digamma 偏差修正,对 稳定,默认 ;Alg.1 方差小偏差大,Alg.2 偏差小方差大(默认);可输出负值 = 与 0 一致。
  11. 单位:离散 bits,连续 nats;JIDT kernel 估计器是例外(bits)。
  12. 四象限框架:同时跑 Gaussian + KSG;Gaussian > 0 而 KSG ≈ 0 不是矛盾,而是 model-free 估计器需要更多数据。
  13. JIDT 代码:属性用字符串设置;setProperty 之后必须 initialise();默认参数不出现在生成代码里,改成非默认值才会生成占位。

十四、下周预告

Week 7 — Statistical significance:怎么判断估计出来的值是「真的有关系」还是「与 0 一致」。

⚠️ 注意 Module 编号和实际进度从这里开始错位(见 Week 6 课后公告):Week 7 要先做完 Module 6 Item 8 的 Part C(上课会接着做,A、B 部分要先完成并准备好代码),再学 Module 7 的内容,tutorial 做 Module 8 的 Item 2(读一篇用信息论方法做数据分析的论文,最好课前先读一篇)。