Semi-Supervised Learning with Scikit-learn’s SelfTrainingClassifier: A Visual Guide
In many real-world scenarios, we often find ourselves with a lot of unlabeled data and a small portion of labeled data.
In many real-world scenarios, we often find ourselves with a lot of unlabeled data and a small portion of labeled data. Manually labeling this data can be expensive and time-consuming. This is where semi-supervised learning shines. It leverages both labeled and unlabeled data to improve the model’s performance.
Scikit-learn offers the SelfTrainingClassifier, a semi-supervised learning method that iteratively pseudo-labels the unlabeled data and refines the model. In this tutorial, we’ll understand how the SelfTrainingClassifier works and visualize its pseudo-labeling process using an animation.
Setting up the Environment
Before we dive in, ensure you have the necessary packages installed:
pip install numpy matplotlib scikit-learnGenerating Synthetic Data
Let’s start by creating a synthetic dataset with two clusters:
from sklearn.datasets import make_blobs
X, y = make_blobs(n_samples=400, centers=2, cluster_std=5, random_state=42)y[123:] = -1 # Unlabeled samplesWe’ve deliberately left a large portion of the samples as unlabeled (denoted by -1).
Initializing the Base Classifier
For this tutorial, we’ll use a logistic regression model with an elastic net penalty:
from sklearn.linear_model import LogisticRegression
base_classifier = LogisticRegression(penalty='elasticnet', solver='saga', max_iter=10000, class_weight='balanced', l1_ratio=0.1, C=0.001)The SelfTrainingClassifier
The SelfTrainingClassifier in Scikit-learn takes in the base classifier and iteratively pseudo-labels the unlabeled data:
from sklearn.semi_supervised import SelfTrainingClassifier
self_training_clf = SelfTrainingClassifier(base_classifier, criterion="k_best", k_best=2, max_iter=10)Here, the k_best criterion means that in each iteration, the two most confidently predicted samples will be pseudo-labeled.
Training and Collecting Iteration Data
We’ll manually run the classifier for 10 iterations, capturing the state of the labels at each step:
iterations_data = []
def train_one_iteration(): prev_labels = y.copy() self_training_clf.fit(X, y) new_labels = self_training_clf.transduction_ y[:] = new_labels pseudo_labeled_indices = np.where((prev_labels == -1) & (new_labels != -1)) return pseudo_labeled_indices
for i in range(10): indices = train_one_iteration() iterations_data.append((y.copy(), indices))Visualizing the Process
Using Matplotlib, we can animate the pseudo-labeling process:
import matplotlib.pyplot as pltfrom matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()scatter = ax.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Paired, edgecolors='k')highlighted, = ax.plot([], [], 'ro', markersize=5)
def init(): return scatter, highlighted
def update(frame): scatter.set_array(iterations_data[frame][0]) highlighted.set_data(X[iterations_data[frame][1], 0], X[iterations_data[frame][1], 1]) ax.set_title(f"SelfTrainingClassifier Iteration: {frame+1}") return scatter, highlighted
ani = FuncAnimation(fig, update, frames=len(iterations_data), init_func=init, blit=False)ani.save('self_training_animation.gif', writer='imagemagick', fps=1)This will save the animation as a GIF. The red dots in the animation represent the samples that have been pseudo-labeled in each iteration.
Conclusion
The SelfTrainingClassifier is a powerful tool for semi-supervised learning, especially when you have a large amount of unlabeled data. By visualizing its pseudo-labeling process, we gain insights into how the classifier is gradually confident about labeling the unlabeled samples. This can be especially useful for understanding and debugging your semi-supervised learning models.
Comments