Multi-label Text Classification using the OneVsRest Strategy
Many real-world text classification problems involve assigning multiple labels to each document. For example, a research article about using machine learning to detect cancer might be tagged with labels like "machine learning", "healthcare", "oncology", "biomedical imaging", etc. Building effective multi-label text classifiers can enable improved organization, retrieval, and recommendation of documents.
While some classification algorithms like k-nearest neighbors can be directly applied to multi-label problems, many standard algorithms like logistic regression, decision trees, and support vector machines are inherently binary – they assume each training example has a single class label. One common strategy for adapting binary classifiers to multi-label problems is the One-vs-Rest (OvR) or One-vs-All (OvA) approach.
How the OneVsRest Classifier Works
The idea behind OvR is quite simple – for each possible class label, train a separate binary classifier that predicts whether or not that label applies, ignoring the other labels. When it‘s time to classify a new example, run it through all the binary classifiers and combine their predicted labels.
More formally, given a training set with N examples and L possible labels, OvR trains L independent binary classifiers. The i-th classifier is trained to predict whether label i applies, treating examples with label i as positive and all other examples as negative. Labels are assumed to be coded as binary vectors y of length L where y[i] = 1 if label i applies and 0 otherwise.
At test time, a new example x is fed into each of the L classifiers to generate L binary predictions. These are then combined into a single predicted label vector y_pred where y_pred[i] = 1 if the i-th classifier predicts that label i applies to x.
The key assumption behind OvR is that labels are independent – the prediction for each label is made separately from the others. This is often reasonable for many multi-label problems, but in some cases there may be strong dependencies or correlations between labels that OvR can‘t capture. More sophisticated approaches like classifier chains aim to model label dependencies.
Text Classification Workflow with OneVsRest
Let‘s walk through a typical workflow for multi-label text classification using the OneVsRest strategy, implemented in Python with the scikit-learn library. We‘ll use a dataset of research article abstracts tagged with multiple subject areas as a running example.
1. Text Preprocessing
Raw text data needs to be cleaned and normalized before it can be fed into machine learning models. This involves steps like:
- Tokenization: Splitting text into words, usually by whitespace or punctuation
- Lowercasing: Converting all characters to lowercase to treat different cases like "Learning" and "learning" the same
- Removing stopwords: Filtering out very common words like "the", "and", "of" that appear in most documents and aren‘t informative
- Removing punctuation and digits: Stripping out commas, periods, brackets, numbers, etc. that generally don‘t help with classification
- Stemming/lemmatization: Reducing words to their base or dictionary forms, so that variants like "learns", "learning", "learned" all map to "learn"
Scikit-learn provides utilities for many of these preprocessing steps:
import re
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizer
def preprocess(text):
# Lowercase and remove punctuation/digits
text = re.sub(r‘[^a-zA-Z]‘, ‘ ‘, text.lower())
# Tokenize and remove stopwords
tokens = [w for w in text.split() if w not in stopwords.words(‘english‘)]
# Lemmatize
lemmatizer = WordNetLemmatizer()
tokens = [lemmatizer.lemmatize(w) for w in tokens]
return ‘ ‘.join(tokens)
2. Feature Extraction
Once we have clean, normalized tokens, we need to convert them into numerical feature vectors that machine learning models can work with. The most common approaches are:
- Bag-of-words: Represent each document as a vector of token counts, with one dimension per unique word in the vocabulary
- TF-IDF: Similar to bag-of-words, but weight each token‘s count by its Inverse Document Frequency, which measures how informative that token is based on how frequently it appears across documents
- Word embeddings: Use a pre-trained model like Word2Vec or GloVe to map each token to a dense vector that capture its semantic meaning, then combine into a document vector by averaging or other pooling
Scikit-learn has built-in utilities for bag-of-words and TF-IDF:
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
# Bag-of-words
bow_vectorizer = CountVectorizer()
X_bow = bow_vectorizer.fit_transform(preprocessed_texts)
# TF-IDF
tfidf_vectorizer = TfidfVectorizer()
X_tfidf = tfidf_vectorizer.fit_transform(preprocessed_texts)
3. Training Binary Classifiers with OneVsRest
Now we have our cleaned text data represented as numerical feature vectors X and multi-label targets y. To train a OvR classifier, we just need to pass our desired binary classification algorithm into scikit-learn‘s OneVsRestClassifier meta-estimator:
from sklearn.multiclass import OneVsRestClassifier
from sklearn.linear_model import LogisticRegression
ovr_classifier = OneVsRestClassifier(LogisticRegression())
ovr_classifier.fit(X_tfidf, y_train)
This will automatically train one logistic regression for each possible label found in y_train. We can inspect the individual binary estimators:
print(len(ovr_classifier.estimators_))
print(ovr_classifier.estimators_[0].coef_)
The choice of base estimator is up to you and depends on your particular dataset – popular options include logistic regression, decision trees, support vector machines, and multi-layer perceptrons.
4. Tuning Hyperparameters and Thresholds
Most ML algorithms have hyperparameters that control model complexity, regularization strength, training procedure, etc. Tuning them to your particular dataset is crucial for maximizing performance. With OvR, we can search over combinations of hyperparameters for the base estimator and the OvR meta-estimator itself.
A common approach is grid search – defining a set of possible values for each hyperparameter and training a model for every combination:
from sklearn.model_selection import GridSearchCV
params = {
‘estimator__C‘: [0.1, 1, 10],
‘estimator__penalty‘: [‘l1‘, ‘l2‘]
}
grid = GridSearchCV(ovr_classifier, param_grid=params, cv=5)
grid.fit(X_tfidf, y_train)
print(grid.best_params_)
print(grid.best_score_)
In addition to hyperparameters, another key factor is the decision threshold each binary classifier uses to predict whether its label applies. By default this is 0.5, but adjusting thresholds can dramatically impact precision vs. recall. We can tune thresholds on a held-out validation set by choosing the value that maximizes F1 score:
from sklearn.metrics import f1_score
def tune_thresholds(clf, X_val, y_val):
thresholds = np.arange(0.1, 0.9, 0.05)
f1_scores = []
for th in thresholds:
y_pred = (clf.predict_proba(X_val) >= th).astype(int)
f1 = f1_score(y_val, y_pred, average=‘micro‘)
f1_scores.append(f1)
best_th = thresholds[np.argmax(f1_scores)]
best_f1 = max(f1_scores)
return best_th, best_f1
5. Combining Predictions from Binary Classifiers
Once we‘ve trained and tuned our OvR classifier, we can apply it to new examples to predict what labels should be assigned:
y_pred = ovr_classifier.predict(X_test_tfidf)
print(y_pred[0])
y_pred will be a binary matrix where y_pred[i][j] = 1 if the i-th example is predicted to have label j. We can compare to the true test labels to evaluate performance:
from sklearn.metrics import f1_score, accuracy_score
print(‘Test Accuracy:‘, accuracy_score(y_test, y_pred))
print(‘Test F1 (micro):‘, f1_score(y_test, y_pred, average=‘micro‘))
print(‘Test F1 (macro):‘, f1_score(y_test, y_pred, average=‘macro‘))
Accuracy isn‘t a great metric for multi-label problems, since it harshly penalizes partially incorrect predictions. F1 scores are more commonly used – micro-averaging treats each (example, label) pair as a separate prediction, while macro-averaging computes the F1 for each label and then averages them.
Comparing to Other Approaches
OvR with binary classifiers is a simple but effective approach to multi-label classification. However, some drawbacks are:
- It doesn‘t capture label correlations
- Training and prediction cost scales linearly with the number of possible labels
- It can struggle with label imbalance if some labels are very rare
Some alternative algorithms and strategies:
- Multi-label k-nearest neighbors
- Label powerset: Treat each unique combination of labels as a separate class, then train a multi-class classifier
- Classifier chains: Train a sequence of binary classifiers that use predictions of previous classifiers as features
- Adapted algorithm approach: Extend specific algorithms to directly handle multiple labels (e.g. multi-label decision trees)
- Neural networks with multiple output nodes to predict each label
Scaling to Large Datasets
OvR can struggle with very large datasets with many examples and possible labels, since the cost of training L binary classifiers becomes prohibitive. Some tips for scaling:
- Use a compact feature representation like hashing or embeddings instead of high-dimensional bag-of-words
- Train binary classifiers in parallel across multiple cores or machines
- Use online learning algorithms that can scale to large datasets by training incrementally on small batches
- Compress the label space by combining similar labels or using dimensionality reduction techniques like PCA
Real-world Applications
Multi-label text classification with OvR has many practical applications, including:
- Tagging news articles and blog posts with relevant topics
- Categorizing e-commerce product listings
- Assigning diagnoses to medical records
- Identifying emotions expressed in social media posts
- Classifying protein functions based on biological literature
For example, the Reuters corpus contains over 800,000 manually categorized news articles. Each article can have multiple topic labels like "economic performance", "inflation", "acquisitions", etc. out of 103 total categories. Researchers have used OvR with SVMs to build classifiers that can automatically tag new articles with relevant topics.
As another example, Facebook has used multi-label classification to automatically identify content that violates its community standards. Posts can be flagged with multiple labels like "hate speech", "violence", "nudity", etc. and machine learning models help scale moderation efforts to billions of posts per day.
Conclusion
The OneVsRest strategy is a simple but powerful approach for extending binary classifiers to handle multi-label problems. When combined with effective text preprocessing, feature extraction, and hyperparameter tuning, OvR can build high-quality multi-label classifiers for a wide range of applications. While it has some limitations, it‘s a great starting point for many real-world text classification tasks.
Here we walked through a typical workflow of training an OvR classifier on a multi-label dataset of tagged research article abstracts. The key steps are cleaning and tokenizing text data, transforming into numerical features, fitting binary classifiers for each label, tuning hyperparameters and decision thresholds, and combining individual classifiers‘ predictions.
With the power of meta-estimators like OneVsRestClassifier in scikit-learn, building effective multi-label text classifiers in Python is quite straightforward. You can easily experiment with different combinations of preprocessing techniques, feature representations, and base algorithms to find what works best for your particular dataset and task.
The most important aspects are high-quality labeled training data and careful model evaluation using appropriate metrics like F1 score. Bad data or misaligned objectives can lead you astray even with state-of-the-art modeling techniques. Always start by establishing a strong baseline, then iterate and refine your approach based on empirical results.
While we focused on OvR here, a robust machine learning practitioner should be familiar with a range of strategies for multi-label classification, including adapted algorithms, label powerset, classifier chains, and neural networks. The best approach depends on characteristics of your particular dataset and the relative priorities of prediction speed, label correlation, and computational cost for your application.
Multi-label classification is a rapidly evolving field and an active area of research. Some promising directions include improving OvR with label hierarchy information, extreme multi-label classification with millions of possible labels, and multi-label learning with noisy or missing labels. New techniques are constantly emerging to tackle more complex real-world problems.
In the end, OvR is a valuable tool to have in your NLP toolbox. When combined with other techniques like active learning, transfer learning, and unsupervised feature extraction, it can help build powerful, scalable systems for organizing, searching, and recommending documents. Try it out on your own multi-label text datasets and see what insights you can uncover!