内容

1安装

要安装软件包,请使用以下方法。

如果(!requireNamespace("BiocManager")) install.packages("BiocManager") BiocManager::install("mbkmeans")

2简介

属性的介绍性示例mbkmeans包,其中包含中提出的小批量k-means算法的实现(2010年斯卡利)用于大型单细胞测序数据。该算法在小的随机数据子样本(“小批量”)上运行_k_means迭代,而不是在整个数据集上运行。这既加快了计算速度,又减少了内存中必须包含的数据量。

用户使用的主要功能是mbkmeans.这是作为S4泛型实现的,实现的方法是矩阵矩阵HDF5MatrixDelayedMatrixSummarizedExperiment,SingleCellExperiment

这项工作的大部分灵感来自MiniBatchKmeans ()函数在ClusterRR包,我们重用了其中实现的许多c++函数。

我们在这里的主要贡献是提供一个接口DelayedArray而且HDF5Array包装mbkmeans算法只在任何时候将当前迭代所需的“迷你批量”带入内存,而从不需要将整个数据集加载到内存中。这允许用户运行迷你批处理k-means算法在非常大的数据集上,不完全适合内存。mbkmeans也在用户提供的内存矩阵上无缝运行,与标准算法相比,这样做显著提高了算法的速度k-均值算法((Hicks et al. 2020)).完整的比较mbkmeans与其他实现可以在(Hicks et al. 2020)

这项工作的动机是大型单细胞rna测序(scRNA-seq)数据集的聚类,因此主要重点是Bioconductor的SingleCellExperiment而且SummarizedExperiment数据的容器。出于这个原因,mbkmeans假设基因组数据的典型数据表示,其中基因(变量)在行中,细胞(观察值)在列中。这与大多数其他统计应用相反,特别是与统计数据::kmeans ()而且ClusterR: MiniBatchKmeans ()假设行中的观察值的函数。

我们提供了一个较低的层次mini_batch ()函数,该函数期望行中的观测值,并期望直接替换ClusterR: MiniBatchKmeans ()对于磁盘上的数据表示,例如HDF5文件。的其余部分展示了典型用例mbkmeans ()接口;对mini_batch ()功能应参考其手册页。

2.1示例数据集

为了说明一个典型的用例,我们使用pbmc4k数据集TENxPBMCData.该数据集包含一组来自健康供者外周血的约4000个细胞,预计将包含多种类型或细胞群。

我们会注意到mbkmeans它是为非常大的数据集设计的,特别是大到不能在内存中保存完整的数据矩阵,或者不能计算必要的计算的数据集。这个小插图使用一个小数据集,允许用户快速跟随和理解命令。(Hicks et al. 2020)给出了使用的例子mbkmeans对于一个拥有130万个单元格的数据集,这是观察改进的内存使用和速度的更合适的大小。

首先,我们加载所需的包。

库(TENxPBMCData)库(scater)库(singlecel实验)库(mbkmeans)库(DelayedMatrixStats)

请注意,在这个小插图中,我们的目标不是识别生物学上有意义的集群(这将需要更复杂的数据规范化和降维),而是我们的目标只是展示如何运行迷你批处理k-means在hdf5支持的矩阵上。

我们简单地通过缩放使用的总计数数量来规范化数据然后选择1000个最易变的基因和随机的100个细胞来加速计算。

tenx_pbmc4k <- TENxPBMCData(dataset = "pbmc4k") set.seed(1034) idx <- sample(seq_len(NCOL(tenx_pbmc4k)), 100) sce <- tenx_pbmc4k[, idx] #normalization sce <- logNormCounts(sce) vars <- rowVars(logcounts(sce)) names(vars) <- rownames(sce) vars <- sort(vars, reduced = TRUE) sce1000 <- sce[names(vars)[1:1000],] sce1000
##类:singlecel实验## dim: 1000 100 ##元数据(0):## assays(2): counts logcounts ## rownames(1000): ENSG00000090382 ENSG00000204287…ENSG00000117748 ## ENSG00000135968 ## rowData names(3): ENSEMBL_ID Symbol_TENx Symbol ## colnames: NULL ## colData names(12): Sample Barcode…## mainExpName: NULL ## altExpNames(0):

