半监督学习在乳腺癌数据集上的应用

机器学习领域,半监督学习是一种介于无监督学习和监督学习之间的方法。它结合了少量标记数据和大量未标记数据,以提高模型的性能。本文以乳腺癌数据集为例,探讨了自训练分类器(SelfTrainingClassifier)在不同阈值下的表现。

乳腺癌数据集是一个经典的数据集,包含了569个样本,每个样本有30个特征。在本实验中,仅保留了50个样本的标签,其余519个样本的标签被删除,以模拟半监督学习的场景。自训练分类器在这种设置下被训练,并且考察了不同阈值对分类器性能的影响。

实验结果显示,当阈值较低(在[0.4, 0.5]范围内)时,分类器会从标记信心度较低的样本中学习。这些样本很可能被错误地标记,导致分类器在这些错误标签上训练时,准确度较低。值得注意的是,分类器几乎标记了所有样本,并且仅在一个迭代中完成。

对于非常高的阈值(在[0.9, 1)范围内),观察到分类器没有增加其数据集(自标记样本的数量为0)。因此,使用0.9999阈值的分类器的准确度与普通监督分类器的准确度相同。

最优的准确度位于这两个极端之间,大约在0.7的阈值处。通过调整阈值,可以在保持数据集大小的同时,提高分类器的准确度。这种自训练的方法为半监督学习提供了一种有效的策略,尤其是在标记数据稀缺的情况下。

代码实现

以下是使用Python和scikit-learn库实现上述实验的代码。代码中使用了StratifiedKFold进行交叉验证,并计算了不同阈值下的分类器准确度和标记样本数量。

import matplotlib.pyplot as plt import numpy as np from sklearn import datasets from sklearn.metrics import accuracy_score from sklearn.model_selection import StratifiedKFold from sklearn.semi_supervised import SelfTrainingClassifier from sklearn.svm import SVC from sklearn.utils import shuffle n_splits = 3 X, y = datasets.load_breast_cancer(return_X_y=True) X, y = shuffle(X, y, random_state=42) y_true = y.copy() y[50:] = -1 total_samples = y.shape[0] base_classifier = SVC(probability=True, gamma=0.001, random_state=42) x_values = np.arange(0.4, 1.05, 0.05) x_values = np.append(x_values, 0.99999) scores = np.empty((x_values.shape[0], n_splits)) amount_labeled = np.empty((x_values.shape[0], n_splits)) amount_iterations = np.empty((x_values.shape[0], n_splits)) for i, threshold in enumerate(x_values): self_training_clf = SelfTrainingClassifier(base_classifier, threshold=threshold) skfolds = StratifiedKFold(n_splits=n_splits) for fold, (train_index, test_index) in enumerate(skfolds.split(X, y)): X_train = X[train_index] y_train = y[train_index] X_test = X[test_index] y_test = y[test_index] y_test_true = y_true[test_index] self_training_clf.fit(X_train, y_train) amount_labeled[i, fold] = (total_samples - np.unique(self_training_clf.labeled_iter_, return_counts=True)[1][0]) amount_iterations[i, fold] = np.max(self_training_clf.labeled_iter_) y_pred = self_training_clf.predict(X_test) scores[i, fold] = accuracy_score(y_test_true, y_pred) ax1 = plt.subplot(211) ax1.errorbar(x_values, scores.mean(axis=1), yerr=scores.std(axis=1), capsize=2, color="b") ax1.set_ylabel("Accuracy", color="b") ax1.tick_params("y", colors="b") ax2 = ax1.twinx() ax2.errorbar(x_values, amount_labeled.mean(axis=1), yerr=amount_labeled.std(axis=1), capsize=2, color="g") ax2.set_ylim(bottom=0) ax2.set_ylabel("Amount of labeled samples", color="g") ax2.tick_params("y", colors="g") ax3 = plt.subplot(212, sharex=ax1) ax3.errorbar(x_values, amount_iterations.mean(axis=1), yerr=amount_iterations.std(axis=1), capsize=2, color="b") ax3.set_ylim(bottom=0) ax3.set_ylabel("Amount of iterations") ax3.set_xlabel("Threshold") plt.show()
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485