Optimal Clustering by Lloyd Algorithm for Low-Rank Mixture Model¶
讲者: Dong Xia
会场: Inference in Statistical Models for Network Data
报告题目: Optimal Clustering by Lloyd Algorithm for Low-Rank Mixture Model
链接: arXiv
来源: JCSDS 2026 · 返回会议总览
一、领域脉络与小综述¶
这个方向是什么¶
这个子方向研究的是矩阵值观测数据(每个样本是一个矩阵,而非向量)的聚类问题。其核心统计问题是:当每个矩阵观测的期望(即“中心矩阵”)具有低秩结构时,如何设计计算高效的聚类算法,并刻画其统计最优性与计算可行性之间的权衡。该方向当前处于“从经典向量GMM向结构化张量/矩阵模型扩展”的阶段,核心挑战在于:低秩结构既带来了统计上的“福音”(降低了对分离强度的要求),也引入了计算上的“诅咒”(需要额外的信号强度条件才能被算法利用)。
发展脉络(history)¶
-
奠基工作:向量GMM的聚类理论。经典工作如Lu and Zhou (2016) 证明了Lloyd算法在子高斯混合模型下的收敛性,并给出了指数型聚类误差率。Löffler et al. (2021) 证明了谱聚类在GMM下的极小化最优性,其误差率为
exp(-Δ²/8),其中Δ是分离强度(中心之间的最小欧氏距离)。Gao and Zhang (2019) 提出了一个统一的迭代算法框架,并在线性收敛速度下达到了极小化最优率。这些工作为矩阵/张量情形提供了理论基准。 -
主要进展:引入低秩结构。意识到矩阵观测常具有低秩期望后,研究者开始设计专门方法。Sun and Li (2019) 提出了张量高斯混合模型,将聚类转化为低秩张量分解中的因子估计问题,但未给出聚类误差率。Mai et al. (2021) 提出了张量正态混合模型和增强EM算法,给出了估计误差率,但训练聚类误差缺失。Jing et al. (2021) 针对多层网络提出了混合多层SBM,基于张量分解的谱聚类方法给出了聚类误差率,但作者指出该率“likely sub-optimal”,且要求
n = O(d1)这一限制性条件。Lyu et al. (2021) 将混合框架扩展到潜在空间模型,也导出了次优的聚类误差率。 -
当前Frontier:统计-计算权衡与最优性。Lyu and Xia (2022) 研究了低秩高斯混合模型(LrMM)下中心矩阵估计的极小化最优率和计算极限,揭示了多个相变和统计-计算间隙。Luo and Zhang (2020) 研究了高阶张量聚类的统计与计算极限,识别了检测与恢复的尖锐边界。Han et al. (2022a) 提出了张量块模型和高阶Lloyd算法,但该算法利用的是块结构而非低秩结构,不适用于LrMM。
-
本文的位置:本文填补了LrMM下最优聚类误差率的空白。它提出了一个结合Lloyd算法和低秩近似的计算高效算法(lr-Lloyd),证明了在良好初始化下,该算法能达到极小化最优的指数型聚类误差率
exp(-Δ²/8)。更重要的是,本文首次揭示了LrMM下聚类问题的计算瓶颈由信号强度(中心矩阵的最小非零奇异值)而非分离强度刻画,并基于低度似然比框架提供了计算障碍的证据。
子线索聚类¶
- 线索一:统计最优性。这一簇工作关注“理论上能达到多好的聚类精度”,通常以极小化下界为基准。代表工作:Löffler et al. (2021)(GMM下的极小化最优谱聚类)、Gao and Zhang (2019)(统一迭代框架)、Lu and Zhou (2016)(Lloyd算法的最优性)。本文的Theorem 1和Theorem 3属于此线索。
- 线索二:计算可行性算法。这一簇工作设计能在多项式时间内运行的聚类算法,并分析其条件。代表工作:Lu and Zhou (2016)(Lloyd算法)、Jing et al. (2021)(TWIST张量分解)、Han et al. (2022a)(高阶Lloyd算法)。本文的Algorithm 1 (lr-Lloyd) 和 Algorithm 2 (TS-Init) 属于此线索。
- 线索三:计算瓶颈与统计-计算权衡。这一簇工作试图刻画“哪些问题是统计上可能但计算上困难的”。代表工作:Löffler et al. (2020)(稀疏GMM下的低度似然比证据)、Ding et al. (2019)(稀疏PCA)、Kunisky et al. (2019)(低度似然比框架综述)。本文的Section 4和Theorem 4属于此线索,将计算瓶颈与信号强度而非分离强度联系起来。
这个方向在追问的核心问题¶
- 分离强度Δ需要多大才能实现一致聚类? 在GMM中,已知
Δ ≫ 1 + (d*/n)^{1/2}可实现指数型误差率(Gao and Zhang, 2022),而Δ ≳ (d* log n / n)^{1/4}可实现精确恢复(Ndaoud, 2018; Chen and Yang, 2021)。在LrMM下,这个条件如何被低秩结构改善?本文给出Δ² ≫ 1 + d1 r_max / n,但这是否是最终答案? - 信号强度(最小非零奇异值)在计算中扮演什么角色? 本文发现,即使分离强度很强,若信号强度不足(
Λ_min = o(d^{1/2} n^{1/4})),多项式时间算法也无法实现一致聚类。这个阈值是否严格?它与张量PCA中的已知阈值有何联系? - 如何实现最优初始化? Lloyd算法对初始化敏感。本文提出的张量谱初始化(Algorithm 2)需要信号强度条件,而一旦初始化成功,后续迭代不再需要该条件。是否存在更弱的初始化条件?
- 聚类与估计的难度差异:在LrMM下,聚类是否一定比估计更难?本文Section 6给出了一个例子,其中估计是可能的但聚类不可能(低维情形),以及另一个例子,其中聚类是可能的但估计不可能(弱信号中心)。这种差异的完整刻画是什么?
⚠️ 作者的framing¶
- 作者把缺口frame成什么:作者将LrMM定位为“GMM的自然推广,但低秩结构带来了新的统计与计算挑战”。他们强调,现有工作要么忽略了低秩结构(如直接向量化),要么在理论上次优或受限于
n = O(d1)。本文的贡献是同时达到极小化最优聚类误差率和计算高效,并首次揭示了信号强度而非分离强度是计算瓶颈。 - 哪些竞争路线被淡化或回避:
- 凸松弛方法(如SDP):作者在Introduction中提及“convex relaxation seems not immediately accessible for the clustering of LrMM, especially when there are more than two clusters”,但并未深入讨论。对于K=2的情形,SDP是否可行?作者回避了这一点。
- 基于EM的方法(如Mai et al., 2021的DEEM):作者指出DEEM需要高斯假设和K-S检验,且未提供聚类误差率,但并未在模拟中与DEEM进行公平比较(BHL数据集上,DEEM的输入是降维后的数据,而本文用的是原始数据)。
- 其他非凸方法:如张量分解的HOOI(Zhang and Xia, 2018),作者指出其需要
σ_min(M3(S))的下界,这在LrMM下过于严格,因此不适合。
- 什么明显该被引/该存在、却没出现在intro里? 作者引用了大量关于GMM和张量模型的工作,但似乎没有引用关于矩阵正态分布(Matrix Normal Distribution)的经典文献(如Dawid, 1981; Gupta & Nagar, 2000)。LrMM假设噪声矩阵的条目独立同分布,这等价于协方差矩阵为
I_d1 ⊗ I_d2的矩阵正态分布。若考虑更一般的可分离协方差结构(如Σ_row ⊗ Σ_col),问题会更复杂,但这也是一个自然的扩展方向。此外,关于随机块模型(SBM)的精确恢复阈值(如Abbe et al., 2016)的讨论可以更深入,因为LrMM与多层SBM有密切联系。
张力¶
未见明显对立引用。所有被引工作基本在“GMM聚类理论”和“低秩模型”这两个大框架下相互补充,没有出现同一问题下结论相反的情况。
二、最核心、最简单的例子 / 数学问题¶
第一步:把符号、模型、可观测数据交代清楚¶
-
符号:
X_i ∈ R^{d1 × d2}:第i个矩阵观测,i = 1, ..., n。s_i^* ∈ [K]:第i个观测的真实潜在类别标签(未知)。M_k ∈ R^{d1 × d2}:第k个类别的总体中心矩阵(未知),k = 1, ..., K。假设rank(M_k) = r_k,且r_k ≪ d2。E_i ∈ R^{d1 × d2}:第i个观测的噪声矩阵,其条目i.i.d.服从均值为0、方差为1的子高斯分布。Δ := min_{a≠b} ||M_a - M_b||_F:分离强度,衡量不同类别中心矩阵之间的最小Frobenius距离。λ := min_k σ_min(M_k):个体信号强度,衡量所有中心矩阵的最小非零奇异值。Λ_min := min_{j=1,2} σ_min(M_j(M)):张量信号强度,其中M ∈ R^{d1 × d2 × n}是信号张量(第i个切片为M_{s_i^*}),M_j(M)是其mode-j矩阵化。这个量衡量了信号张量在前两个模式上的“强度”。n_k^* := |{i: s_i^* = k}|:第k个类别的真实样本量。α := min_k n_k^* / (n/K):最小类别比例,衡量类别平衡性。κ_0 := max_k ||M_k|| / min_k σ_min(M_k):最大条件数。
-
模型:低秩混合模型(LrMM)。数据生成过程为:先以概率
π_k从K个类别中抽取一个标签s_i^*,然后给定s_i^* = k,观测X_i由低秩中心矩阵M_k加上独立子高斯噪声E_i构成:X_i = M_{s_i^*} + E_i。关键假设是每个中心矩阵M_k都是低秩的(r_k ≪ d2)。 -
可观测数据:研究者能观测到的是
n个矩阵{X_i}_{i=1}^n。不可观测的是:- 真实标签
{s_i^*}。 - 总体中心矩阵
{M_k}。 - 噪声矩阵
{E_i}。 - 中心矩阵的秩
{r_k}和类别数K(本文假设已知)。
- 真实标签
第二步:讲最小内核¶
最简特例:对称的两类秩-1 LrMM
考虑最简单的情形:K=2,r_1 = r_2 = 1,且两个中心矩阵互为相反数:M_1 = -M_2 = M,其中 M = λ u v^T,u ∈ R^{d1},v ∈ R^{d2} 是单位向量,λ > 0 是信号强度。此时,分离强度 Δ = ||M_1 - M_2||_F = 2||M||_F = 2λ。个体信号强度 λ = σ_min(M) = λ。张量信号强度 Λ_min 在此特例下与 λ 成正比(具体为 Λ_min ≍ √n λ)。真实标签 s_i^* ∈ {+1, -1} 等概率。
在这个特例下,论文的核心问题退化为:给定 n 个矩阵观测 X_i = s_i^* M + E_i,我们能否通过多项式时间算法(如Lloyd算法)以指数型小的误差率恢复标签 s_i^*?
核心思路:
1. 初始化:使用张量谱方法(Algorithm 2的简化版)。构造数据张量 X ∈ R^{d1 × d2 × n},其第i个切片是 X_i。计算其mode-1和mode-2矩阵化的前1个左奇异向量,得到 û 和 v̂。然后对每个观测计算投影 Ĝ_i = û û^T X_i v̂ v̂^T,这是一个标量(因为秩为1)。对 {Ĝ_i} 运行K-means(K=2)得到初始标签 ŝ_i^{(0)}。
- 关键条件:这个初始化要成功,需要信号强度 λ 足够强,使得 û 和 v̂ 能可靠估计 u 和 v。本文证明这需要 Λ_min ≳ d^{1/2} n^{1/4},即 λ ≳ d^{1/2} n^{-1/4}。
- 迭代:给定初始标签,运行低秩Lloyd算法(Algorithm 1的简化版)。
- 更新中心:对每个类别
k ∈ {+1, -1},计算当前标签下该类别的样本均值X̄_k,然后取其秩-1 SVD近似作为新的中心估计M̂_k。 - 更新标签:对每个观测
X_i,将其分配给与M̂_k距离更近的类别。 - 关键性质:一旦初始化足够好(即初始聚类误差很小),后续迭代会快速收敛。本文证明,在分离强度
Δ足够大(Δ² ≫ 1 + d1/n)的条件下,每次迭代后聚类误差至少减半,直到达到极小化最优的指数型误差率exp(-Δ²/8)。
- 更新中心:对每个类别
这个特例揭示了论文的核心数学困难:在更新中心时,我们不是简单地取均值,而是取均值的低秩近似。这个非线性操作使得分析变得复杂。例如,M̂_k 与真实中心 M_k 之间的误差不仅包含随机噪声,还包含来自错误分类样本的“污染”。要控制这个污染,就需要信号强度 λ 足够大,使得SVD能有效“去噪”。这正是为什么在初始化阶段需要信号强度条件,而在迭代阶段,由于误差已经很小,该条件可以放松。
三、这篇论文做了什么¶
三句话¶
- 研究了什么问题:研究了低秩混合模型(LrMM)下矩阵值观测的聚类问题,旨在设计计算高效的算法并刻画其统计最优性与计算极限。
- 核心工具/方法:提出了低秩Lloyd算法(lr-Lloyd),将经典的Lloyd算法与低秩近似(SVD)相结合;并设计了基于张量高阶SVD(HOSVD)的谱初始化方法(TS-Init)。
- 主要结论:证明了在良好初始化下,lr-Lloyd算法能以指数型收敛速度达到极小化最优的聚类误差率
exp(-Δ²/8),且该率仅由分离强度Δ决定;同时,基于低度似然比框架提供了证据,表明若信号强度不足(Λ_min = o(d^{1/2}n^{1/4})),则任何多项式时间算法都无法实现一致聚类,即使分离强度很强。
关键设定与假设¶
- 模型:LrMM(公式4),假设噪声矩阵
E_i的条目i.i.d.服从均值为0、方差为1的子高斯分布(Assumption 1)。类别标签s_i^*视为固定实现,但满足n_k^* ≍ nπ_k(由Chernoff bound保证)。 - 已知参数:类别数
K和每个中心矩阵的秩r_k假设已知。作者在Section 7.1简要讨论了如何通过scree plot估计这些参数。 - 关键假设:
- 分离强度条件(公式11):
Δ² / (α^{-1}(κ_0² ∨ Kr)Kr (d/n + 1)) → ∞。这比GMM所需的Δ ≫ 1 + (d1d2/n)^{1/2}弱得多,体现了低秩的“福音”。 - 信号强度条件(公式13,用于初始化):
Λ_min ≥ C (rK)^{1/2} d^{1/2} n^{1/4}。这是计算可行性的关键,体现了低秩的“诅咒”。 - 初始聚类误差条件(公式10):
n^{-1} ℓ_c(ŝ^{(0)}, s^*) = o(α/(κ_0² K Δ²))。这要求初始聚类误差足够小,是Lloyd算法局部收敛性质所必需的。 - 与已有文献的对比:相比GMM(Gao and Zhang, 2022),本文额外需要信号强度条件;相比张量块模型(Han et al., 2022a),本文不要求块结构的离散性,但分析更复杂。
- 分离强度条件(公式11):
主要结果¶
- Theorem 1(lr-Lloyd的收敛性):在分离强度条件(11)和初始条件(10)下,lr-Lloyd算法第t次迭代后的聚类误差满足
n^{-1} h_c(ŝ^{(t)}, s^*) ≤ exp(-(1-o(1))Δ²/8) + 2^{-t}。该误差率与GMM的极小化最优率一致,且迭代次数仅需O(min{Δ², log n})。 - Theorem 2(TS-Init的保证):在信号强度条件(13)和分离强度条件(14)下,TS-Init算法输出的初始聚类误差满足
n^{-1} h_c(ŝ^{(0)}, s^*) ≤ C K/Δ² (dKr/n + 1)。这保证了初始聚类是一致(consistent)的,从而满足Theorem 1的条件。 - Theorem 3(极小化下界):在LrMM下,任何聚类算法的期望误差至少为
exp(-(1+o(1))Δ²/8)。这与Theorem 1的上界匹配,证明了lr-Lloyd的极小化最优性。 - Theorem 4(计算障碍):考虑对称的两类秩-1 LrMM。若信号强度
Λ_min = o(d^{1/2} n^{1/4}),则低度似然比的范数||L^{≤D}_n|| = 1+o(1)。根据Conjecture 1,这意味着没有多项式时间检验能区分有信号和无信号的情形。 - Theorem 5(从聚类到检验的归约):若存在一个多项式时间的一致聚类算法,则存在一个多项式时间的一致检验。结合Theorem 4和Conjecture 1,得到Corollary 1:若信号强度不足,则任何多项式时间聚类算法都无法实现一致聚类。
- Theorem 6 & 7(弱信号强度下的变体):当其中一个中心矩阵的信号强度很弱(无法可靠估计)时,提出了修正的rlr-Lloyd算法(Algorithm 3)和rTS-Init初始化(Algorithm 4),并证明了在适当条件下仍能达到最优聚类误差率。
证明路线与技术技巧(理论型)¶
整体路线(以Theorem 1为例):
1. 建立“好事件”:定义并证明高概率事件 Q1 ∩ Q2 ∩ Q3(Lemma 3),在这些事件下,随机噪声的算子范数、样本均值的偏差等都有良好的上界。
2. 单步迭代分析:证明从第t-1次到第t次迭代,聚类误差满足收缩性质(公式21):ℓ(ŝ^{(t)}, s^*) ≤ 2n exp(-(1-o(1))Δ²/8) + (1/2) ℓ(ŝ^{(t-1)}, s^*)。
- 分解误差:将 ℓ(ŝ^{(t)}, s^*) 分解为三部分:ξ_err(由随机噪声直接导致的错误)、β_1(由中心估计误差导致的错误)、β_2(由中心估计误差的二次项导致的错误)。
- 控制 ξ_err:利用子高斯变量的尾概率,直接得到其期望上界为 n exp(-Δ²/8),再通过Markov不等式得到高概率上界。
- 控制 β_1:这是最困难的部分。需要分析 M̂_k^{(t)} - M_k 的误差。关键在于使用谱表示公式(Lemma 5,来自Xia, 2021),将SVD后的中心估计展开为关于扰动 Δ^{(t-1)} 的无穷级数。然后,将 β_1 中的内积 ⟨E_i, M̂_k - M_k⟩ 分解为多个项,每个项对应级数中的一项。对于每一项,利用“留一法”(leave-one-out)技巧解耦 E_i 与 M̂_k 的依赖关系,再结合子高斯尾概率和Lemma 6(关于秩约束下二次型的上界)进行控制。
- 控制 β_2:利用 ||M̂_k - M_k||_F 的上界(由Lemma 4和信号强度条件保证)直接进行放缩。
3. 数学归纳:证明若第t-1次迭代的误差满足初始条件,则第t次迭代的误差也满足,从而收缩性质对所有t成立。最终得到指数型误差率。
关键跳跃点:
- 谱表示公式的应用:这是整个证明的技术核心。没有这个公式,就无法处理SVD的非线性,无法将 M̂_k 的误差展开为可分析的级数形式。作者巧妙地利用该公式,将问题转化为对一系列“多项式型”随机变量的控制。
- “留一法”解耦:在控制 β_1 时,M̂_k 依赖于所有数据,包括 E_i。通过将扰动 Δ^{(t-1)} 分解为包含 E_i 的部分和不包含 E_i 的部分,作者将内积 ⟨E_i, M̂_k - M_k⟩ 中的项分为两类:一类是 E_i 与独立于它的量做内积(可用尾概率),另一类是 E_i 与包含它自身的量做内积(其范数很小,可被信号强度条件吸收)。
技术技巧点名:
- 谱表示公式(Lemma 5):来自Xia (2021),用于将SVD后的矩阵展开为关于扰动的无穷级数。这是处理低秩估计问题的关键工具。
- 留一法(Leave-one-out):用于解耦估计量与特定样本的依赖关系。
- 经验过程理论(Lemma 9,来自Mendelson, 2016):用于控制秩约束下二次型 ∑ ⟨E_i, Ξ⟩² 的上界(Lemma 6)。
- 低度似然比框架(Kunisky et al., 2019):用于提供计算障碍的证据。
- 样本分裂技巧(Theorem 5的证明中):用于将聚类算法归约为假设检验。
真实例子与应用¶
本文有丰富的真实数据应用(Section 8.2):
1. BHL数据集(脑、心、肺组织基因表达):n=27, d1=1124, d2=4, K=3。lr-Lloyd算法(Algorithm 1 + 2)的聚类误差为3.70%,优于DEEM(7.41%)、K-means(11.11%)等方法。作者认为改进源于:lr-Lloyd不需要高斯假设和K-S检验,且利用了中心矩阵的秩-1结构。
2. EEG数据集(酒精中毒脑电信号):n=122, d1=256, d2=64, K=2。rlr-Lloyd算法(Algorithm 3 + 4)的聚类误差为28.69%(S2刺激条件),优于vec-Lloyd(35.25%)、DTC(39.34%)等方法。作者指出,原始lr-Lloyd在此数据集上表现不佳,因为控制组的平均矩阵接近纯噪声,这正好是rlr-Lloyd设计的场景。
3. 疟疾寄生虫基因网络数据集:n=9, d1=d2=212, K=6。TS-Init算法(Algorithm 2)直接将9个HVRs聚类为6组,结果与Jing et al. (2021)的TWIST方法一致,但避免了重复聚类。
4. UN贸易流网络数据集:n=97, d1=d2=48, K=2。lr-Lloyd算法将97种商品聚类为两类:低耐久性产品(如动植物产品)和工业产品,结果具有可解释性。
🔎 结论是否比证明窄¶
- Theorem 1的指数型误差率:证明中要求
Δ² / (α^{-1}(κ_0² ∨ Kr)Kr (d/n + 1)) → ∞(公式11),但结论中写的是exp(-(1-o(1))Δ²/8)。这里的o(1)项依赖于Δ²与(d/n + 1)的比值。若该比值只是趋于无穷但很慢,则o(1)可能并不小,指数率中的常数可能不再是严格的1/8。作者在定理陈述后承认了这一点,并指出o(1)项的量级为Ω( (Kr(d+log n)/(αn))^{1/2-ϵ} / Δ )。 - Theorem 2的初始化保证:条件(13)要求
Λ_min ≥ C (rK)^{1/2} d^{1/2} n^{1/4}。这个条件很强,且依赖于r和K。作者在Section 3.2中通过Lemma 2讨论了Λ_min与个体信号强度λ的关系,指出在两种特殊情形(所有中心共享相同奇异空间,或中心奇异空间相互正交)下,该条件可以简化为λ ≥ C d^{1/2} n^{-1/4}。但对于一般情形,这个条件可能更严格。 - 计算障碍的证据:Section 4的结论(Corollary 1)依赖于Conjecture 1(低度似然比猜想),这是一个被广泛相信但未被严格证明的猜想。因此,本文提供的“证据”是启发性的,而非严格的证明。作者在文中明确标注了这一点。
四、开放问题¶
-
分离强度Δ的精确刻画:本文给出了实现指数型误差率的充分条件
Δ² ≫ 1 + d1 r_max / n。但在GMM中,存在一个更弱的条件Δ ≳ (d* log n / n)^{1/4}可实现精确恢复(Ndaoud, 2018; Chen and Yang, 2021)。在LrMM下,这个“n^{-1/4}”尺度的条件是否也能实现?作者在Section 3.1末尾明确提出了这个问题,并认为“answering this question is perhaps more challenging than that under GMM”。(扎根于论文第14页:“This leaves a natural question under LrMM: is the separation strength condition (11) is relaxable to the scale n^{-1/4}?”) -
信号强度条件的必要性:本文基于低度似然比猜想,提供了证据表明信号强度
Λ_min = o(d^{1/2} n^{1/4})时,多项式时间算法无法实现一致聚类。这个阈值是否是严格的?是否存在一个多项式时间算法能在更弱的信号强度下成功?或者,能否在更强的计算模型(如SQ模型)下证明这个下界?(扎根于论文Section 4,特别是Theorem 4和Corollary 1。) -
秩和聚类数的自适应估计:本文假设
K和r_k已知。作者在Section 7.1简要讨论了如何通过scree plot估计这些参数,但未提供理论保证。能否设计一个自适应的算法,在未知这些参数的情况下仍能达到最优聚类误差率?(扎根于论文第26页:“Our tensor-based spectral initialization method requires an input of ranks rU, rV and the number of clusters K, which are usually unknown in practice.”) -
非高斯和非独立噪声的扩展:本文的噪声假设是i.i.d.子高斯。但在真实应用中,如二进制网络(疟疾基因数据)或计数数据,噪声结构更复杂。作者在Section 7.2指出,对于伯努利噪声,其方差非齐性,本文的定理2可能不成立,且定理1的证明可能不是最优的。如何将理论扩展到这些更一般的噪声模型?(扎根于论文第27页:“Unfortunately, our theory can not directly cover those cases, although the noise are still sub-Gaussian.”)
Maintained by 陈星宇 · Homepage · Source on GitHub