3.mbkmeans

主要功能,mbkmeans (),返回一个包含的列表对象重心WCSS_per_cluster(其中WCSS代表within-cluster-sum-of-squares),best_initializationiters_per_initiazation而且集群

它接受任何类似矩阵的对象作为输入,例如SummarizedExperimentSingleCellExperiment矩阵DelayedMatrix而且HDF5Matrix

在本例中,输入为aSingleCellExperiment对象。

res <- mbkmeans(sce1000, clusters = 5, reduceMethod = NA, whereassay = "logcounts")

集群的数量(如kk-means算法)通过集群论点。在这种情况下,我们设集群= 5个没有什么特别的原因。为SingleCellExperiment对象时,函数提供reduceMethod而且whichAssay参数。的reduceMethod参数应该指定用于聚类的降维槽,默认为“PCA”。注意这一点不执行但PCA只查看已经存储在对象中的名为“PCA”的槽。或者,也可以指定whichAssay作为小批的输入品k则。仅在以下情况下使用reduceMethod选择是NA.看到mbkmeans ?欲知详情。

3.1论据的选择

还有其他的论点mbkmeans ()使功能更加灵活,适用于更多的情况。

3.1.1批量大小

小批量的大小是通过batch_size论点。这个参数给出了在任何时候进入内存的数据样本的大小,从而限制了算法的内存使用。

blocksize ()函数可用于将批处理大小设置为可用内存允许的最大大小。它同时考虑数据集中的列数和当前同步机上的RAM数量,以计算出会话可用RAM的合理的批处理大小。计算使用get_ram ()函数benchmarkme包中。看到benchmarkme更多细节。

Batchsize <- blocksize(sce1000)批量大小
## [1] 100

在这个简单的示例中,因为整个数据都适合内存,所以默认批处理大小是单个大小为100的批处理。

(Hicks et al. 2020)为大型数据集(即全部数据不能存储在内存中)提供批处理大小的影响的比较。他们的结果表明,该算法在大范围的批处理大小(1000 -10,000个单元)下都是强大的:如果批处理大小在500-1000个单元以上,结果的准确性是等效的,只要批处理小于大约10,000个单元,在内存使用或速度方面没有明显的优势(对应于完整数据矩阵的子样本,其内存足迹在大多数现代计算机上是不明显的)。出于这个原因,我们会错误地使用中建议的更大的批大小范围(Hicks et al. 2020)- 10000个细胞。此外,由于初始化在默认情况下使用与批处理大小相同的单元格数量,这为确定初始起点提供了一个可靠的示例。

我们要注意的是,最好在选择批大小的基础上进行选择绝对批处理中的单元数,而不是根据总体样本量的百分比选择批处理大小。如果批处理大小是根据单元格的百分比选择的,那么非常大的数据集将使用非常大的批处理单元格,从而抵消了内存和速度的增益。而且,为了保证算法的良好性能,不需要这么大的批量。批次的连续重采样工作类似于随机梯度下降,并允许(局部)最小化目标函数(2010年斯卡利)用相对较小的批量大小,证明了单细胞数据的工作(Hicks et al. 2020).如果有的话,批处理的大小应该更多地由问题的复杂性来控制(例如,底层真实集群或子类型的数量),而不是数据集中整体单元格的数量。

3.1.2初始化

小批量的性能k-means很大程度上取决于初始化的过程。我们实现了两种不同的初始化方法:

  1. 随机初始化,如常规初始化k则;
  2. kmeans + +,建议于(Arthur and Vassilvitskii 2007).默认值为“kmean++”。

用于初始化质心的数据百分比是通过init_fraction参数,该参数应大于0且小于1。给出了默认值,以便比例匹配的值batch_size,转换成比例的数据。

