TfidfVectorizer
NotFittedError
machine learning
natural language processing
Python debugging

NotFittedError TfidfVectorizer - Vocabulary wasn't fitted

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

NotFittedError: Vocabulary wasn't fitted means you tried to use TfidfVectorizer before it had learned a vocabulary from training text. In scikit-learn, vectorizers behave like other estimators: they must be fitted before they can transform new data. The fix is usually simple, but the deeper issue is making sure the same fitted vectorizer instance survives through the whole pipeline.

What TfidfVectorizer Learns During fit

TfidfVectorizer does two important things during fitting:

  • it builds a vocabulary from the training corpus
  • it computes inverse-document-frequency statistics

Until that happens, the vectorizer does not know which terms exist or how to map them into feature columns.

That is why this fails:

python
1from sklearn.feature_extraction.text import TfidfVectorizer
2
3vectorizer = TfidfVectorizer()
4vectorizer.transform(["hello world"])

The vectorizer has no fitted vocabulary yet, so transform() has nothing to work with.

The Correct Basic Pattern

Fit on training data first, then transform.

python
1from sklearn.feature_extraction.text import TfidfVectorizer
2
3train_texts = [
4    "machine learning is fun",
5    "text classification with tfidf",
6    "vectorizers need fitting",
7]
8
9test_texts = [
10    "machine learning",
11    "tfidf features",
12]
13
14vectorizer = TfidfVectorizer()
15X_train = vectorizer.fit_transform(train_texts)
16X_test = vectorizer.transform(test_texts)
17
18print(X_train.shape)
19print(X_test.shape)

fit_transform() is just a convenience method that performs fitting and transformation in one step for the training set.

A Very Common Cause: Reinitializing the Vectorizer

A frequent bug is fitting one instance and then accidentally creating a new one before prediction.

python
1from sklearn.feature_extraction.text import TfidfVectorizer
2
3train_texts = ["a document", "another document"]
4
5vectorizer = TfidfVectorizer()
6vectorizer.fit(train_texts)
7
8# Bug: a brand-new, unfitted instance replaces the old one.
9vectorizer = TfidfVectorizer()
10vectorizer.transform(["new text"])

The error message is correct here: the current object has never been fitted, even though an earlier object was.

Keep the Fitted Vectorizer Together With the Model

In text pipelines, the vectorizer and the classifier belong together. If you train the vectorizer on one machine or in one script and then predict elsewhere, save and reload the same fitted object.

python
1import joblib
2from sklearn.feature_extraction.text import TfidfVectorizer
3
4train_texts = ["first doc", "second doc"]
5vectorizer = TfidfVectorizer()
6vectorizer.fit(train_texts)
7
8joblib.dump(vectorizer, "vectorizer.joblib")
9loaded_vectorizer = joblib.load("vectorizer.joblib")
10
11print(loaded_vectorizer.transform(["first doc"]).shape)

If you save only the classifier and not the fitted vectorizer, prediction code will eventually fail or produce inconsistent features.

Pipelines Solve This Cleanly

Scikit-learn pipelines are often the best long-term solution because they keep fitting and transformation steps attached to the estimator.

python
1from sklearn.feature_extraction.text import TfidfVectorizer
2from sklearn.linear_model import LogisticRegression
3from sklearn.pipeline import Pipeline
4
5texts = ["good movie", "bad movie", "great film", "awful film"]
6labels = [1, 0, 1, 0]
7
8pipeline = Pipeline([
9    ("tfidf", TfidfVectorizer()),
10    ("clf", LogisticRegression()),
11])
12
13pipeline.fit(texts, labels)
14print(pipeline.predict(["great movie"]))

With a pipeline, you do not manually remember whether the vectorizer is fitted. The pipeline manages the lifecycle.

Vocabulary Edge Cases

Sometimes the error appears because the training corpus is empty after preprocessing. For example, if your stop-word removal or token pattern removes every token, the vocabulary can end up empty.

That situation often raises an empty-vocabulary error rather than NotFittedError, but the lesson is similar: inspect the actual training text after preprocessing, not just before it.

Common Pitfalls

The biggest mistake is calling transform() on a fresh vectorizer before any fit() or fit_transform() call.

Another mistake is fitting one vectorizer instance and later replacing it with a new instance by accident.

People also save only the downstream model and forget the fitted text-preprocessing object. In text ML, the vectorizer is part of the model pipeline, not optional glue.

Finally, do not ignore the training corpus itself. If preprocessing strips everything away, the vectorizer cannot build a meaningful vocabulary.

Summary

  • 'TfidfVectorizer must be fitted before it can transform text.'
  • Use fit_transform() for training data and transform() for new data.
  • Keep the same fitted vectorizer instance for prediction.
  • Save and reload the vectorizer together with the model, or use a pipeline.
  • If fitting still fails, inspect whether preprocessing is leaving you with an empty or invalid corpus.

Course illustration
Course illustration

All Rights Reserved.