NEUral-network based Cell Annotation, NeuCA
, is a tool for cell type annotation using single-cell RNA-seq data. It is a supervised cell label assignment method that uses existing scRNA-seq data with known labels to train a neural network-based classifier, and then predict cell labels in single-cell RNA-seq data of interest.
NeuCA 1.6.0
The fast advancing single cell RNA sequencing (scRNA-seq) technology enables transcriptome study in heterogeneous tissues at a single cell level. The initial important step of analyzing scRNA-seq data is to accurately annotate cell labels. We present a neural-network based cell annotation method NeuCA
.
When closely correlated cell types exist, NeuCA
uses the cell type tree information through a hierarchical structure of neural networks to improve annotation accuracy. Feature selection is performed in hierarchical structure to further improve classification accuracy. When cell type correlations are not high, a feed-forward neural network is adopted.
NeuCA
depends on the following packages:
SingleCellExperiment
classThe scRNA-seq data input for NeuCA
must be objects of the Bioconductor SingleCellExperiment. You may need to read corresponding vignettes on how to create a SingleCellExperiment from your own data. An example is provided here to show how to do that, but please note this is not a comprehensive guidance for SingleCellExperiment.
Step 1: Load in example scRNA-seq data.
We are using two example datasets here: Baron_scRNA
and Seg_scRNA
. Baron_scRNA
is a droplet(inDrop)-based, single-cell RNA-seq data generated from pancrease (Baron et al.). Around 10,000 human and 2,000 mouse pancreatic cells from four cadaveric donors and two strains of mice were sequenced. Seg_scRNA
is a Smart-Seq2 based, single-cell RNA-seq dataset (Segerstolpe et al.). It has thousands of human islet cells from healthy and type-2 diabetic donors. A total of 3,386 cells were collected, with around 350 cells from each donor. Here, subsets of these two datasets (with cell type labels for each cell) were included as examples.
library(NeuCA)
data("Baron_scRNA")
data("Seg_scRNA")
Step 2a: Prepare training data as a SingleCellExperiment object.
Baron_anno = data.frame(Baron_true_cell_label, row.names = colnames(Baron_counts))
Baron_sce = SingleCellExperiment(
assays = list(normcounts = as.matrix(Baron_counts)),
colData = Baron_anno
)
# use gene names as feature symbols
rowData(Baron_sce)$feature_symbol <- rownames(Baron_sce)
# remove features with duplicated names
Baron_sce <- Baron_sce[!duplicated(rownames(Baron_sce)), ]
Step 2b: Similarly, prepare testing data as a SingleCellExperiment object. Note the true cell type labels are not necessary (and of course often not available).
Seg_anno = data.frame(Seg_true_cell_label, row.names = colnames(Seg_counts))
Seg_sce <- SingleCellExperiment(
assays = list(normcounts = as.matrix(Seg_counts)),
colData = Seg_anno
)
# use gene names as feature symbols
rowData(Seg_sce)$feature_symbol <- rownames(Seg_sce)
# remove features with duplicated names
Seg_sce <- Seg_sce[!duplicated(rownames(Seg_sce)), ]
Step 3: with both training and testing data as objects in SingleCellExperiment
class, now we can train the classifier in NeuCA
and predict testing dataset’s cell types. This process can be achieved with one line of code:
predicted.label = NeuCA(train = Baron_sce, test = Seg_sce,
model.size = "big", verbose = FALSE)
#Baron_scRNA is used as the training scRNA-seq dataset
#Seg_scRNA is used as the testing scRNA-seq dataset
NeuCA
can detect whether highly-correlated cell types exist in the training dataset, and automatically determine if a general neural-network model will be adopted or a marker-guided hierarchical neural-network will be adopted for classification.
[Tuning parameter] In neural-network, the numbers of layers and nodes are tunable parameters. Users have the option to determine the complexity of the neural-network used in NeuCA
by specifying the desired model.size
argument. Here, “big”, “medium” and “small” are 3 possible choices, reflecting large, medium and small number of nodes and layers in neural-network, respectively. The model size details are shown in the following Table 1. From our experience, “big” or “medium” can often produce
high accuracy predictions.
Number of layers | Number of nodes in hidden layers | |
---|---|---|
Small | 3 | 64 |
Medium | 4 | 64,128 |
Big | 5 | 64,128,256 |
predicted.label
is a vector of the same length with the number of cells in the testing dataset, containing all cell’s predicted cell type. It can be viewed directly:
head(predicted.label)
## [1] "alpha" "gamma" "gamma" "gamma" "gamma" "alpha"
table(predicted.label)
## predicted.label
## alpha beta delta ductal endothelial gamma
## 328 109 56 65 9 135
[Optional] If you have the true cell type labels for the testing dataset, you may evaluate the predictive performance by a confusion matrix:
table(predicted.label, Seg_true_cell_label)
## Seg_true_cell_label
## predicted.label alpha beta delta ductal endothelial gamma
## alpha 328 0 0 0 0 0
## beta 0 109 0 0 0 0
## delta 0 0 56 0 0 0
## ductal 1 0 0 64 0 0
## endothelial 0 0 0 0 9 0
## gamma 0 0 0 0 0 135
You may also draw a Sankey diagram to visualize the prediction accuracy:
## R version 4.3.0 RC (2023-04-13 r84269)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 22.04.2 LTS
##
## Matrix products: default
## BLAS: /home/biocbuild/bbs-3.17-bioc/R/lib/libRblas.so
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.10.0
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=en_GB LC_COLLATE=C
## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
##
## time zone: America/New_York
## tzcode source: system (glibc)
##
## attached base packages:
## [1] stats4 stats graphics grDevices utils datasets methods
## [8] base
##
## other attached packages:
## [1] networkD3_0.4 kableExtra_1.3.4
## [3] knitr_1.42 NeuCA_1.6.0
## [5] SingleCellExperiment_1.22.0 SummarizedExperiment_1.30.0
## [7] Biobase_2.60.0 GenomicRanges_1.52.0
## [9] GenomeInfoDb_1.36.0 IRanges_2.34.0
## [11] S4Vectors_0.38.0 BiocGenerics_0.46.0
## [13] MatrixGenerics_1.12.0 matrixStats_0.63.0
## [15] e1071_1.7-13 limma_3.56.0
## [17] keras_2.11.1 BiocStyle_2.28.0
##
## loaded via a namespace (and not attached):
## [1] xfun_0.39 bslib_0.4.2 htmlwidgets_1.6.2
## [4] lattice_0.21-8 vctrs_0.6.2 tools_4.3.0
## [7] tfruns_1.5.1 bitops_1.0-7 generics_0.1.3
## [10] proxy_0.4-27 pkgconfig_2.0.3 Matrix_1.5-4
## [13] webshot_0.5.4 lifecycle_1.0.3 GenomeInfoDbData_1.2.10
## [16] compiler_4.3.0 stringr_1.5.0 munsell_0.5.0
## [19] htmltools_0.5.5 class_7.3-21 sass_0.4.5
## [22] RCurl_1.98-1.12 yaml_2.3.7 jquerylib_0.1.4
## [25] whisker_0.4.1 ellipsis_0.3.2 cachem_1.0.7
## [28] DelayedArray_0.26.0 rvest_1.0.3 digest_0.6.31
## [31] stringi_1.7.12 bookdown_0.33 fastmap_1.1.1
## [34] grid_4.3.0 colorspace_2.1-0 cli_3.6.1
## [37] magrittr_2.0.3 base64enc_0.1-3 scales_1.2.1
## [40] rmarkdown_2.21 XVector_0.40.0 httr_1.4.5
## [43] igraph_1.4.2 reticulate_1.28 png_0.1-8
## [46] evaluate_0.20 viridisLite_0.4.1 rlang_1.1.0
## [49] Rcpp_1.0.10 zeallot_0.1.0 glue_1.6.2
## [52] BiocManager_1.30.20 xml2_1.3.3 svglite_2.1.1
## [55] rstudioapi_0.14 jsonlite_1.8.4 R6_2.5.1
## [58] systemfonts_1.0.4 zlibbioc_1.46.0 tensorflow_2.11.0