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

拟合NearestNeighbors时出现数组元素赋值序列ValueError

问题描述

现有结构如下的PySpark DataFrame,包含id与features两个字段,features字段为等长浮点数值组成的特征向量列表:

+------+---------------------------------------------------------------------+
|id    |features                                                             |
+------+---------------------------------------------------------------------+
|2484  |[0.016910851, 0.025989642, 0.0025321299, -0.022232508, -0.00701562]  |
|2504  |[0.015019539, 0.024844216, 0.0029279909, -0.020771071, -0.0061111804]|
|2904  |[0.014104126, 0.02474243, 0.0011707658, -0.021675153, -0.0050868453] |
|3084  |[0.110674664, 0.17139696, 0.059836507, -0.1926481, -0.060425207]     |
|3164  |[0.17688861, 0.2159168, 0.10567094, -0.17365277, -0.016458606]       |
|377784|[0.18425785, 0.34397766, 0.022859085, -0.35151178, -0.07897296]      |
|425114|[0.14556459, 0.25762737, 0.09011796, -0.27128243, 0.011280057]       |
|455074|[0.13579306, 0.3266111, 0.016416805, -0.31139722, -0.054227617]      |
|532624|[0.22281846, 0.1575731, 0.14126688, -0.29887098, -0.09433056]        |
|781654|[0.1381407, 0.14674455, 0.06877328, -0.13415968, -0.06589967]        |
+------+---------------------------------------------------------------------+

基于上述特征执行最近邻检索的初始代码如下:

df_collect = df.toPandas()
#converting list column to array
df_collect['features'] = df_collect['features'].apply(lambda x: np.array(x))
features = df_collect['features'].to_numpy()

knnobj = NearestNeighbors(n_neighbors=5, algorithm='auto').fit(features)

执行fit拟合操作时触发如下报错:

TypeError                                 Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars

The above exception was the direct cause of the following exception:

ValueError                                Traceback (most recent call last)
/tmp/ipykernel_6511/1498389666.py in <module>
----> 1 knnobj = NearestNeighbors(n_neighbors=5, algorithm='auto').fit(features)

~/miniconda3/envs/dev_env_37/lib/python3.7/site-packages/sklearn/neighbors/_unsupervised.py in fit(self, X, y)
    164             The fitted nearest neighbors estimator.
    165         """
--> 166         return self._fit(X)

~/miniconda3/envs/dev_env_37/lib/python3.7/site-packages/sklearn/neighbors/_base.py in _fit(self, X, y)
    433         else:
    434             if not isinstance(X, (KDTree, BallTree, NeighborsBase)):
--> 435                 X = self._validate_data(X, accept_sparse="csr")
    436 
    437         self._check_algorithm_metric()

~/miniconda3/envs/dev_env_37/lib/python3.7/site-packages/sklearn/base.py in _validate_data(self, X, y, reset, validate_separately, **check_params)
    564             raise ValueError("Validation should be done on X, y or both.")
    565         elif not no_val_X and no_val_y:
--> 566             X = check_array(X, **check_params)
    567             out = X
    568         elif no_val_X and not no_val_y:

~/miniconda3/envs/dev_env_37/lib/python3.7/site-packages/sklearn/utils/validation.py in check_array(array, accept_sparse, accept_large_sparse, dtype, order, copy, force_all_finite, ensure_2d, allow_nd, ensure_min_samples, ensure_min_features, estimator)
    744                     array = array.astype(dtype, casting="unsafe", copy=False)
    745                 else:
--> 746                     array = np.asarray(array, order=order, dtype=dtype)
    747             except ComplexWarning as complex_warning:
    748                 raise ValueError(

ValueError: setting an array element with a sequence.

已完成排查:所有子数组的长度、数据类型完全一致,打印features变量输出如下:

array([array([ 0.01691085,  0.02598964,  0.00253213, -0.02223251, -0.00701562]),
       array([ 0.01501954,  0.02484422,  0.00292799, -0.02077107, -0.00611118]),
       array([ 0.01410413,  0.02474243,  0.00117077, -0.02167515, -0.00508685]),
       ...,
       array([ 0.01896316,  0.03188267,  0.00258667, -0.02800867, -0.00646481]),
       array([ 0.03538242,  0.07453772,  0.00816828, -0.02914227, -0.0942148 ]),
       array([ 0.02470775,  0.02561068,  0.00401011, -0.02863882, -0.00419102])],
      dtype=object)
报错根因

scikit-learn的NearestNeighbors.fit()要求输入必须是形状为(n_samples, n_features)的二维数值类型numpy数组,但当前生成的features是dtype=object的一维数组,每个元素是单独的一维numpy数组,属于数组嵌套结构。
即使所有子数组长度、类型完全一致,numpy也无法直接将这种object类型的嵌套数组自动转换为二维浮点数组,因此在sklearn内部调用np.asarray做格式校验时抛出错误。

解决方法

只需要将嵌套的一维数组堆叠为标准二维数值数组即可,核心修改是用np.stack()处理数组列,修正后的代码如下:

import numpy as np
from sklearn.neighbors import NearestNeighbors

df_collect = df.toPandas()
# 将列表列转换为指定类型的numpy数组
df_collect['features'] = df_collect['features'].apply(lambda x: np.array(x, dtype=np.float64))
# 堆叠为形状(样本数, 特征维度)的二维数值数组
features = np.stack(df_collect['features'].values)

# 可选:验证数组格式
# print(features.shape, features.dtype)
knnobj = NearestNeighbors(n_neighbors=5, algorithm='auto').fit(features)

如果数据量较大,toPandas()会把全量数据拉取到Driver节点容易触发内存溢出,建议直接使用PySpark MLlib自带的最近邻实现,避免单节点内存瓶颈。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 21:51:27