sklearn.cluster.KMeans运行报错求助:AttributeError问题排查
问题:KMeans运行触发AttributeError错误
从scikit-learn官方文档复制的KMeans示例代码:
from sklearn.cluster import KMeans import numpy as np X = np.array([[1, 2], [1, 4], [1, 0],[10, 2], [10, 4], [10, 0]]) kmeans = KMeans(n_clusters=2, random_state=0, n_init="auto").fit(X) kmeans.labels_
运行后触发AttributeError,报错栈如下:
AttributeError Traceback (most recent call last) Input In [4], in <cell line: 4>() 2 import numpy as np 3 X = np.array([[1, 2], [1, 4], [1, 0],[10, 2], [10, 4], [10, 0]]) ----> 4 kmeans = KMeans(n_clusters=2, random_state=0, n_init="auto").fit(X) 5 kmeans.labels_ File ~\anaconda3\lib\site-packages\sklearn\cluster\_kmeans.py:1455, in KMeans.fit(self, X, y, sample_weight) 1453 else: 1454 kmeans_single = _kmeans_single_lloyd -> 1455 self._check_mkl_vcomp(X, X.shape[0]) 1457 best_inertia, best_labels = None, None 1459 for i in range(self._n_init): 1460 # Initialize centers File ~\anaconda3\lib\site-packages\sklearn\cluster\_kmeans.py:911, in _BaseKMeans._check_mkl_vcomp(self, X, n_samples) 909 n_active_threads = int(np.ceil(n_samples / CHUNK_SIZE)) 910 if n_active_threads < self._n_threads: -> 911 modules = threadpool_info() 912 has_vcomp = "vcomp" in [module["prefix"] for module in modules] 913 has_mkl = ("mkl", "intel") in [ 914 (module["internal_api"], module.get("threading_layer", None)) 915 for module in modules 916 ] File ~\anaconda3\lib\site-packages\sklearn\utils\fixes.py:150, in threadpool_info() 148 return controller.info() 149 else: -> 150 return threadpoolctl.threadpool_info() File ~\anaconda3\lib\site-packages\threadpoolctl.py:124, in threadpool_info() 107 @_format_docstring(USER_APIS=list(_ALL_USER_APIS), 108 INTERNAL_APIS=_ALL_INTERNAL_APIS) 109 def threadpool_info(): 110 """Return the maximal number of threads for each detected library. 111 112 Return a list with all the supported modules that have been found. Each (...) 122 In addition, each module may contain internal_api specific entries. 123 """ -> 124 return _ThreadpoolInfo(user_api=_ALL_USER_APIS).todicts() File ~\anaconda3\lib\site-packages\threadpoolctl.py:340, in _ThreadpoolInfo.__init__(self, user_api, prefixes, modules) 337 self.user_api = [] if user_api is None else user_api 339 self.modules = [] -> 340 self._load_modules() 341 self._warn_if_incompatible_openmp() 342 else: File ~\anaconda3\lib\site-packages\threadpoolctl.py:373, in _ThreadpoolInfo._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() File ~\anaconda3\lib\site-packages\threadpoolctl.py:485, in _ThreadpoolInfo._find_modules_with_enum_process_module_ex(self) 482 filepath = buf.value 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) File ~\anaconda3\lib\site-packages\threadpoolctl.py:515, in _ThreadpoolInfo._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) File ~\anaconda3\lib\site-packages\threadpoolctl.py:606, in _Module.__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() File ~\anaconda3\lib\site-packages\threadpoolctl.py:646, in _OpenBLASModule.get_version(self) 643 get_config = getattr(self._dynlib, "openblas_get_config", 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'
已尝试将scikit-learn降级到1.2.2(与Google Colab版本一致),其他scikit-learn函数运行正常,但KMeans仍报错。
问题原因
该错误并非scikit-learn本身的问题,而是依赖库threadpoolctl在检测OpenBLAS版本时的bug:当OpenBLAS的openblas_get_config()函数返回None时,代码直接调用split()方法,触发AttributeError。
解决方法
方法1:升级threadpoolctl到修复版本
执行以下命令升级threadpoolctl到>=3.1.0版本(该版本已修复此bug):
pip install --upgrade threadpoolctl
方法2:临时禁用线程池检测
在代码开头添加以下环境变量设置,跳过线程池相关检测:
import os os.environ["OMP_NUM_THREADS"] = "1" os.environ["OPENBLAS_NUM_THREADS"] = "1"
方法3:更换线性代数库
若使用Anaconda环境,可安装MKL替代OpenBLAS,避免该兼容性问题:
conda install mkl
内容的提问来源于stack exchange,提问作者Ho Chung Yip
相关产品推荐
相关产品推荐

