Python案例如何用Scikit-learn做半监督学习

wen python案例 1

本文目录导读:

Python案例如何用Scikit-learn做半监督学习

  1. 基础示例:LabelPropagation
  2. LabelSpreading算法
  3. 完整的示例:对比不同方法
  4. 可视化传播过程
  5. 超参数调优示例
  6. 实战:图像分类示例
  7. 关键要点

我来介绍用Scikit-learn做半监督学习的几种方法,主要使用LabelPropagationLabelSpreading两种算法。

基础示例:LabelPropagation

import numpy as np
import matplotlib.pyplot as plt
from sklearn.semi_supervised import LabelPropagation, LabelSpreading
from sklearn.datasets import make_moons
from sklearn.metrics import accuracy_score
# 生成数据
X, y = make_moons(n_samples=200, noise=0.15, random_state=42)
# 创建半监督学习场景:只标记部分数据
rng = np.random.RandomState(42)
random_unlabeled_points = rng.rand(len(y)) < 0.7  # 70%的数据无标签
y_mixed = y.copy()
y_mixed[random_unlabeled_points] = -1  # -1表示无标签
# 训练LabelPropagation模型
lp_model = LabelPropagation(kernel='knn', n_neighbors=7, max_iter=100)
lp_model.fit(X, y_mixed)
# 预测
y_pred = lp_model.predict(X)
# 评估(只对原始有标签的数据)
labeled_indices = ~random_unlabeled_points
accuracy = accuracy_score(y[labeled_indices], y_pred[labeled_indices])
print(f"LabelPropagation准确率: {accuracy:.3f}")

LabelSpreading算法

# 使用LabelSpreading算法
ls_model = LabelSpreading(kernel='rbf', gamma=20, alpha=0.8)
ls_model.fit(X, y_mixed)
y_pred_ls = ls_model.predict(X)
accuracy_ls = accuracy_score(y[labeled_indices], y_pred_ls[labeled_indices])
print(f"LabelSpreading准确率: {accuracy_ls:.3f}")
# 查看传播后的标签概率
probabilities = ls_model.predict_proba(X)
print(f"传播概率维度: {probabilities.shape}")

完整的示例:对比不同方法

import numpy as np
from sklearn.semi_supervised import LabelPropagation, LabelSpreading
from sklearn.semi_supervised import SelfTrainingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
# 1. 加载数据集
digits = load_digits()
X, y = digits.data, digits.target
# 2. 分割数据集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42
)
# 3. 创建半监督场景:只保留少量标签
n_labeled = 50  # 只有50个有标签的样本
rng = np.random.RandomState(42)
indices = rng.permutation(len(X_train))
# 创建混合标签:大多数设为-1(无标签)
y_train_mixed = y_train.copy()
y_train_mixed[indices[n_labeled:]] = -1
print(f"训练集大小: {len(X_train)}")
print(f"有标签样本数: {n_labeled}")
print(f"无标签样本数: {len(X_train) - n_labeled}")
# 4. 训练各个模型
models = {
    'LabelPropagation': LabelPropagation(kernel='rbf', gamma=20),
    'LabelSpreading': LabelSpreading(kernel='rbf', gamma=20),
    'SelfTraining': SelfTrainingClassifier(
        LogisticRegression(max_iter=1000, random_state=42)
    )
}
# 5. 训练和评估
for name, model in models.items():
    model.fit(X_train, y_train_mixed)
    y_pred = model.predict(X_test)
    accuracy = np.mean(y_pred == y_test)
    print(f"\n{name} 准确率: {accuracy:.3f}")

可视化传播过程

import numpy as np
import matplotlib.pyplot as plt
from sklearn.semi_supervised import LabelSpreading
from sklearn.datasets import make_swiss_roll
from mpl_toolkits.mplot3d import Axes3D
# 生成Swiss Roll数据集
n_samples = 500
X, color = make_swiss_roll(n_samples=n_samples, noise=0.1, random_state=42)
# 随机选择标签点
np.random.seed(42)
n_labeled = 20
random_states = np.random.randint(0, n_samples, n_labeled)
y_labels = np.full(n_samples, -1)
y_labels[random_states] = color[random_states].astype(int) % 3  # 3个类别
# 训练LabelSpreading
model = LabelSpreading(kernel='rbf', gamma=20, alpha=0.8)
model.fit(X, y_labels)
# 获取传播后的标签
y_propagated = model.predict(X)
# 可视化
fig = plt.figure(figsize=(12, 5))
# 原始标签
ax1 = fig.add_subplot(121, projection='3d')
scatter = ax1.scatter(X[:, 0], X[:, 1], X[:, 2], 
                     c=y_labels, cmap='viridis', s=50)
