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

半监督SVM模型运行超时,求实现问题排查与代码修正

关于Elliptic比特币数据集半监督SVM实现的问题与修复

我正在使用Elliptic比特币数据集,测试其在监督式与半监督式模型上的性能。以下是我的监督式SVM模型代码:

classified = class_features_df[class_features_df['class'].isin(['1','2'])]

X = classified.drop(columns=['txId', 'class', 'time step']) 
y = classified[['class']]

# 将合法交易(class 2)标记为0,非法交易(class 1)标记为1
y = y['class'].apply(lambda x: 0 if x == '2' else 1 )

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=15, shuffle=False)

model_svm = svm.SVC(kernel='linear') # Linear Kernel

# 修正:变量名统一,用model_svm而非model,y_train而非Y_train
model_svm.fit(X_train, y_train)

# 计算准确率
y_pred = model_svm.predict(X_test)
acc = accuracy_score(y_test, y_pred)

上述代码运行正常且结果良好,但尝试使用相同逻辑实现半监督式学习时,模型出现警告且已运行超过1小时(而监督式模型运行耗时不到1分钟),半监督代码如下:

unclassified = class_features_df[class_features_df['class'] == 3]

X_unclassified = unclassified[local_features_col + agg_features_col]

predictions = model_svm.predict(X_unclassified.values)

# 这里会触发SettingWithCopyWarning,因为unclassified是原数据集的切片
unclassified['class'] = predictions

# 合并标记数据和预测后的未标记数据
classified = classified.append(unclassified)

Xtrain = classified.drop(columns=['txId', 'class', 'time step'])
ytrain = classified['class'].astype('int') # 转换类型避免错误

X_train_lab, X_test_unlab, y_train_lab, y_test_unlab = train_test_split(Xtrain, ytrain, test_size=0.3, random_state=15, shuffle=False)

model_svm.fit(X_train_lab, y_train_lab)

# 评估模型
y_pred = model_svm.predict(X_test_unlab)
acc = accuracy_score(y_test_unlab, y_pred)
print("Accuracy ", acc)

补充信息:类别1和2为已标记交易,类别3为未标记交易。


问题分析与代码修复

1. 核心逻辑问题:SVM不适合大规模自训练场景

你当前的实现属于自训练(Self-Training),但存在两个关键问题:

  • Elliptic数据集中未标记数据(class 3)占比约90%,合并后数据集规模是原标记数据的10倍以上。SVM的训练时间复杂度为O(n²),数据量暴增会直接导致训练时间陡增。
  • 直接将所有未标记数据的预测结果作为硬标签加入训练,会引入大量噪声,既降低模型精度,又进一步加重训练负担。

2. 代码中的具体错误

  • 变量名不一致:监督式代码中定义了model_svm,但调用model.fit,且Y_train/y_train大小写混乱,会直接触发报错。
  • SettingWithCopyWarning:unclassified是class_features_df的切片,直接修改unclassified['class']会触发警告,甚至导致数据未被正确修改。
  • 特征不一致:监督式代码中X是删除txId/class/time step后的列,而半监督中X_unclassified用local_features_col + agg_features_col,需确保两者特征完全一致,否则预测和训练会出错。
  • 过时方法:DataFrame.append已被弃用,应使用pd.concat。

3. 修复后的代码方案

方案一:优化自训练SVM(仅选取高置信度样本)
import pandas as pd
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# 1. 预处理标记数据
classified = class_features_df[class_features_df['class'].isin(['1','2'])].copy()
X_labeled = classified.drop(columns=['txId', 'class', 'time step'])
y_labeled = classified['class'].apply(lambda x: 0 if x == '2' else 1).astype(int)

# 2. 预处理未标记数据
unclassified = class_features_df[class_features_df['class'] == 3].copy()
X_unlabeled = unclassified.drop(columns=['txId', 'class', 'time step'])

# 3. 初始训练SVM(开启概率计算,用于筛选高置信度样本)
model_svm = SVC(kernel='linear', probability=True)
model_svm.fit(X_labeled, y_labeled)

# 4. 自训练:仅选取置信度>0.9的未标记样本加入训练
probs = model_svm.predict_proba(X_unlabeled)
confidence = probs.max(axis=1)
high_conf_idx = confidence > 0.9

# 合并高置信度样本到标记数据集
X_combined = pd.concat([X_labeled, X_unlabeled[high_conf_idx]])
y_combined = pd.concat([y_labeled, pd.Series(model_svm.predict(X_unlabeled[high_conf_idx]), index=X_unlabeled[high_conf_idx].index)])

# 5. 划分训练测试集并训练
X_train, X_test, y_train, y_test = train_test_split(X_combined, y_combined, test_size=0.3, random_state=15, shuffle=False)
model_svm.fit(X_train, y_train)

# 6. 评估
y_pred = model_svm.predict(X_test)
acc = accuracy_score(y_test, y_pred)
print("Accuracy: ", acc)
方案二:使用sklearn专门的半监督模型(推荐)

SVM并非原生半监督模型,sklearn提供的LabelPropagation/LabelSpreading更适合这类场景:

from sklearn.semi_supervised import LabelPropagation
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# 1. 准备全量数据:将未标记样本的y设为-1(半监督模型要求)
full_df = class_features_df.copy()
full_df['label'] = full_df['class'].apply(lambda x: 1 if x == '1' else (0 if x == '2' else -1)).astype(int)

X = full_df.drop(columns=['txId', 'class', 'time step', 'label'])
y = full_df['label']

# 2. 划分训练测试集,过滤测试集中的未标记样本用于评估
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=15, shuffle=True)
test_mask = y_test != -1
X_test_labeled = X_test[test_mask]
y_test_labeled = y_test[test_mask]

# 3. 训练半监督模型
model = LabelPropagation(kernel='rbf', gamma=20)
model.fit(X_train, y_train)

# 4. 评估
y_pred = model.predict(X_test_labeled)
acc = accuracy_score(y_test_labeled, y_pred)
print("Accuracy: ", acc)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 19:40:28