scikit-learn 双聚类(Biclustering)完全指南:Spectral Co-Clustering 与 Spectral Biclustering 的原理、参数与评估 scikit-learn 双聚类Biclustering完全指南Spectral Co-Clustering 与 Spectral Biclustering 的原理、参数与评估【免费下载链接】scikit-learnscikit-learn: machine learning in Python项目地址: https://gitcode.com/gh_mirrors/sc/scikit-learn双聚类biclustering是同时对数据矩阵的行和列进行聚类的一类算法其产物是同时覆盖特定行子集与列子集的bicluster双簇子矩阵。本文以 doc/modules/biclustering.rst 为核心骨架结合 scikit-learn 仓库中sklearn.cluster与sklearn.metrics的真实实现系统讲解双聚类的概念、两种谱聚类算法Spectral Co-Clustering 与 Spectral Biclustering的数学原理与全部核心参数、数据集生成工具以及基于consensus_score的评估方法。读完后你将能够理解双聚类与普通聚类的本质差异独立完成从数据生成、模型训练到结果评估与可视化的完整闭环并能根据数据形态块对角 vs 棋盘结构、稠密 vs 稀疏正确选择算法与归一化方法。什么是双聚类Biclustering双聚类算法同时对数据矩阵的行和列进行聚类。行簇与列簇的组合即构成 bicluster每个 bicluster 决定了原数据矩阵中的一个具有特定性质的子矩阵。例如给定一个形状为(10, 10)的矩阵一个包含 3 行 2 列的 bicluster 就导出一个形状为(3, 2)的子矩阵 import numpy as np data np.arange(100).reshape(10, 10) rows np.array([0, 2, 3])[:, np.newaxis] columns np.array([1, 2]) data[rows, columns] array([[ 1, 2], [21, 22], [31, 32]])为了可视化可以重排数据矩阵的行与列使 bicluster 变为连续块。不同算法对 bicluster 的定义不同常见的类型包括常量值、常量行或常量列constant values, constant rows, or constant columns异常高或异常低的值unusually high or low values低方差的子矩阵submatrices with low variance相关的行或列correlated rows or columns算法在行与列如何分配给 bicluster上也存在差异这导致了不同的 bicluster 结构。当行和列被划分为若干分区时会出现**块对角block diagonal或棋盘checkerboard**结构。块对角结构每一行、每一列恰好属于一个 bicluster。此时重排矩阵的行列后bicluster 会呈现在对角线上见 Spectral Co-Clustering 示例图 生成的第三张图其典型特征是每个 bicluster 内的均值高于其他行列。棋盘结构每一行属于所有列簇每一列属于所有行簇。例如 2 个行分区 × 3 个列分区时每行属于 3 个 bicluster、每列属于 2 个 bicluster各 bicluster 内部的方差很小见 Spectral Biclustering 示例图。注双聚类在不同领域有众多别名包括 co-clustering共聚类、two-mode clustering双模聚类、two-way clustering双向聚类、block clustering块聚类、coupled two-way clustering耦合双向聚类等。Spectral Co-Clustering 算法的命名即反映了这些别名。模型拟合后的成员属性拟合模型之后可以从以下属性中获取行、列簇归属信息源码定义于 sklearn/cluster/_bicluster.pyrows_[i]一个二值向量非零项对应的行属于 biclusteri形状为(n_row_clusters, n_rows)columns_[i]一个二值向量指示哪些列属于 biclusteri形状为(n_column_clusters, n_columns)biclusters_由rows_与columns_组成的元组可直接传给consensus_score进行评分。此外部分模型如块对角与棋盘结构下的两种谱算法还提供row_labels_与column_labels_属性它们是长度为行数 / 列数的一维整数标签数组分别给出每行、每列的簇编号。Spectral Co-Clustering谱共聚类SpectralCoclustering见 sklearn/cluster/_bicluster.py 中的SpectralCoclustering类用于寻找值高于对应其他行列的 bicluster。每一行、每一列恰好属于一个 bicluster因此重排行列使分区连续后这些高值会沿对角线显现——这正是块对角结构。算法直觉该算法将输入数据矩阵视为一张二分图矩阵的行与列分别对应图的两组顶点每个矩阵元素对应一条连接某行顶点与某列顶点的边权重为元素值。算法通过近似该图的**归一化割normalized cut**来寻找稠密子图heavy subgraphs。数学公式归一化割问题的最优解可以通过图 Laplacian 的广义特征值分解来近似。通常这需要直接处理 Laplacian 矩阵若原始数据矩阵 $A$ 的形状为 $m \times n$对应二分图的 Laplacian 矩阵形状为 $(mn) \times (mn)$。但在本算法中可以直接在更小、更高效的 $A$ 上操作。输入矩阵 $A$ 首先按下式预处理$$A_n R^{-1/2} A C^{-1/2}$$其中 $R$ 是对角矩阵第 $i$ 个对角元为 $\sum_j A_{ij}$行和$C$ 是对角矩阵第 $j$ 个对角元为 $\sum_i A_{ij}$列和。这一独立行列归一化正是源码中_scale_normalize函数sklearn/cluster/_bicluster.py所做的事先通过make_nonnegative确保矩阵非负再分别用行列和的平方根的倒数进行缩放。随后计算奇异值分解 $A_n U \Sigma V^\top$其部分左奇异向量给出行分区部分右奇异向量给出列分区。取从第二个开始的 $\ell \lceil \log_2 k \rceil$ 个奇异向量$k$ 为 bicluster 数构成矩阵 $Z$$$Z \begin{bmatrix} R^{-1/2} U \ C^{-1/2} V \end{bmatrix}$$其中 $U$ 的列取 $u_2, \dots, u_{\ell 1}$$V$ 同理。最后对 $Z$ 的行使用 k-means 聚类前n_rows个标签给出行分区其余n_columns个标签给出列分区。这一过程对应源码_fit中的实现——n_sv 1 int(np.ceil(np.log2(self.n_clusters)))决定奇异向量数量z np.vstack((row_diag[:, np.newaxis] * u, col_diag[:, np.newaxis] * v))构造 $Z$随后对 $Z$ 整体执行 k-means再按行数切分标签。参数详解参数默认值含义n_clusters3要发现的 bicluster 数量须 1且 n_samples否则报ValueErrorsvd_methodrandomized计算奇异向量的算法randomized使用sklearn.utils.extmath.randomized_svd对大矩阵更快arpack使用scipy.sparse.linalg.svds更精确但可能更慢n_svd_vecsNoneSVD 中使用的向量数对应arpack的ncv与randomized的n_oversamplesmini_batchFalse是否使用 mini-batch k-means更快但结果可能有差异initk-meansk-means 的初始化方法k-means、random或形状为(n_clusters, n_features)的 ndarrayn_init10k-means 尝试的随机初始化次数使用 mini-batch k-means 时选择最佳初始化并运行一次否则每次初始化都运行并取最优random_stateNone随机种子控制 SVD 与 k-means 初始化的随机性传 int 可复现结果从源码_parameter_constraintssklearn/cluster/_bicluster.py可以看出svd_method被限制为{randomized, arpack}init被限制为{k-means, random}或数组n_init必须为正整数其余参数的取值边界均有严格校验。快速上手示例参考官方示例 examples/bicluster/plot_spectral_coclustering.py 的完整流程用make_biclusters生成数据、打乱后交给算法再重排可视化并计算共识分数import numpy as np from sklearn.cluster import SpectralCoclustering from sklearn.datasets import make_biclusters from sklearn.metrics import consensus_score data, rows, columns make_biclusters( shape(300, 300), n_clusters5, noise5, shuffleFalse, random_state0 ) # 打乱行列模拟真实场景中结构未知的数据 rng np.random.RandomState(0) data data[rng.permutation(data.shape[0])][:, rng.permutation(data.shape[1])] model SpectralCoclustering(n_clusters5, random_state0) model.fit(data) score consensus_score(model.biclusters_, (rows, columns)) print(fconsensus score: {score:.3f}) # 按模型标签重排行列bicluster 即可连续呈现 fit_data data[np.argsort(model.row_labels_)] fit_data fit_data[:, np.argsort(model.column_labels_)]Spectral Biclustering谱双聚类SpectralBiclustering见 sklearn/cluster/_bicluster.py 中的SpectralBiclustering类假设输入数据矩阵具有隐藏的棋盘结构行与列可以被划分使得行簇与列簇笛卡尔积中的任意 bicluster 内部近似为常数。例如有 2 个行分区、3 个列分区时每行属于 3 个 bicluster每列属于 2 个 bicluster。算法将矩阵的行列进行划分使对应的分块常数棋盘矩阵能良好地近似原矩阵。数学公式输入矩阵 $A$ 首先被归一化以凸显棋盘模式共有三种可选方法独立行列归一化scale与 Spectral Co-Clustering 相同使行和为某常数、列和为另一常数。双随机归一化bistochastic反复进行行列归一化直至收敛使行和与列和收敛到同一常数。源码_bistochastic_normalizesklearn/cluster/_bicluster.py实现这一过程默认最多迭代 1000 次、容差tol1e-5。对数归一化log先计算 $L \log A$再计算 $L$ 的列均值 $\overline{L_{i \cdot}}$、行均值 $\overline{L_{\cdot j}}$ 与总体均值 $\overline{L_{\cdot \cdot}}$最终矩阵为$$K_{ij} L_{ij} - \overline{L_{i \cdot}} - \overline{L_{\cdot j}} \overline{L_{\cdot \cdot}}$$对应源码_log_normalize。注意对数归一化要求数据非稀疏因为稀疏矩阵中大量元素为 0$\log 0$ 发散为 $-\infty$源码对此直接抛出ValueErrorCannot compute log of a sparse matrix...。归一化后与 Spectral Co-Clustering 类似地计算前若干奇异向量。区别在于若使用对数归一化所有奇异向量都有意义若使用独立归一化或双随机归一化首个奇异向量 $u_1$、$v_1$ 会被丢弃后续所称的首个奇异向量指 $u_2 \dots u_{p1}$ 与 $v_2 \dots v_{p1}$。得到奇异向量后算法依据哪个向量能被分段常数向量最好地近似对其进行排序每个向量的分段常数近似由一维 k-means 得到并用欧氏距离评分选出左右两侧最佳的若干奇异向量。随后将数据投影到这组最佳奇异向量上并聚类。源码中这一步骤由_fit_best_piecewise与_project_and_cluster实现。例如若计算了 $p$ 个奇异向量按上述方式找出其中 $q$ 个最优的$q p$。设 $U$ 为以 $q$ 个最佳左奇异向量为列的矩阵$V$ 同理。为了划分行将 $A$ 的行投影到 $q$ 维空间$A \cdot V$把该 $m \times q$ 矩阵的 $m$ 行视为样本做 k-means即得行标签类似地将列投影到 $A^{\top} \cdot U$ 并对该 $n \times q$ 矩阵聚类即得列标签。参数详解SpectralBiclustering独有参数继承自BaseSpectral的svd_method、n_svd_vecs、mini_batch、init、n_init、random_state含义与上表相同参数默认值含义n_clusters3棋盘结构中的行列簇数可为整数行列簇数相同或元组(n_row_clusters, n_column_clusters)元组中各值须在(1, n_samples)范围内methodbistochastic归一化方法scale、bistochastic、log之一。论文作者推荐log但稀疏数据无法使用对数归一化因此默认取bistochastic。若methodlog数据必须非稀疏n_components6需要检验的奇异向量个数须 1n_best3用于投影聚类的最佳奇异向量个数须 1且 n_components否则报ValueErrorn_clusters同时支持整数与二元组的设计在源码_check_parameters中有完整体现元组会被解包校验任何非法输入都会得到包含取值说明的ValueErrorn_best n_components时同样会明确报错。快速上手示例参考官方示例 examples/bicluster/plot_spectral_biclustering.py用make_checkerboard生成棋盘数据4 行簇 × 3 列簇打乱后用methodlog拟合import numpy as np from sklearn.cluster import SpectralBiclustering from sklearn.datasets import make_checkerboard from sklearn.metrics import consensus_score n_clusters (4, 3) data, rows, columns make_checkerboard( shape(300, 300), n_clustersn_clusters, noise10, shuffleFalse, random_state42 ) # 打乱数据 rng np.random.RandomState(0) data data[rng.permutation(data.shape[0])][:, rng.permutation(data.shape[1])] model SpectralBiclustering(n_clustersn_clusters, methodlog, random_state0) model.fit(data) score consensus_score(model.biclusters_, (rows, columns)) print(fconsensus score: {score:.1f}) # 越接近 1 越好 # 重排行列使棋盘结构显现 reordered data[np.argsort(model.row_labels_)] reordered reordered[:, np.argsort(model.column_labels_)]示例还演示了用np.outer(np.sort(model.row_labels_) 1, np.sort(model.column_labels_) 1)绘制行标签与列标签的外积图直接可视化重排后的棋盘结构——这正是分块常数棋盘矩阵近似原矩阵这一假设的可视化印证。该算法尤其适合特征顺序有意义的数据如图像、时间序列、基因组数据。双聚类数据集生成工具sklearn.datasets提供了两个专为双聚类设计的数据生成函数定义于 sklearn/datasets/_samples_generator.pymake_biclusters(shape, n_clusters, *, noise0.0, minval10, maxval100, shuffleTrue, random_stateNone)生成常量块对角结构数组。bicluster 的常量值从[minval, maxval]区间均匀采样noise为高斯噪声的标准差返回(X, rows, cols)其中X形状为shaperows/cols为形状(n_clusters, n_rows)/(n_clusters, n_cols)的簇归属指示矩阵。它适用于 Spectral Co-Clustering 的场景高值块对角。make_checkerboard(shape, n_clusters, *, noise0.0, minval10, maxval100, shuffleTrue, random_stateNone)生成分块棋盘结构数组n_clusters可为整数或(n_row_clusters, n_column_clusters)元组返回结构同上适用于 Spectral Biclustering 的场景。两者都支持shuffle参数默认True是否打乱样本与random_state传 int 保证可复现。人工构造数据的最大价值在于真实数据中 bicluster 的真解通常未知而人工数据已知真解因此可以精确评估算法的还原能力。双聚类评估consensus_score双聚类结果的评估有**内部internal与外部external**两种途径内部度量如簇稳定性仅依赖数据与结果本身。目前 scikit-learn尚未实现任何内部双聚类度量外部度量参考外部信息如真解。真实数据通常不知道真解但人工数据因真解已知可用于精确评估算法。要比较找到的一组 bicluster与真解一组 bicluster需要两类相似度单个 bicluster 之间的相似度以及将个体相似度汇总为总体得分的方法。Jaccard 指数目前 scikit-learn 仅实现了 Jaccard 指数作为单个 bicluster 的相似度度量$$J(A, B) \frac{|A \cap B|}{|A| |B| - |A \cap B|}$$其中 $A$、$B$ 为 bicluster$|A \cap B|$ 是二者交集中的元素个数。Jaccard 指数在 bicluster 完全不相交时取得最小值 0在完全相同时取得最大值 1。源码_jaccardsklearn/metrics/cluster/_bicluster.py通过行指示向量与列指示向量的内积实现交集计数。共识分数consensus_scoreconsensus_score(a, b, *, similarityjaccard)定义于 sklearn/metrics/cluster/_bicluster.py用于比较两组 biclusterHochreiter et al., 2010 提出的方法计算分三步用 Jaccard 指数或类似度量计算两组 bicluster 两两之间的相似度矩阵以一对一方式将两组 bicluster 进行匹配最大化相似度之和。这一步通过scipy.optimize.linear_sum_assignment完成其底层使用改进的 Jonker-Volgenant 算法源码中即为linear_sum_assignment(1.0 - matrix)把最大化问题转为最小化将最终相似度之和除以较大集合的大小。consensus_score的最小值 0 出现在两组 bicluster 两两完全不相交时最大值 1 出现在两组完全一致时。参数a、b均为(rows, columns)形式的二元组即模型的biclusters_属性similarity可为字符串jaccard或任意接受四个一维指示向量(a_rows, a_columns, b_rows, b_columns)并返回标量的可调用函数。典型用法如下与两个官方示例中的用法一致from sklearn.metrics import consensus_score # a 与 b 均为 (rows_indicators, columns_indicators) 元组 score consensus_score(model.biclusters_, true_biclusters)在 examples/bicluster/plot_spectral_coclustering.py 与 examples/bicluster/plot_spectral_biclustering.py 中真解(rows, columns)会先按打乱时所用的行列索引对齐如(rows[:, row_idx], columns[:, col_idx])再与模型结果比较从而在混淆后仍能正确度量还原精度。实战决策建议与限制综合文档与源码可给出如下工程化建议结构形态决定算法数据近似每行每列各属一个高值块的块对角结构时选择SpectralCoclustering数据近似行簇 × 列簇的棋盘常数结构时选择SpectralBiclustering。归一化方法的选择SpectralBiclustering默认methodbistochastic是因为稀疏数据无法取对数若数据稠密可尝试论文推荐的methodlog以获得更清晰的结果官方示例即使用log。SpectralCoclustering固定使用独立行列归一化_scale_normalize。稀疏数据支持两种谱聚类算法都支持非负的 CSR 稀疏矩阵fit中accept_sparsecsr且__sklearn_tags__声明input_tags.sparse True但methodlog例外。规模与精度权衡大矩阵优先svd_methodrandomized追求精确可换arpack。mini_batchTrue可加速 k-means 阶段但结果可能不同。确定性复现固定random_state如0、42可同时控制 SVD 与 k-means 的随机性保证实验可复现。评估缺位提醒scikit-learn 目前没有内部双聚类度量正式评估前请先用make_biclusters/make_checkerboard构造带真解的数据验证流程。参考资源完整示例见 examples/bicluster/plot_spectral_coclustering.py 与 examples/bicluster/plot_spectral_biclustering.py另见文本聚类场景 examples/bicluster/plot_bicluster_newsgroups.py算法核心实现在 sklearn/cluster/_bicluster.py评估实现在 sklearn/metrics/cluster/_bicluster.py数据生成器在 sklearn/datasets/_samples_generator.py。算法背后的原始文献分别为 Dhillon2001的《Co-clustering documents and words using bipartite spectral graph partitioning》与 Kluger et al.2003的《Spectral biclustering of microarray data》。【免费下载链接】scikit-learnscikit-learn: machine learning in Python项目地址: https://gitcode.com/gh_mirrors/sc/scikit-learn创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考