Naive Bayes classifier trained on a custom NCBI RefSeq V3-V4 database classifies almost all ASVs as same species

Hello,

I am currently using QIIME 2 2026.1.

Previously, I built a custom full-length NCBI RefSeq 16S classifier using rescript get-ncbi-data with BioProject 33175 (Bacteria). I first created this workflow in 2023 and have continued using essentially the same pipeline through QIIME 2 2025.10. The full-length classifier has consistently produced reasonable taxonomic assignments.

After upgrading to QIIME 2 2026.1, since our sequencing data target the V3-V4 region (341F/805R), I decided to build a region-specific classifier instead of continuing to use the full-length classifier. While reading previous discussions on the forum, I learned that the recommended workflow is to dereplicate both before and after extract-reads, so I updated my pipeline accordingly.

However, after training the classifier with fit-classifier-naive-bayes, almost every ASV is classified as:

k__Pseudomonadati; p__Pseudomonadota; c__Gammaproteobacteria; o__Pseudomonadales; f__Pseudomonadaceae; g__Pseudomonas; s__batumici

regardless of the input sequence.

I also found this previous discussion:

The reported symptom looks very similar to mine, but that issue seemed to be caused by very short sequences generated during extract-reads. In my workflow, I already use --p-min-length 300 and --p-max-length 550, so I do not think that explanation applies to my case.

To better understand the problem, I compared the results using different classification methods.

  • The full-length classifier produces diverse taxonomic assignments as expected.
  • classify-consensus-blast using the same V3-V4 reference sequences and taxonomy also returns diverse taxonomic assignments.
  • However, the Naive Bayes classifier trained from the same V3-V4 reference database classifies nearly all ASVs as Pseudomonas batumici.

Because the BLAST-based classification appears reasonable, I wonder whether the issue lies in my classifier training workflow rather than in the reference database itself.

Below are the commands I used to build the classifier and perform taxonomic classification.

Workflow of how I trained it:

qiime rescript get-ncbi-data \
    --p-query '33175[BioProject] OR 33317[BioProject]' \
    --o-sequences ncbi-refseqs-unfiltered.qza \
    --o-taxonomy ncbi-refseqs-taxonomy-unfiltered.qza

qiime rescript filter-seqs-length-by-taxon \
    --i-sequences ncbi-refseqs-unfiltered.qza \
    --i-taxonomy ncbi-refseqs-taxonomy-unfiltered.qza \
    --p-labels Archaea Bacteria \
    --p-min-lens 900 1200 \
    --o-filtered-seqs ncbi-refseqs.qza \
    --o-discarded-seqs ncbi-refseqs-tooshort.qza

qiime rescript filter-taxa \
    --i-taxonomy ncbi-refseqs-taxonomy-unfiltered.qza \
    --m-ids-to-keep-file ncbi-refseqs.qza \
    --o-filtered-taxonomy ncbi-refseqs-taxonomy.qza

qiime rescript dereplicate \
--i-sequences ncbi-refseqs.qza \
--i-taxa ncbi-refseqs-taxonomy.qza \
--p-mode 'uniq' \
--o-dereplicated-sequences ncbi-refseqs-derep-uniq.qza \
--o-dereplicated-taxa ncbi-refseqs-taxonomy-derep-uniq.qza

qiime rescript evaluate-fit-classifier \
    --i-sequences ncbi-refseqs-derep-uniq.qza \
    --i-taxonomy ncbi-refseqs-taxonomy-derep-uniq.qza \
    --o-classifier ncbi-refseqs-classifier.qza \
    --o-evaluation ncbi-refseqs-classifier-evaluation.qzv \
    --o-observed-taxonomy ncbi-refseqs-predicted-taxonomy.qza

