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

使用Scikit-learn kNN分类模型时遇AttributeError问题求助

问题

使用Scikit-learn构建kNN分类模型,X为0-1之间的数值列,Y对应5种健康类别。运行代码时出现AttributeError: 'NoneType' object has no attribute 'split'错误,决策树分类器无此问题。已更新Scikit-learn至最新版本,运行环境为Anaconda3。

代码

HealthX = Health.drop(columns='Reported_Health')#Produces a dataframe of all the population-by-health proportions
HealthY = Health['Reported_Health']#Produces a dataframe of all the reported healths

HealthX_Train, HealthX_Test, HealthY_Train, HealthY_Test = train_test_split(HealthX, HealthY, test_size = 0.2, random_state = 413, stratify=HealthY) #split the data into training and testing data

kNN_3U = KNeighborsClassifier(3, weights='uniform') #Declares a Uniform-weighted 3-NN machiene learning model
kNN_3U = Pipeline([('scaler', StandardScaler()), ('model', kNN_3U)]) #appends the model variable to include scalar data processing using a pipeline
kNN_3U.fit(HealthX_Train, HealthY_Train) #Trains the machiene learning algorithm on the given training data

kNN_3U_Ac_Train = accuracy_score(HealthY_Train, kNN_3U.predict(HealthX_Train)) #Calculates the micro-accuracy of the machiene learning model during the Training Phase

错误信息

AttributeError                            Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_29052/877452642.py in <module>
      3 kNN_3U.fit(HealthX_Train, HealthY_Train) #Trains the machiene learning algorithm on the given training data
      4 
----> 5 kNN_3U_Ac_Train = accuracy_score(HealthY_Train, kNN_3U.predict(HealthX_Train)) #Calculates the micro-accuracy of the machiene learning model during the Training Phase
      6 kNN_3U_BAc_Train = balanced_accuracy_score(HalthY_Train, kNN_3U.predict(HealthX_Train)) #Calculates the macro-accuracy of the machiene learning model during the Training Phase
      7 kNN_3U_Ac_Test = accuracy_score(HealthY_Test, kNN_3U.predict(HealthX_Test)) #Calculates the micro-accuracy of the machiene learning model during the Testing Phase

~\AppData\Roaming\Python\Python38\site-packages\sklearn\pipeline.py in predict(self, X, **predict_params)
    506         for _, name, transform in self._iter(with_final=False):
    507             Xt = transform.transform(Xt)
--> 508         return self.steps[-1][1].predict(Xt, **predict_params)
    509 
    510     @available_if(_final_estimator_has("fit_predict"))

~\AppData\Roaming\Python\Python38\site-packages\sklearn\neighbors\_classification.py in predict(self, X)
    259             # In that case, we do not need the distances to perform
    260             # the weighting so we do not compute them.
--> 261             neigh_ind = self.kneighbors(X, return_distance=False)
    262             neigh_dist = None
    263         else:

~\AppData\Roaming\Python\Python38\site-packages\sklearn\neighbors\_base.py in kneighbors(self, X, n_neighbors, return_distance)
    820         )
    821         if use_pairwise_distances_reductions:
