半监督学习是一种机器学习方法,它利用少量的标记数据和大量的未标记数据来训练模型。这种方法特别适用于那些获取标签成本高昂或难以实现的场景。常见的半监督学习技术包括自训练(self-training)、多视角学习(multi-view learning)等。
自训练 (Self-Training)
自训练是一种简单但有效的半监督学习方法。其基本思想是使用初始的小量标记数据训练一个基础分类器,然后用这个分类器对未标记数据进行预测,并将置信度高的预测结果加入到训练集中,从而迭代地改进模型。
示例:使用自训练方法进行文本分类
假设有一个部分标记的电子邮件数据集目标是识别垃圾邮件。
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import accuracy_score, classification_report
# 假设数据已经加载到变量emails中,其中每个条目都是一个字典,含有"text"和"label"两个键
# 标记数据
labeled_emails = [
{"text": "Free Viagra now!!!", "label": "spam"},
{"text": "Hello, how are you?", "label": "ham"},
# 更多数据...
]
# 未标记数据
unlabeled_emails = [
{"text": "Win a million dollars now!"},
{"text": "Dinner at 7?"},
# 更多数据...
]
# 准备标记数据
labeled_texts = [email["text"] for email in labeled_emails]
labeled_labels = [email["label"] for email in labeled_emails]
# 特征提取
vectorizer = TfidfVectorizer()
X_labeled = vectorizer.fit_transform(labeled_texts)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_labeled, labeled_labels, test_size=0.2, random_state=42)
# 创建并训练初始分类器
classifier = MultinomialNB()
classifier.fit(X_train, y_train)
# 迭代次数
num_iterations = 10
threshold = 0.9 # 置信度阈值
for _ in range(num_iterations):
# 对未标记数据进行预测
unlabeled_texts = [email["text"] for email in unlabeled_emails]
X_unlabeled = vectorizer.transform(unlabeled_texts)
predicted_probs = classifier.predict_proba(X_unlabeled)
# 找出高置信度的预测
high_confidence_indices = np.where(np.max(predicted_probs, axis=1) > threshold)[0]
if len(high_confidence_indices) == 0:
break # 没有新的高置信度样本
# 将这些高置信度样本加入到训练集中
new_X = X_unlabeled[high_confidence_indices]
new_y = classifier.classes_[np.argmax(predicted_probs[high_confidence_indices], axis=1)]
X_train = np.vstack((X_train, new_X))
y_train = np.concatenate((y_train, new_y))
# 重新训练分类器
classifier.fit(X_train, y_train)
# 最终评估
predictions = classifier.predict(X_test)
print("Final Accuracy:", accuracy_score(y_test, predictions))
print(classification_report(y_test, predictions))
#
-
数据准备:
labeled_emails
包含了部分带有标签的电子邮件。unlabeled_emails
包含了大量的未标记电子邮件。- 使用TF-IDF向量化文本数据。
-
初始训练:
- 使用标记数据训练一个朴素贝叶斯分类器。
-
自训练循环:
- 在每次迭代中,使用当前分类器对未标记数据进行预测。
- 选择预测概率超过一定阈值(如0.9)的数据点,认为这些预测是可靠的。
- 将这些高置信度的预测结果及其特征加入到训练集中。
- 重新训练分类器,以利用新增加的标记数据。
-
最终评估:
- 在测试集上评估最终模型的性能。
- 输出准确率和分类报告。
-
新数据预测:
- 使用最终训练好的模型对新的未标记数据进行分类。
多视角学习 (Multi-View Learning)
多视角学习是指从多个不同的视角或特征空间来看待同一个问题,通过整合不同视角的信息来提高学习效果。例如,在图像分类任务中,可以从颜色、纹理等多个角度来描述图像。
示例:使用多视角学习进行手写数字识别
假设有两个不同的特征提取方法来处理MNIST手写数字数据集,将展示如何使用这两个视角来训练模型。
import numpy as np
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
# 加载MNIST数据集
digits = load_digits()
X, y = digits.data, digits.target
# 分割训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 定义两种不同的特征提取方法
def extract_feature_1(X):
return X # 直接使用原始像素作为特征
def extract_feature_2(X):
return X[:, ::2] # 只使用奇数列的像素作为特征
# 提取特征
X_train_view1 = extract_feature_1(X_train)
X_train_view2 = extract_feature_2(X_train)
X_test_view1 = extract_feature_1(X_test)
X_test_view2 = extract_feature_2(X_test)
# 训练两个独立的分类器
classifier1 = LogisticRegression(max_iter=1000)
classifier1.fit(X_train_view1, y_train)
classifier2 = LogisticRegression(max_iter=1000)
classifier2.fit(X_train_view2, y_train)
# 预测
preds1 = classifier1.predict(X_test_view1)
preds2 = classifier2.predict(X_test_view2)
# 结合两个视角的预测
final_preds = np.array([preds1, preds2]).mode(axis=0)[0]
# 评估
print("Accuracy using View 1:", accuracy_score(y_test, preds1))
print("Accuracy using View 2:", accuracy_score(y_test, preds2))
print("Combined Accuracy:", accuracy_score(y_test, final_preds))
-
数据准备:
- 加载MNIST手写数字数据集。
- 分割训练集和测试集。
-
特征提取:
- 定义两个不同的特征提取方法:
extract_feature_1
直接使用原始像素,extract_feature_2
只使用奇数列的像素。
- 定义两个不同的特征提取方法:
-
训练分类器:
- 使用逻辑回归分别在两个视角上训练分类器。
-
预测与结合:
- 在测试集上分别使用两个分类器进行预测。
- 通过投票机制(取众数)来结合两个视角的预测结果。
-
评估:
- 分别计算单个视角的准确率以及结合后的准确率。