ax1.set_title('原始标签(蓝色=无标签)')
ax1.set_xlabel('X')
ax1.set_ylabel('Y')
ax1.set_zlabel('Z')
# 传播后的标签
ax2 = fig.add_subplot(122, projection='3d')
scatter = ax2.scatter(X[:, 0], X[:, 1], X[:, 2], 
                     c=y_propagated, cmap='viridis', s=50)
ax2.set_title('传播后的标签')
ax2.set_xlabel('X')
ax2.set_ylabel('Y')
ax2.set_zlabel('Z')
plt.tight_layout()
plt.show()

超参数调优示例

from sklearn.model_selection import GridSearchCV
from sklearn.semi_supervised import LabelSpreading
from sklearn.metrics import make_scorer, f1_score
import numpy as np
# 创建数据集
np.random.seed(42)
X = np.random.randn(200, 10)
y = (X[:, 0] + X[:, 1] > 0).astype(int)
# 创建半监督场景
y_mixed = y.copy()
mask = np.random.random(len(y)) > 0.1  # 90%无标签
y_mixed[mask] = -1
# 定义参数网格
param_grid = {
    'kernel': ['knn', 'rbf'],
    'gamma': [10, 20, 30, 40],
    'n_neighbors': [3, 5, 7, 9],
    'alpha': [0.5, 0.7, 0.9]
}
# 创建模型
ls = LabelSpreading(max_iter=100)
# 网格搜索
grid_search = GridSearchCV(
    ls, param_grid, cv=3,
    scoring=make_scorer(f1_score, average='weighted'),
    n_jobs=-1
)
# 使用有标签的数据进行验证
labeled_mask = y_mixed != -1
grid_search.fit(X[labeled_mask], y[labeled_mask])
print(f"最佳参数: {grid_search.best_params_}")
print(f"最佳分数: {grid_search.best_score_:.3f}")

实战:图像分类示例

from sklearn.semi_supervised import LabelPropagation
from sklearn.datasets import load_digits
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
# 加载手写数字数据集
digits = load_digits()
X, y = digits.data, digits.target
# 降维可视化
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)
# 创建半监督场景
n_labeled = 30
rng = np.random.RandomState(42)
labeled_idx = rng.choice(len(y), n_labeled, replace=False)
y_mixed = -np.ones_like(y)
y_mixed[labeled_idx] = y[labeled_idx]
# 训练
model = LabelPropagation(kernel='rbf', gamma=10)
model.fit(X, y_mixed)
# 可视化结果
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
# 真实标签
scatter1 = ax1.scatter(X_pca[:, 0], X_pca[:, 1], c=y, cmap='tab10', alpha=0.6)
ax1.set_title('真实标签')
plt.colorbar(scatter1, ax=ax1)
# 预测标签
y_pred = model.transduction_
scatter2 = ax2.scatter(X_pca[:, 0], X_pca[:, 1], c=y_pred, cmap='tab10', alpha=0.6)
ax2.set_title('传播后标签')
plt.colorbar(scatter2, ax=ax2)
plt.tight_layout()
plt.show()
# 评估
accuracy = np.mean(y_pred == y)
print(f"整体准确率: {accuracy:.3f}")

关键要点

  1. 数据准备:无标签样本用 -1 标记

  2. 算法选择

    • LabelPropagation:基于图传播
    • LabelSpreading:改进版,更稳定
    • SelfTrainingClassifier:可以结合任何分类器
  3. 适用场景

    • 标注数据稀缺
    • 数据量大但标注成本高
    • 需要利用无标签数据提升性能
  4. 注意事项

    • 选择合适的核函数(knn 或 rbf)
    • 调整传播参数(gamma, alpha 等)
    • 监控传播效果的稳定性

这些示例展示了 Scikit-learn 中半监督学习的基本用法,适合处理标签数据稀缺的实际问题。

抱歉,评论功能暂时关闭!