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

scikit-learn kNN回归含列表型特征报错ValueError的解决问询

解决scikit-learn kNN回归中嵌套列表特征的ValueError问题

你遇到的ValueError: setting an array element with a sequence完全是因为scikit-learn的模型(包括KNeighborsRegressor)不支持将嵌套列表作为单个特征值——它要求输入的特征矩阵必须是二维数值数组(或稀疏矩阵),所有元素都是标量类型。你的'list'列每个元素都是一个列表,直接违反了这个输入要求。

下面是分步解决的方案:

1. 将嵌套列表特征展开为多个标量特征

首先需要把每个列表型特征拆分成多个独立的数值列,比如把[1,0,3,5,0,9]拆成list_0到list_5共6个列。用pandas可以轻松实现:

# 展开list列成多个独立特征
expanded_list = paul['list'].apply(pd.Series)
expanded_list.columns = [f'list_{i}' for i in expanded_list.columns]

# 合并到原数据集,删除原始的list列
paul_processed = pd.concat([paul.drop('list', axis=1), expanded_list], axis=1)

处理后的数据集所有特征都是标量,符合scikit-learn的输入要求。

2. 调整自定义距离函数

原来的距离函数是针对单个特征可能为列表的情况设计的,现在所有特征都是标量,我们需要修改函数,让它能接收整个样本的特征向量,分别计算不同类型特征的距离后求和:

import pandas as pd

def my_distance(X, Y, **kwargs):
    # X和Y是单个样本的一维特征向量
    # 提取不同类型的特征(对应处理后的数据集列顺序:cat, metr, list_0~list_5)
    cat_x, cat_y = X[0], Y[0]
    metr_x, metr_y = X[1], Y[1]
    list_x = X[2:]
    list_y = Y[2:]
    
    # 计算原list特征部分的距离:sum(max(xk,yk)) * Para_list
    sum_max_list = sum(max(xk, yk) for xk, yk in zip(list_x, list_y))
    dist_list = sum_max_list * kwargs["Para_list"]
    
    # 计算分类特征cat的距离
    if cat_x == cat_y and cat_x != -1:
        dist_cat = 0
    elif cat_x == -1 or cat_y == -1 or pd.isna(cat_x) or pd.isna(cat_y):
        dist_cat = kwargs["Para_minus1"]
    else:
        dist_cat = kwargs["Para_nominal"]
    
    # 计算数值特征metr的距离
    if metr_x == metr_y:
        dist_metr = 0
    elif metr_x == -1 or metr_y == -1 or pd.isna(metr_x) or pd.isna(metr_y):
        dist_metr = kwargs["Para_minus1"]
    else:
        dist_metr = abs(metr_x - metr_y) * kwargs["Para_metrisch"]
    
    # 总距离为各部分距离之和
    return dist_list + dist_cat + dist_metr

3. 重新训练kNN模型

注意需要用DistanceMetric.get_metric包装自定义函数,并且将数据集转换为numpy数组(避免pandas DataFrame的类型兼容问题):

from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsRegressor
from sklearn.metrics import DistanceMetric

# 拆分训练测试集
train, test = train_test_split(paul_processed, test_size=0.3)
x_train = train.drop('target', axis=1).values
y_train = train['target'].values
x_test = test.drop('target', axis=1).values
y_test = test['target'].values

# 包装自定义距离函数
custom_metric = DistanceMetric.get_metric('pyfunc', func=my_distance)

# 初始化并训练模型
knn = KNeighborsRegressor(
    n_neighbors=2,
    algorithm='ball_tree',
    metric=custom_metric,
    metric_params={"Para_list": 2, "Para_minus1": 3, "Para_metrisch": 2, "Para_nominal": 4}
)
knn.fit(x_train, y_train)

# 预测
y_pred = knn.predict(x_test)

额外注意事项

  • 使用ball_tree算法时,自定义距离函数必须满足对称性(my_distance(X,Y) == my_distance(Y,X))和非负性(距离值≥0),否则算法可能出现异常或结果错误,你的函数目前是符合这些要求的。
  • 如果你的列表长度不固定,需要先统一长度(比如补0或NaN)再展开,否则无法转换成规整的特征矩阵。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 07:48:14