res_random <- mbkmeans(sce1000, clusters = 5, reduceMethod = NA, whichAssay = "logcounts", initializer = "random") table(res$ clusters, res_random$ clusters)
## ## 1 23 4 5 ## 1 0 0 0 0 1 ## 2 0 0 1 0 0 ## 3 4 0 23 0 0 ## 4 0 0 0 0 4 ## 5 0 5 0 14 48

的大值init_fraction将导致该比例的数据被保存在内存中,并用于初始化kmeans + +算法。因此,较大的值init_fraction将需要大量的内存——可能比实际的聚类算法使用的内存还要多。事实上,对于越来越大的数据集,保持使用的分数不变将导致初始化时使用的单元格数量减少,并增加内存使用(类似于上面讨论的批处理大小问题)。因此,我们建议用户保持默认值,并对batch_size参数,确保算法的初始化阶段和实际聚类阶段的内存使用一致。如上文所述batch_size,出于这个原因,我们建议batch_size在较大的范围内建议为合理的(Hicks et al. 2020)从而改善初始化。

3.2运行mbkmeans的多个值\ (k \)

要设置的主要参数\ (k \)-means及其变体为集群的个数\ (k \)mbkmeans即使在非常大的数据集中,也足够快地重新运行不同数量的聚类算法。

这里,我们应用mbkmeans\ (k \)从5到15,用弯头法选择聚类数(即曲线上拐点对应的值)。我们注意到,这只是选择集群数量的经验法则,并且存在许多不同的方法来决定的适当值\ (k \)

为了加快计算速度,我们将在前20台pc上进行集群。

sce1000 <- runPCA(sce1000, ncomponents=20) ks <- seq(5,15) res <- lapply(ks, function(k) {mbkmeans(sce1000, clusters = k, reduceMethod = "PCA", calc_wcss = TRUE, num_init=10)}) wcss <- sapply(res, function(x) sum(x$WCSS_per_cluster)) plot(ks, wcss, type = "b")

从情节上看,似乎K = 12可能是一个合理的值。

4k

注意,如果我们设置Init_fraction = 1初始化项= "random",Batch_size = ncol(x),我们恢复了经典k则算法。

res_full <- mbkmeans(sce1000, clusters = 5, reduceMethod = NA, whichAssay = "logcounts", initializer = "random", batch_size = ncol(sce1000)) res_classic <- kmeans(t(logcounts(sce1000)), centers = 5) table(res_full$ clusters, res_classic$cluster)
## ## 1 2 3 4 5 ## 10 7 0 7 0 ## 2 0 0 14 43 0 ## 3 2 0 0 0 0 0 ## 4 16 0 0 0 0 10 ## 5 0 0 0 0 10

但是请注意,由于这两种算法从不同的随机初始化开始,它们并不总是收敛到相同的解。此外,如果算法使用的批处理小于完整数据集(batch_size < ncol (x)),然后mbkmeans会不会收敛到与kmeans即使初始化相同。这是因为kmeans而且mbkmeans有不同的最优搜索路径,问题是非凸的。

用于内存使用、速度和准确性的比较mbkmeanskmeans有关算法使用批处理的非平凡情况,请参见(Hicks et al. 2020),其中证明mbkmeans提供显著的速度改进和使用较少的内存kmeans,而不影响准确性。

5与恫吓一起使用

咆哮package为在Bioconductor包/工作流中进行集群提供了灵活和可扩展的框架。的clusterRows ()函数控制对不同聚类算法的调度。在本例中,我们将使用小批量k-means算法基于主成分分析(PCA)坐标将细胞聚类为细胞群。

mat <- reducedDim(sce1000, "PCA")
## [1] 100 20

在以下三个场景中,我们将集群中心的数量作为一个数字传递中心= 5论点。此外,我们还可以通过其他mbkmeans参数(如。batch_size = 10).在前两种情况下,我们只返回集群标签。然而,在第三个场景中,我们要求全部mbkmeans输出。