qiime feature-classifier extract-reads \
    --i-sequences ncbi-refseqs-derep-uniq.qza \
    --p-f-primer CCTACGGGNGGCWGCAG \
    --p-r-primer GACTACHVGGGTATCTAATCC \
    --p-min-length 300 \
    --p-max-length 550 \
    --o-reads ncbi-refseqs-v3v4.qza

qiime rescript dereplicate \
--i-sequences ncbi-refseqs-v3v4.qza \
--i-taxa ncbi-refseqs-taxonomy-derep-uniq.qza \
--p-mode 'uniq' \
--o-dereplicated-sequences ncbi-refseqs-uniq-v3v4.qza \
--o-dereplicated-taxa ncbi-refseqs-taxonomy-v3v4.qza

qiime feature-classifier fit-classifier-naive-bayes \
  --i-reference-reads ncbi-refseqs-uniq-v3v4.qza \
  --i-reference-taxonomy ncbi-refseqs-taxonomy-v3v4.qza \
  --o-classifier ncbi-refseqs-v3v4-classifier.qza

After training the classifiers, I obtained the following taxonomic classification results:

qiime feature-classifier classify-sklearn \
  --i-reads DADA2_rep_seqs.qza \
  --i-classifier ncbi-refseqs-classifier.qza \
  --o-classification taxonomy_ncbi.qza

The full-length classifier produces diverse taxonomic assignments.

qiime feature-classifier classify-consensus-blast \
  --i-query DADA2_rep_seqs.qza \
  --i-reference-reads ncbi-refseqs-uniq-v3v4.qza \
  --i-reference-taxonomy ncbi-refseqs-taxonomy-v3v4.qza \
  --o-classification blast-taxonomy.qza \
  --o-search-results blast-search-results.qza

Using the same V3-V4 reference sequences with classify-consensus-blast also produces diverse taxonomic assignments.

qiime feature-classifier classify-sklearn \
  --i-reads DADA2_rep_seqs.qza \
  --i-classifier ncbi-refseqs-v3v4-classifier.qza \
  --o-classification taxonomy-v3v4_ncbi.qza

However, the V3-V4 Naive Bayes classifier predicts almost every ASV as Pseudomonas batumici.

I would appreciate any advice on the following questions:

  1. Is there anything incorrect or missing in my workflow for building a V3-V4 Naive Bayes classifier?
  2. Is there any known issue that could cause a classifier trained from a custom V3-V4 NCBI RefSeq database to assign nearly all ASVs to the same species?
  3. Since classify-consensus-blast returns diverse taxonomic assignments using the same reference sequences and taxonomy, could there be something wrong with my classifier generation process, or have I misunderstood an important step in training a region-specific Naive Bayes classifier?

Thank you very much for your time and assistance.

Hi @Kris_P,

Is this an issue with other project data, or just this project? Often this approach works well. I usually observe such patterns when the data set itself is awry, or the orientation of the reads is out of sync with the naïve bayes classifier. That is, the sequence data should be in the same orientation as the reference database. To aid in this situation you can use the rescript orient-reads action to correct your paired-end reads prior to denoising and then run naïve bayes classifier. Alternatively, you can use rescript orient-seqs, to re-orient your ASVs, prior to running the naïve bayes classifier.

You can also try constructing your reference database with extract-seq-segments approach to potentially improve the quality your16S rRNA gene NCBI classifier. Basically, just follow this tutorial after the extract reads step.

Finally, is there a reason why you are not using SILVA, GTDB, or Greengenes2 for this? Note: the upcoming QIIME 2 release will have the latest GTDB reference within RESCRIPt, but if you would like to use it now, you should be able to pip install the latest version of RESCRIPt from the GitHub repo.

Finally, I have a working draft of some tools that have been removed from RESCRIPt, and we are in the process of "adding them back" via a separate plugin called RESCRIPT-evaluate. This will enable you to evaluate the characteristics of the classifier you generate. That is, the equivalent RESCRIPt evaluation commands within this tutorial should be replaced with the same-named commands of this new plugin (which requires RESCRIPt).