Monday, August 24, 2026
HomeData ScienceText Classification with NLP – Python Guide 2026

Text Classification with NLP – Python Guide 2026

Table of Content

Text classification — assigning categories to text — is one of the most common NLP tasks in industry. Spam detection, sentiment analysis, support ticket routing, content moderation — all of these are text classification problems. This guide walks through the full pipeline from raw text to a deployed classifier in Python.

The Text Classification Pipeline

Every text classification project follows the same pipeline: text cleaning → feature extraction → model training → evaluation → deployment. The key choices are (1) what to use as features (TF-IDF, word embeddings, or transformer encodings) and (2) what classifier to use (logistic regression, gradient boosting, or fine-tuned BERT). We’ll cover all of these.

Text Preprocessing

import re
import nltk
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizer

nltk.download(['stopwords', 'wordnet', 'punkt'])

stop_words  = set(stopwords.words('english'))
lemmatizer  = WordNetLemmatizer()

def preprocess(text: str) -> str:
    text = text.lower()
    text = re.sub(r'http\S+|www\S+', '', text)       # remove URLs
    text = re.sub(r'[^a-z\s]', '', text)             # keep only letters
    text = re.sub(r'\s+', ' ', text).strip()
    tokens = text.split()
    tokens = [lemmatizer.lemmatize(t) for t in tokens if t not in stop_words]
    return ' '.join(tokens)

df['clean_text'] = df['text'].apply(preprocess)

Approach 1 – TF-IDF + Logistic Regression

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report

X_train, X_test, y_train, y_test = train_test_split(
    df['clean_text'], df['label'], test_size=0.2, random_state=42, stratify=df['label'])

pipeline = Pipeline([
    ('tfidf', TfidfVectorizer(max_features=50000, ngram_range=(1, 2),
                               min_df=2, sublinear_tf=True)),
    ('clf',   LogisticRegression(max_iter=1000, C=1.0, class_weight='balanced')),
])

pipeline.fit(X_train, y_train)
y_pred = pipeline.predict(X_test)
print(classification_report(y_test, y_pred))

This simple pipeline achieves surprisingly strong results — often 85-92% accuracy on well-defined tasks. It’s fast, interpretable, and doesn’t need a GPU.

Understanding TF-IDF

TF-IDF (Term Frequency-Inverse Document Frequency) scores words by how often they appear in a document (TF) relative to how often they appear across all documents (IDF). Words that appear frequently in one document but rarely overall (like “arbitrage” in a finance article) get high TF-IDF scores. Common words like “the” get low scores. ngram_range=(1,2) includes both single words and two-word phrases, capturing context like “not good” instead of treating “not” and “good” separately.

Approach 2 – Word Embeddings + Gradient Boosting

import numpy as np
from sentence_transformers import SentenceTransformer
from sklearn.ensemble import GradientBoostingClassifier

# Encode texts as dense vectors (384 dimensions)
model = SentenceTransformer('all-MiniLM-L6-v2')
X_train_emb = model.encode(X_train.tolist(), show_progress_bar=True)
X_test_emb  = model.encode(X_test.tolist(),  show_progress_bar=True)

# Train classifier on embeddings
clf = GradientBoostingClassifier(n_estimators=200, learning_rate=0.1)
clf.fit(X_train_emb, y_train)
print(classification_report(y_test, clf.predict(X_test_emb)))

Approach 3 – Fine-Tuned BERT (Best Accuracy)

from transformers import pipeline as hf_pipeline

# Zero-shot (no training needed)
classifier = hf_pipeline("zero-shot-classification", model="facebook/bart-large-mnli")
result = classifier(
    "This product broke after one week. Terrible quality.",
    candidate_labels=["positive review", "negative review", "neutral review"])
print(result['labels'][0])  # negative review

# Fine-tuned (highest accuracy, needs labelled data)
from transformers import AutoTokenizer, AutoModelForSequenceClassification, Trainer, TrainingArguments

tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased")
model     = AutoModelForSequenceClassification.from_pretrained(
                "distilbert-base-uncased", num_labels=len(df['label'].unique()))

Multi-Label Classification

from sklearn.preprocessing import MultiLabelBinarizer
from sklearn.multiclass import OneVsRestClassifier

# Each text can belong to multiple categories
mlb = MultiLabelBinarizer()
y_multi = mlb.fit_transform(df['labels'])  # labels is a list of lists

pipeline_multi = Pipeline([
    ('tfidf', TfidfVectorizer(max_features=30000)),
    ('clf',   OneVsRestClassifier(LogisticRegression(max_iter=500)))
])
pipeline_multi.fit(X_train, y_multi[train_idx])

Deployment as a REST API

import pickle
from fastapi import FastAPI
from pydantic import BaseModel

with open("text_classifier.pkl", "wb") as f:
    pickle.dump(pipeline, f)

app = FastAPI()

class TextInput(BaseModel):
    text: str

@app.post("/classify")
def classify(input: TextInput):
    clean = preprocess(input.text)
    label = pipeline.predict([clean])[0]
    prob  = pipeline.predict_proba([clean]).max()
    return {"label": label, "confidence": round(float(prob), 4)}

Conclusion

For most text classification tasks, start with TF-IDF + logistic regression — it’s fast to train, easy to interpret, and achieves 85%+ accuracy on clean datasets. Move to sentence embeddings + gradient boosting when you need more accuracy without a GPU. Fine-tune BERT or DistilBERT when you need maximum accuracy and have enough labelled data (>1000 examples per class). The right choice depends on your data size, latency constraints, and infrastructure.

Leave feedback about this

  • Rating

Durgesh Kekare
Durgesh Kekarehttps://www.dataexpertise.in
Durgesh Kekare is a data science educator and founder of DataExpertise.in. With expertise in Python, machine learning, and analytics, he helps 10,000+ learners break into data careers.

Latest Posts

List of Categories