使用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
相关产品推荐
相关产品推荐

