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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 07:15:14