library(bluster) clusterRows(mat, MbkmeansParam(centers=5))
# #[1] 2 5 5 5 4 3 1 1 3 5 1 2 5 1 1 1 3 5 3 2 1 5 5 1 3 1 1 5 1 3 4 5 1 2 1 4 # #[38] 5 5 5 4 5 4 5 4 3 2 1 3 5 5 5 1 3 2 5 4 1 3 5 4 1 1 3 5 2 4 5 4 1 5 4 1 # #[75] 5 3 1 5 3 1 2 1 4 1 2 5 4 5 1 1 5 1 4 2 4 2 5 1 2 # #级别:1 2 3 4 5
clusterRows(mat, MbkmeansParam(centers=5, batch_size=10))
# #[1] 5 5 3 3 3 3 3 3 3 3 3 1 3 5 5 5 5 3 3 3 4 5 3 3 5 5 5 3 3 3 4 5 1 5 4 # #[38] 3 3 3 3 3 3 3 3 3 3 3 3 3 1 5 1 3 5 4 3 3 4 5 5 3 2 3 3 3 3 3 3 3 5 # #[75] 3 3 3 3 5 4 5 3 5 1 3 4 5 5 5 3 3 3 3 3 3 5 4 # #级别:1 2 3 4 5
clusterRows(mat, MbkmeansParam(centers=5, batch_size=10), full = TRUE)
# # # # $集群[1]1 1 5 5 5 5 5 5 5 5 5 2 5 3 1 1 1 5 5 5 5 5 5 1 5 1 1 5 5 5 5 1 2 1 5 # #[38]5 5 5 5 5 5 5 5 5 5 5 5 5 2 1 5 1 2 5 5 5 5 5 5 1 1 5 5 5 5 5 5 5 5 1 # #[75]5 5 5 5 1 5 1 5 1 2 1 1 5 5 5 5 5 5 5 5 4 5 1 5 # #级别:12 34 5 ## ## $objects ## $objects$mbkmeans ## $objects$mbkmeans$ centids ## [,1] [,2] [,3] [,4] [,4] [,4] [,5] [,5] [,5] [,] -15.010417 -0.7962079 4.968180 2.7679840 0.605855 -0.2194566 -1.4958129 ## [2,] 1.398788 15.2268393 -4.914318 8.7031508 0.624902 -2.6562225 -0.8620272 ## [3,] -17.543300 -0.3406707 6.138011 4.3145411 -1.079512 0.6031462 3.6588221 ## [4,] 4.953126 -5.2662492 -1.885661 -1.303848 -0.6517419-0.3327930 ## [,8] [,9] [,10] [,11] [,12] [,13] ## [1,] 0.6686381 0.7806568 -1.1359341 1.1528491 -1.407013 -1.5457278 ## [2,] 3.2219319 -3.0456175 -0.2216553 -1.8928053 5.403923 2.9907297 ## [3,] -8.2619290 -4.0679099 -3.2909212 5.7171778 8.625866 -4.8241775 ## [4,] 3.3455593 -2.0061982 -1.3108509 -9.4799142 1.971986 -9.3333830 ## [5,] 0.4513868 -1.7769361 -1.2359026 0.4449523 0.151892 0.9781383 ## [,14] [,15] [,16] [,17] [,18] [,19] ## [1,] 1.6981873 -3.2334236 -0.7828917 -0.11174807 0.7921814 -2.0950737 ## [2,] -1.0326219 0.3752647 2.2624371 -2.48013345 2.6617969 2.6872741 ## [3,] 0.2712364 1.0289170 -5.9773702 2.34843262 1.5557200 3.6983167 ## [4,] 0.8668148 -1.5455810 -1.8839526 4.15320464 2.9828209 -2.4133479 ## [5,] 2.0870510 1.4041611 -0.3987755 0.06157393 0.6216171 0.4357754 ## [,20] ## [1,] 0.12192702 ## [2,] 2.21400473 ## [3,] -2.67676140 ## [4,] -0.06365159 ## [5,] 0.77074762 ## ## $objects$mbkmeans$WCSS_per_cluster ## numeric(0) ## ## $objects$mbkmeans$best_initialization ## [1] 1 ## ## $objects$mbkmeans$iters_per_initialization ## [,1] ## [1,] 17 ## ## $objects$mbkmeans$Clusters ## [1] 5 5 5 5 5 5 5 1 1 5 5 2 5 1 1 1 5 5 3 5 5 1 5 5 1 5 1 1 5 1 5 5 5 1 2 1 5 ## [38] 5 5 5 5 5 5 5 5 5 1 5 5 5 5 2 1 5 2 5 5 1 5 5 5 5 1 1 5 5 5 5 5 5 1 5 5 1 ## [75] 5 5 1 5 5 1 5 1 5 1 2 5 5 5 1 1 5 1 5 5 5 5 4 5 1 5

