劉小澤寫於2020.7.18
爲何取名叫“交響樂”?因爲單細胞分析就像一個大樂團,需要各個流程的協同配合
單細胞交響樂1-常用的數據結構SingleCellExperiment
單細胞交響樂2-scRNAseq從實驗到下游簡介
單細胞交響樂3-細胞質控
單細胞交響樂4-歸一化
單細胞交響樂5-挑選高變化基因
單細胞交響樂6-降維
單細胞交響樂7-聚類分羣
單細胞交響樂8-marker基因檢測
單細胞交響樂9-細胞類型註釋
單細胞交響樂9-細胞類型註釋
單細胞交響樂10-數據集整合後的批次矯正
單細胞交響樂11-多樣本間差異分析
單細胞交響樂12-檢測Doublet
單細胞交響樂13-細胞週期推斷
單細胞交響樂14-細胞軌跡推斷
單細胞交響樂15-scRNA與蛋白丰度信息結合
1 前言
scRNA-seq技術越來越成熟,測的細胞數也在日益增長,越來越多的研究結果發表在GEO數據庫中,而且還有大型單細胞項目的開展(例如人類圖譜計劃HCA)。因此分析方法需要考慮到逐漸龐大的數據集,這次就來看看怎麼做可以幫助我們獲得更快的處理速度和分析效率。
2 快速估算
2.1 近似而非精確的近鄰搜索
在高維空間中對近鄰細胞進行判斷基本上是必備流程,像buildSNNGraph()
, doubletCells()
都是需要經歷這一步。默認是利用KNN(k-nearest neighbours)算法找到更準確的近鄰數量,而犧牲速度。但是大型數據更需要的是速度,例如這個BiocNeighbors
R包就可以通過BNPARAM=
輕鬆轉換近鄰搜索方法
以pbmc數據爲例,這個數據之前應該分享過
load('clustered.sce.pbmc.RData')
sce.pbmc
## class: SingleCellExperiment
## dim: 33694 3922
## metadata(1): Samples
## assays(2): counts logcounts
## rownames(33694): RP11-34P13.3 FAM138A ... AC213203.1 FAM231B
## rowData names(2): ID Symbol
## colnames(3922): AAACCTGAGAAGGCCT-1 AAACCTGAGACAGACC-1 ...
## TTTGTCACAGGTCCAC-1 TTTGTCATCCCAAGAT-1
## colData names(4): Sample Barcode sizeFactor label
## reducedDimNames(3): PCA TSNE UMAP
## altExpNames(0):
看到這裏的數據是經過了PCA、t-SNE、UMAP降維操作的,並已經做好了分羣,使用的也是默認的精確KNN搜索。
下面使用近似搜索:
AnnoyParam
的解釋是:A class to hold parameters for the Annoy algorithm for approximate nearest neighbor identification. 也就是它包裝了近似搜索的一套參數,並傳遞給buildSNNGraph
library(scran)
library(BiocNeighbors)
snn.gr <- buildSNNGraph(sce.pbmc, BNPARAM=AnnoyParam(), use.dimred="PCA")
clusters <- igraph::cluster_walktrap(snn.gr)
table(Exact=colLabels(sce.pbmc), Approx=clusters$membership)
這裏因爲數據量不大,並看不出速度上的優勢,只是爲了證明二者在準確度上相差無幾
2.2 奇異值分解
術語叫做:singular value decomposition (SVD),在 denoisePCA()
, fastMNN()
, doubletCells()
都有應用。默認使用base::svd()
也是進行了精確的計算,同樣不適合大型數據集。好在 irlba
和rsvd
兩個R包都提供了近似計算方法,具體的參數配置和AnnoyParam
一樣也是做成了BiocSingular
包的一個函數
library(scater)
library(BiocSingular)
# 方法一:randomized SVD (RSVD)
set.seed(101000)
r.out <- runPCA(sce.pbmc, ncomponents=20, BSPARAM=RandomParam())
str(reducedDim(r.out))
## num [1:3922, 1:20] 15.3 13.41 -8.46 -7.86 6.38 ...
## - attr(*, "dimnames")=List of 2
## ..$ : chr [1:3922] "AAACCTGAGAAGGCCT-1" "AAACCTGAGACAGACC-1" "AAACCTGAGGCATGGT-1" "AAACCTGCAAGGTTCT-1" ...
## ..$ : chr [1:20] "PC1" "PC2" "PC3" "PC4" ...
## - attr(*, "percentVar")= num [1:20] 20.26 10.02 5.36 2.19 1.41 ...
## - attr(*, "rotation")= num [1:500, 1:20] 0.2015 0.182 0.1764 0.1067 0.0649 ...
## ..- attr(*, "dimnames")=List of 2
## .. ..$ : chr [1:500] "LYZ" "S100A9" "S100A8" "HLA-DRA" ...
## .. ..$ : chr [1:20] "PC1" "PC2" "PC3" "PC4" ...
# 方法二:IRLBA
set.seed(101001)
i.out <- runPCA(sce.pbmc, ncomponents=20, BSPARAM=IrlbaParam())
str(reducedDim(i.out))
## num [1:3922, 1:20] 15.3 13.41 -8.46 -7.86 6.38 ...
## - attr(*, "dimnames")=List of 2
## ..$ : chr [1:3922] "AAACCTGAGAAGGCCT-1" "AAACCTGAGACAGACC-1" "AAACCTGAGGCATGGT-1" "AAACCTGCAAGGTTCT-1" ...
## ..$ : chr [1:20] "PC1" "PC2" "PC3" "PC4" ...
## - attr(*, "percentVar")= num [1:20] 20.26 10.02 5.36 2.19 1.41 ...
## - attr(*, "rotation")= num [1:500, 1:20] 0.2015 0.182 0.1764 0.1067 0.0649 ...
## ..- attr(*, "dimnames")=List of 2
## .. ..$ : chr [1:500] "LYZ" "S100A9" "S100A8" "HLA-DRA" ...
## .. ..$ : chr [1:20] "PC1" "PC2" "PC3" "PC4" ...
這兩種方法的速度都比準確的SVD方法快,丟失的準確度也微乎其微,也因此被scran和scater包設爲了默認的參數,也因此需要設置隨機種子(畢竟都是估計的方法,每次運行結果都不一致)。當然,IRLBA相比RSVD更準確,但速度不如RSVD。
3 並行計算
3.1 爲什麼?
R 採用的是內存計算模式(In-Memory),被處理的數據需要預取到主存(RAM)中。其優點是計算效率高、速度快,但缺點是這樣一來能處理的問題規模就非常有限(小於 RAM 的大小)。另一方面,R 的核心(R core)是一個單線程的程序,在多核處理器上,R 無法有效地利用所有的計算內核。即使機器性能很強大,有32個核心,但它也只能使用1/32的計算能力,浪費了31/32。
3.2 怎麼做?
使用BiocParallel
包,可以將並行運算覆蓋到基於Bioconductor的分析中
不同的硬件和操作系統,選擇的並行方法也不同
library(BiocParallel)
registered() #可以看看支持哪些類型的加速,最頂上的是默認的
一般包括:
- SerialParam:全平臺支持
- MulticoreParam:適用於Unix和Mac。在windows上它等同於SerialParam
- SnowParam:全平臺支持
- BatchtoolsParam:集羣
- DoparParam:全平臺支持
如果要更改
# 本來的default是 MulticoreParam
default <- registered()
# 現在改成BatchtoolsParam
register(BatchtoolsParam(workers = 10), default = TRUE)
names(registered())
## [1] "BatchtoolsParam" "MulticoreParam" "SnowParam" "SerialParam"
# 要再恢復原來的設置
for (param in rev(default)) register(param)
可以這麼使用
# 不同的方法
dec.pbmc.mc <- modelGeneVar(sce.pbmc, BPPARAM=MulticoreParam(2))
dec.pbmc.snow <- modelGeneVar(sce.pbmc, BPPARAM=SnowParam(5))
在SLURM HPC中,可以使用BatchtoolsParam
參考:https://bioconductor.org/packages/3.11/BiocParallel/vignettes/BiocParallel_BatchtoolsParam.pdf
# 設置每個任務2小時、8G內存、1CPU,總共10個任務
bpp <- BatchtoolsParam(10, cluster="slurm",
resources=list(walltime=7200, memory=8000, ncpus=1))
注意
- 這個並行計算只是加速了CPU的計算速度,但如果任務受限於內存或硬盤的讀入讀出,它依然是沒辦法加速的;
- R實現多線程還是很麻煩的,它的操作邏輯是:先設置一個或多個session(對話窗口);然後加載相關的包;session之間進行數據傳遞。可能最後還不如單線程運行效果好
4 可能會遇到內存不足
想一下,我們處理的核心是不是基於表達矩陣?既然是核心,就需要完全載入內存中,然後才能實現後面的順利讀取、處理。現在單細胞的表達矩陣有兩種形式:稀疏矩陣dgCMatrix
或者普通矩陣matrix
。如果我們的數據是10X產生的130萬個腦細胞數據,如果是以普通矩陣讀入,就需要消耗100G內存,即使使用稀疏矩陣,也需要消耗30G內存左右。因此沒有很好的服務器基本上幹不了這個事。
用處理速度換取內存不足
如果真的面臨無法增加內存的困境,還有一個plan B,就是用硬盤空間來存儲數據,必要時再調用一部分數據到內存,雖然這一來一回很影響處理速度,但畢竟可以用。
使用這個HDF5Array
R包可以做到(類似的還有 bigmemory
, matter
),它會將底層數據做成HDF5格式
例如,從130萬個腦細胞數據中選取了2萬個
library(TENxBrainData)
sce.brain <- TENxBrainData20k()
sce.brain
## class: SingleCellExperiment
## dim: 27998 20000
## metadata(0):
## assays(1): counts
## rownames: NULL
## rowData names(2): Ensembl Symbol
## colnames: NULL
## colData names(4): Barcode Sequence Library Mouse
## reducedDimNames(0):
## altExpNames(0):
看一下這個表達矩陣,顯然是一個HDF5的矩陣
counts(sce.brain)
## <27998 x 20000> matrix of class HDF5Matrix and type "integer":
## [,1] [,2] [,3] [,4] ... [,19997] [,19998] [,19999]
## [1,] 0 0 0 0 . 0 0 0
## [2,] 0 0 0 0 . 0 0 0
## [3,] 0 0 0 0 . 0 0 0
## [4,] 0 0 0 0 . 0 0 0
## [5,] 0 0 0 0 . 0 0 0
## ... . . . . . . . .
## [27994,] 0 0 0 0 . 0 0 0
## [27995,] 0 0 0 1 . 0 2 0
## [27996,] 0 0 0 0 . 0 1 0
## [27997,] 0 0 0 0 . 0 0 0
## [27998,] 0 0 0 0 . 0 0 0
## [,20000]
## [1,] 0
## [2,] 0
## [3,] 0
## [4,] 0
## [5,] 0
## ... .
## [27994,] 0
## [27995,] 0
## [27996,] 0
## [27997,] 0
## [27998,] 0
看一下這個大小
object.size(counts(sce.brain))
## 2328 bytes
但實際上這個底層數據的大小是
file.info(path(counts(sce.brain)))$size
## [1] 76264332
歡迎關注我們的公衆號~_~
我們是兩個農轉生信的小碩,打造生信星球,想讓它成爲一個不拽術語、通俗易懂的生信知識平臺。需要幫助或提出意見請後臺留言或發送郵件到[email protected]