--> 822             results = ArgKmin.compute(
    823                 X=X,
    824                 Y=self._fit_X,

~\AppData\Roaming\Python\Python38\site-packages\sklearn\metrics\_pairwise_distances_reduction\_dispatcher.py in compute(cls, X, Y, k, metric, chunk_size, metric_kwargs, strategy, return_distance)
    256         """
    257         if X.dtype == Y.dtype == np.float64:
--> 258             return ArgKmin64.compute(
    259                 X=X,
    260                 Y=Y,

sklearn\metrics\_pairwise_distances_reduction\_argkmin.pyx in sklearn.metrics._pairwise_distances_reduction._argkmin.ArgKmin64.compute()

~\AppData\Roaming\Python\Python38\site-packages\sklearn\utils\fixes.py in threadpool_limits(limits, user_api)
     70         return controller.limit(limits=limits, user_api=user_api)
     71     else:
--> 72         return threadpoolctl.threadpool_limits(limits=limits, user_api=user_api)
     73 
     74 

~\AppData\Roaming\Python\Python38\site-packages\threadpoolctl.py in __init__(self, limits, user_api)
    169             self._check_params(limits, user_api)
    170 
--> 171         self._original_info = self._set_threadpool_limits()
    172 
    173     def __enter__(self):

~\AppData\Roaming\Python\Python38\site-packages\threadpoolctl.py in _set_threadpool_limits(self)
    266             return None
    267 
--> 268         modules = _ThreadpoolInfo(prefixes=self._prefixes,
    269                                   user_api=self._user_api)
    270         for module in modules:

~\AppData\Roaming\Python\Python38\site-packages\threadpoolctl.py in __init__(self, user_api, prefixes, modules)
    338 
    339             self.modules = []
--> 340             self._load_modules()
    341             self._warn_if_incompatible_openmp()
    342         else:

~\AppData\Roaming\Python\Python38\site-packages\threadpoolctl.py in _load_modules(self)
    371             self._find_modules_with_dyld()
    372         elif sys.platform == "win32":
--> 373             self._find_modules_with_enum_process_module_ex()
    374         else:
    375             self._find_modules_with_dl_iterate_phdr()

~\AppData\Roaming\Python\Python38\site-packages\threadpoolctl.py in _find_modules_with_enum_process_module_ex(self)
    483 
    484                 # Store the module if it is supported and selected
--> 485                 self._make_module_from_path(filepath)
    486         finally:
    487             kernel_32.CloseHandle(h_process)

~\AppData\Roaming\Python\Python38\site-packages\threadpoolctl.py in _make_module_from_path(self, filepath)
    513             if prefix in self.prefixes or user_api in self.user_api:
    514                 module_class = globals()[module_class]
--> 515                 module = module_class(filepath, prefix, user_api, internal_api)
    516                 self.modules.append(module)
    517 

~\AppData\Roaming\Python\Python38\site-packages\threadpoolctl.py in __init__(self, filepath, prefix, user_api, internal_api)
    604         self.internal_api = internal_api
    605         self._dynlib = ctypes.CDLL(filepath, mode=_RTLD_NOLOAD)
--> 606         self.version = self.get_version()
    607         self.num_threads = self.get_num_threads()
    608         self._get_extra_info()

~\AppData\Roaming\Python\Python38\site-packages\threadpoolctl.py in get_version(self)
    644                              lambda: None)
    645         get_config.restype = ctypes.c_char_p
--> 646         config = get_config().split()
    647         if config[0] == b"OpenBLAS":
    648             return config[1].decode("utf-8")

AttributeError: 'NoneType' object has no attribute 'split'

原因分析

这个错误并非kNN模型本身的问题,而是threadpoolctl库在检测OpenBLAS版本时出现异常。当kNN调用底层的距离计算函数时,Scikit-learn会触发threadpoolctl来管理线程池,而你的环境中OpenBLAS的配置函数返回了None,导致后续调用split()方法报错。决策树不需要调用这类底层线程优化的距离计算逻辑,所以不会触发该错误。

解决方法

方法1:升级或降级threadpoolctl库

该问题是特定版本的threadpoolctl与OpenBLAS的兼容性问题,尝试更新到最新版:

pip install --upgrade threadpoolctl

如果更新后仍有问题,尝试降级到已知兼容的版本:

pip install threadpoolctl==3.1.0

方法2:禁用Scikit-learn的线程池限制

在代码开头添加以下代码,强制关闭threadpoolctl的自动线程管理:

import os
os.environ['SKLEARN_DISABLE_THREADPOOL'] = '1'

方法3:替换OpenBLAS为其他线性代数库

如果使用Anaconda,可以切换到MKL库(Intel的线性代数库,兼容性更好):

conda install mkl

方法4:避免使用pairwise distances reduction优化

在kNN模型中禁用多线程优化,强制使用传统的距离计算方式:

from sklearn.neighbors import KNeighborsClassifier
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

# 初始化kNN时设置n_jobs=1,禁用多线程优化
kNN_3U = KNeighborsClassifier(3, weights='uniform', n_jobs=1)
kNN_3U = Pipeline([('scaler', StandardScaler()), ('model', kNN_3U)])

内容的提问来源于stack exchange,提问作者A S Arrowsmith

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 19:25:54