DeepTaxa Tutorial: Classifying V3-V4 16S ASVs and Validating Against a Mock Community
Open In Colab
A 16S survey produces a set of amplicon sequence variants (ASVs), and the analytical goal is to determine which organisms they represent and how far down the taxonomy the names can be trusted. This notebook pursues that goal with DeepTaxa on V3-V4 reads from a community of known composition, the ZymoBIOMICS Microbial Community Standard, where each assignment can be checked directly.
The key choice when using DeepTaxa is to match the model checkpoint to the sequenced region. DeepTaxa provides region-specific checkpoints; these reads are V3-V4, so the V3-V4 checkpoint is used. The sample is the ZymoBIOMICS standard, eight known bacteria, sequenced 2 x 300 on an Illumina MiSeq over V3-V4 (accession SRR35133066). The analysis begins from ASVs produced with DADA2; the Appendix details that step. The notebook runs on a free Colab GPU.
1 Install
!pip install -q deeptaxa-rrnaimport pandas as pd, torchif torch.cuda.is_available(): g = torch.cuda.get_device_properties(0)print(f"GPU: {g.name}, {g.total_memory //1024**3} GB, compute {g.major}.{g.minor}, CUDA {torch.version.cuda}")else:print("No GPU detected. In Colab: Runtime > Change runtime type > GPU, then run again.")
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/82.7 kB ? eta -:--:--
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 82.7/82.7 kB 5.2 MB/s eta 0:00:00
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/3.2 MB ? eta -:--:--
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸ 3.2/3.2 MB 104.4 MB/s eta 0:00:01
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.2/3.2 MB 68.5 MB/s eta 0:00:00
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/425.6 kB ? eta -:--:--
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 425.6/425.6 kB 39.5 MB/s eta 0:00:00
GPU: Tesla T4, 14 GB, compute 7.5, CUDA 12.8
2 The sequences
Fifteen ASVs were inferred from a ZymoBIOMICS Microbial Community Standard (Zymo Research) sequenced over the V3-V4 region, from the public SRA run SRR35133066. The Appendix shows how they were produced.
A single command performs the classification. --tabular writes one row per sequence with a column per rank.
!deeptaxa predict --fasta-file asvs.fasta --checkpoint deeptaxa-v3v4-v2.pt --output-dir out --tabularpred = pd.read_csv("out/asvs_deeptaxa_predictions.tsv", sep="\t").set_index("sequence_id")counts = counts.reindex(pred.index) # align read counts to the classified ASVs
2026-06-27 09:05:36,373 - INFO -
======================================================================
DeepTaxa Prediction Session (v1.1.0)
--------------------------------------------------
Started: 2026-06-27T09:05:36.373131
======================================================================
config.json: 100% 904/904 [00:00<00:00, 3.09MB/s]
configuration_bert.py: 100% 1.01k/1.01k [00:00<00:00, 2.82MB/s]
[transformers] A new version of the following files was downloaded from https://huggingface.co/zhihan1996/DNABERT-2-117M:
- configuration_bert.py
. Make sure to double-check they do not contain any added malicious code. To avoid downloading new versions of the code file, you can pin a revision.
tokenizer_config.json: 100% 158/158 [00:00<00:00, 701kB/s]
Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads.
2026-06-27 09:05:37,959 - WARNING - Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads.
tokenizer.json: 100% 168k/168k [00:00<00:00, 85.5MB/s]
2026-06-27 09:05:39,130 - INFO - Initialized HybridCNNBERTClassifier with CNN: {'embed_dim': 896, 'num_filters': 256, 'kernel_sizes': [3, 5, 7], 'num_conv_layers': 1, 'dropout_prob': 0.2}, BERT hidden_size=896, output_attentions=False
2026-06-27 09:05:39,291 - INFO - Model loaded from checkpoint: deeptaxa-v3v4-v2.pt with type: hybridcnnbert
2026-06-27 09:05:39,987 - INFO - Loaded 15 sequences from asvs.fasta
Predicting: 100% 1/1 [00:01<00:00, 1.68s/it]
2026-06-27 09:05:41,671 - INFO - Saved run UUID to out/deeptaxa_uuid.txt
2026-06-27 09:05:41,672 - INFO -
======================================================================
DeepTaxa Prediction Summary (v1.1.0)
--------------------------------------------------
Here's a summary of your prediction results:
- Total Sequences Processed: 15
- Prediction Time: 5.30 seconds
- Completed At: 2026-06-27T09:05:41.671186
======================================================================
2026-06-27 09:05:41,672 - INFO - Performance Metrics by Taxonomic Rank:
2026-06-27 09:05:41,672 - INFO - Rank | Mean Score | Std Score | Accuracy | Top-{top_k} Acc | F1 | Precision | Recall | AUC
2026-06-27 09:05:41,672 - INFO - ---------------------------------------------------------------------------------------------------------------------------------
2026-06-27 09:05:41,672 - INFO - domain | 1.0000 | 0.0000 | N/A | N/A | N/A | N/A | N/A | N/A
2026-06-27 09:05:41,673 - INFO - phylum | 1.0000 | 0.0001 | N/A | N/A | N/A | N/A | N/A | N/A
2026-06-27 09:05:41,673 - INFO - class | 1.0000 | 0.0000 | N/A | N/A | N/A | N/A | N/A | N/A
2026-06-27 09:05:41,673 - INFO - order | 0.9993 | 0.0016 | N/A | N/A | N/A | N/A | N/A | N/A
2026-06-27 09:05:41,673 - INFO - family | 0.9665 | 0.1220 | N/A | N/A | N/A | N/A | N/A | N/A
2026-06-27 09:05:41,674 - INFO - genus | 0.9731 | 0.0962 | N/A | N/A | N/A | N/A | N/A | N/A
2026-06-27 09:05:41,674 - INFO - species | 0.8010 | 0.2472 | N/A | N/A | N/A | N/A | N/A | N/A
2026-06-27 09:05:41,894 - INFO - Saved prediction results to: out/asvs_deeptaxa_predictions.json
2026-06-27 09:05:41,909 - INFO - Saved tabular prediction results to: out/asvs_deeptaxa_predictions.tsv
2026-06-27 09:05:41,909 - INFO -
======================================================================
Thank you for using DeepTaxa 🤗
======================================================================
5 Read the predictions
Each rank has a predicted label and a raw_score, the model’s confidence in that label, from 0 to 1. Confidence is high on a region-matched amplicon and falls at the deeper ranks, because the 16S gene carries less information about species than about phylum. A low score means the model is uncertain and should be treated as provisional. Where DeepTaxa cannot resolve a species, it keeps the genus and returns it with an “Unclassified_” prefix, for example “Unclassified_Escherichia”, rather than forcing a species call.
The sample contains eight known genera, so the result can be checked. DeepTaxa reports GTDB names, which differ from the NCBI names of the standard: Lactobacillus fermentum is Limosilactobacillus in GTDB, Pseudomonas may appear as Pseudomonas_E, and Escherichia and Shigella are reported together. The short function below reduces a label to a plain genus name so the two can be compared.
For comparison, the result of a conventional pipeline is loaded as a reference: DADA2 with the SILVA v138 database. That pipeline classifies the genus with a naive Bayes model and assigns a species only by exact matching against the reference. It is labeled DADA2 + SILVA below, since SILVA itself is the reference database, not the classifier.
import resilva = pd.read_csv(f"{base}/v3v4_silva.tsv", sep="\t").set_index("ASV").reindex(pred.index)def base_genus(name):ifnotisinstance(name, str): # missing genus (NaN)returnNone name = re.sub(r"[ _-].*", "", name).lower() # drop GTDB suffixes and "sensu stricto"return {"limosilactobacillus": "lactobacillus", "shigella": "escherichia"}.get(name, name)EXPECTED = {"pseudomonas", "escherichia", "salmonella", "lactobacillus","enterococcus", "staphylococcus", "listeria", "bacillus"}dt_genus = pred["genus_predicted"].map(base_genus)sv_genus = silva["Genus"].map(base_genus)print("DeepTaxa recovered", len(set(dt_genus) & EXPECTED), "of 8 genera")print("DADA2 + SILVA recovered", len(set(sv_genus.dropna()) & EXPECTED), "of 8 genera")print("They agree on the genus of",round(counts[dt_genus == sv_genus].sum() / counts.sum() *100), "% of reads")
DeepTaxa recovered 8 of 8 genera
DADA2 + SILVA recovered 8 of 8 genera
They agree on the genus of 100 % of reads
7 Species: where the two methods differ
At the species rank the methods diverge. The table lists the calls for the most abundant ASVs; a single-word entry is a genus only, where the method stopped, and a two-word entry is a species. DADA2 + SILVA assigns a species only on an exact, unambiguous reference match, so here it stops at the genus on all but a few low-abundance ASVs. Those genus-only entries are reads it declined to name rather than reads it named incorrectly, and every species it does assign is correct. DeepTaxa names a species for a much larger share of the reads, but from this short region it too stops at the genus on several ASVs, such as Staphylococcus, Escherichia, and Listeria, where the V3-V4 window does not support a confident species call. Where it does name a species, the call is occasionally a close relative of the expected organism, such as Shigella for Escherichia coli. The full-length example resolves species more reliably.
The calls reduce to a single set of numbers: the share of reads reaching the correct species. DADA2 + SILVA is credited for exact matches only; DeepTaxa is credited for exact matches, and separately for exact matches plus close relatives that 16S cannot separate from the expected organism.
Reads correctly identified to species (%):
DADA2 + SILVA, exact: 4
DeepTaxa, exact: 32
DeepTaxa, exact or close relative: 52
8 Summary
DeepTaxa recovered all eight genera, agreed with DADA2 + SILVA on the genus of essentially every read, and named a species for many more reads than the reference method, though from this short region it stopped at the genus on some ASVs. The two lessons that carry to other datasets are to use the checkpoint that matches the sequenced region, and to read the confidence score as a measure of information rather than a guarantee, filtering low-confidence calls. The full-length example shows the same workflow where the longer gene supports species-level assignment.
9 Appendix: how the ASVs were made
The ASVs were produced offline from raw reads with primer removal and DADA2.