虽然很多时候集群将在内存数据上执行(例如在PCA之后),但是clusterRows函数还接受任何类似矩阵的对象(内存中或磁盘上的数据表示)mbkmeans接受。

例如,我们可以使用mbkmeanslogcounts化验sce1000对象(类似于上面),它是一个DelayedMatrix对象的DelayedArray包中。

请注意:我们将矩阵转置为clusterRows函数期望行上的观测值和列上的变量。

logcounts (sce1000)
## <1000 x 100>类DelayedMatrix和类型“double”:##[,1][,2][,3]…[,99] [,100] ## ensg00000090382 0.000000 1.482992 0.000000。5.4330604 0.0000000 ## ensg00000204287 2.198815 0.000000 0.000000。5.3387971 0.0000000 ## ensg00000163220 1.762993 1.482992 0.000000。2.1176311 2.0642508 ## ensg00000143546 0.000000 1.135438 1.113099。0.3825221 0.0000000 ## ensg00000019582 3.402730 1.762861 1.733874。6.2009459 2.0642508 ## ... ... ...## ensg00000145779 0.0000000 0.6766523 0.0000000。0.9342195 0.0000000 ## ensg00000106948 0.0000000 1.1354382 0.0000000。0.9342195 1.3735556 ## ensg00000155660 0.0000000 0.6766523 0.0000000。 0.3825221 1.3735556 ## ENSG00000117748 0.0000000 0.0000000 0.0000000 . 0.0000000 0.0000000 ## ENSG00000135968 0.0000000 0.0000000 0.0000000 . 0.3825221 0.0000000
clusterRows (t (logcounts (sce1000)), MbkmeansParam(中心= 4))
# #[1] 2 2 2 1 2 2 1 3 3 1 2 2 2 3 3 3 1 2 3 1 2 3 2 2 3 1 2 3 3 3 1 2 2 3 2 3 2 # #[38] 2 2 2 2 2 2 2 2 1 3 1 2 2 2 2 3 1 2 4 2 3 2 1 2 2 3 3 1 2 2 2 2 2 3 2 2 3 # #[75] 2 1 3 2 1 3 2 3 2 3 2 2 2 2 3 3 2 3 2 2 2 2 2 2 3 2 # #级别:1 2 3 4

6在Bioconductor中使用磁盘数据

这个小插图的重点是使用mbkmeans包中。对于有兴趣了解有关使用的更多信息的用户HDF5文件和磁盘上的数据在Bioconductor,我们推荐优秀的DelayedArray车间,由彼得·希基在Bioc2020

参考文献

Arthur, David, Sergei Vassilvitskii, 2007。k - means++:小心播种的优势在第十八届Acm-Siam离散算法研讨会论文集1027 - 35。工业学会;应用数学。

希克斯,斯蒂芬妮·C,刘若曦,倪雨薇,伊丽莎白·珀多姆,达维德·里索,2020。Mbkmeans:使用小批量K-Means对单细胞数据进行快速聚类bioRxivhttps://doi.org/10.1101/2020.05.27.119438

大卫·斯卡利,2010年。“网络规模的k均值聚类。”在第19届万维网国际会议论文集1177 - 8。ACM。