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

Scikit-learn是否支持层次分类?多子类分类报错咨询

Scikit-learn层次分类支持及代码问题解决

Scikit-learn没有内置专门的层次分类API,但可以通过自定义编码或多阶段训练实现层次分类逻辑。

你的代码报错原因

你定义的y是3维数组(形状(number, rows, cols)),而Scikit-learn分类器要求目标变量y是1维(单标签分类)或2维(多标签/多任务分类),3维数组不符合输入要求,因此抛出ValueError。

针对你的3主类+6子类场景的解决方案

根据任务需求不同,有三种可行思路:

思路1:扁平标签编码(每个样本属于一个主类的一个子类)

将主类与子类的组合映射为唯一整数标签,把层次结构扁平化,直接用普通分类器训练。

import numpy as np
from sklearn.tree import DecisionTreeClassifier

X = np.random.randn(5, 1)
number, main_class_count, sub_class_count = 5, 3, 6

# 生成扁平标签:主类索引*子类数 + 子类索引
y_flat = []
for _ in range(number):
    main = np.random.randint(main_class_count)
    sub = np.random.randint(sub_class_count)
    y_flat.append(main * sub_class_count + sub)
y_flat = np.array(y_flat)

# 训练与预测
clf = DecisionTreeClassifier()
clf.fit(X, y_flat)

# 预测后解码回层次标签
pred = clf.predict(X[0].reshape(1, -1))[0]
pred_main = pred // sub_class_count
pred_sub = pred % sub_class_count
print(f"预测主类:{pred_main},预测子类:{pred_sub}")

思路2:多阶段分类(先分主类,再分子类)

先训练主类分类器,再针对每个主类单独训练子类分类器,实现分层预测。

import numpy as np
from sklearn.tree import DecisionTreeClassifier

X = np.random.randn(5, 1)
number, main_class_count, sub_class_count = 5, 3, 6

# 生成主类和对应子类标签
y_main = np.random.randint(main_class_count, size=number)
y_sub = np.random.randint(sub_class_count, size=number)

# 第一步:训练主类分类器
main_clf = DecisionTreeClassifier()
main_clf.fit(X, y_main)

# 第二步:为每个主类训练子类分类器
sub_clfs = {}
for main_label in range(main_class_count):
    # 筛选当前主类的样本
    mask = y_main == main_label
    X_sub = X[mask]
    y_sub_filtered = y_sub[mask]
    if len(X_sub) > 0:
        sub_clfs[main_label] = DecisionTreeClassifier()
        sub_clfs[main_label].fit(X_sub, y_sub_filtered)

# 分层预测函数
def predict_hierarchy(x):
    main_pred = main_clf.predict(x.reshape(1, -1))[0]
    sub_pred = sub_clfs[main_label].predict(x.reshape(1, -1))[0] if main_pred in sub_clfs else None
    return (main_pred, sub_pred)

# 测试预测
test_x = np.random.randn(1, 1)
print(predict_hierarchy(test_x))

思路3:多任务分类(每个样本需预测所有主类的子类)

如果你的任务是每个样本要同时预测3个主类各自的子类,可使用MultiOutputClassifier包装基础分类器,将3维目标转换为2维多任务标签。

import numpy as np
from sklearn.tree import DecisionTreeClassifier
from sklearn.multioutput import MultiOutputClassifier

X = np.random.randn(5, 1)
number, main_class_count, sub_class_count = 5, 3, 6

# 生成原3维标签
y_3d = np.zeros((number, main_class_count, sub_class_count), dtype=int)
for n in range(number):
    for main in range(main_class_count):
        sub = np.random.randint(sub_class_count)
        y_3d[n, main, sub] = 1

# 转换为2维多任务标签:每个主类对应一个子类索引
y_multi = np.argmax(y_3d, axis=2)  # 形状(5, 3)

# 训练多任务分类器
clf = MultiOutputClassifier(DecisionTreeClassifier())
clf.fit(X, y_multi)

# 预测结果:每个样本对应3个主类的子类索引
preds = clf.predict(X)
print("各样本的主类子类预测结果:")
print(preds)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 11:30:11