You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Label Propagation结合网格搜索与交叉验证的自定义评分问题咨询

解决方案

核心逻辑是拆分和评分全用全量真实标签,仅在模型训练阶段给训练集标签打-1掩码,有两个低成本实现方式:

方案一:自定义估计器包装器(无需改动GridSearchCV逻辑)

将带掩码的标签提前注入自定义的半监督模型包装类,训练时自动替换训练集标签为带-1的版本,全程用真实标签做拆分和评分:

from sklearn.base import BaseEstimator, ClassifierMixin
from sklearn.semi_supervised import LabelPropagation
from sklearn.model_selection import GridSearchCV, StratifiedShuffleSplit
from sklearn.metrics import accuracy_score
import numpy as np

# 1. 提前准备两份标签
y_true_full = np.array([0,0,0,1,1,1]) # 全真实标签,无-1,用于拆分、评分
y_masked = np.array([0,0,-1,1,1,-1]) # 带无标注掩码的标签,仅用于模型训练

# 2. 自定义模型包装器
class MaskedLabelPropagation(BaseEstimator, ClassifierMixin):
    def __init__(self, y_masked, kernel='rbf', gamma=20):
        self.y_masked = y_masked
        self.kernel = kernel
        self.gamma = gamma
        self.model = None
    
    def fit(self, X, y):
        # 取X第一列存储的全局索引,匹配对应掩码标签,训练用X除第一列外的原始特征
        global_idx = X[:,0].astype(int)
        train_X = X[:,1:]
        train_y_masked = self.y_masked[global_idx]
        self.model = LabelPropagation(kernel=self.kernel, gamma=self.gamma)
        self.model.fit(train_X, train_y_masked)
        return self
    
    def predict(self, X):
        test_X = X[:,1:]
        return self.model.predict(test_X)

# 3. 构造带全局索引的输入,保证拆分后索引与样本对应
X_origin = # 填入你的原始特征,shape为(n_samples, n_features)
X_with_idx = np.hstack([np.arange(len(X_origin)).reshape(-1,1), X_origin])

# 4. 正常执行GridSearchCV,全程用y_true_full做拆分和评分
param_grid = {'gamma': [10,20,30]}
cv = StratifiedShuffleSplit(n_splits=5, test_size=0.5, random_state=42)
grid = GridSearchCV(
    estimator=MaskedLabelPropagation(y_masked=y_masked),
    param_grid=param_grid,
    cv=cv,
    scoring='accuracy', # 直接用原生评分函数即可,拿到的y都是真实0/1
    n_jobs=-1
)
grid.fit(X_with_idx, y_true_full)

方案二:手动遍历参数网格(代码量更少,灵活度更高)

如果不想做封装,直接先生成所有折的拆分索引,手动遍历参数网格,训练时加掩码、评分用真实标签即可:

from sklearn.model_selection import ParameterGrid, StratifiedShuffleSplit

param_grid = ParameterGrid({'gamma':[10,20,30], 'kernel':['rbf','knn']})
cv = StratifiedShuffleSplit(n_splits=5, test_size=0.5, random_state=42)

best_score = 0
best_params = None

for params in param_grid:
    fold_scores = []
    for train_idx, test_idx in cv.split(X_origin, y_true_full):
        # 训练阶段用带-1的掩码标签
        train_y = y_masked[train_idx]
        model = LabelPropagation(**params)
        model.fit(X_origin[train_idx], train_y)
        # 评分阶段用全真实标签
        pred = model.predict(X_origin[test_idx])
        fold_scores.append(accuracy_score(y_true_full[test_idx], pred))
    mean_score = np.mean(fold_scores)
    if mean_score > best_score:
        best_score = mean_score
        best_params = params

print(f"最优参数{best_params}, 平均得分{best_score}")

两种方案都不需要重写复杂的网格搜索逻辑,方案二更适合半监督这类需要自定义训练/评分逻辑的场景,维护成本更低。

内容的提问来源于stack exchange,提问作者James

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 02:24:02