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

安装featurewiz后TensorFlow Keras交叉验证报AttributeError错误

问题:安装featurewiz后Keras交叉验证报错AttributeError: 'Adam' object has no attribute 'get_weights'

背景

我是TensorFlow Keras新手,执行conda install -c conda-forge featurewiz安装featurewiz前代码运行正常,安装后执行交叉验证代码时出现错误。

复现代码

from sklearn.model_selection import KFold, cross_validate, cross_val_score
from scikeras.wrappers import KerasClassifier

estimator = KerasClassifier(model, epochs=500, batch_size=10)
kfold = KFold(n_splits=5, shuffle=True)
results = cross_validate(estimator, X, y, cv=kfold, scoring=['accuracy', 'precision_weighted', 'recall_weighted', 'f1_weighted'], return_train_score=True)
print(results)

核心错误

AttributeError: 'Adam' object has no attribute 'get_weights'

完整错误栈

WARNING:absl:Found untraced functions such as _update_step_xla while saving (showing 1 of 1). These functions will not be directly callable after loading.

INFO:tensorflow:Assets written to: ram:///var/folders/c4/ywdtx99d1vl0ptsg1fy494_40000gn/T/tmpsuvxkjb9/assets

INFO:tensorflow:Assets written to: ram:///var/folders/c4/ywdtx99d1vl0ptsg1fy494_40000gn/T/tmpsuvxkjb9/assets

---------------------------------------------------------------------------
Empty                                     Traceback (most recent call last)
File ~/tensorflow-test/env/lib/python3.8/site-packages/joblib/parallel.py:862, in Parallel.dispatch_one_batch(self, iterator)
    861 try:
--> 862     tasks = self._ready_batches.get(block=False)
    863 except queue.Empty:
    864     # slice the iterator n_jobs * batchsize items at a time. If the
    865     # slice returns less than that, then the current batchsize puts
   (...)
    868     # accordingly to distribute evenly the last items between all
    869     # workers.

File ~/tensorflow-test/env/lib/python3.8/queue.py:167, in Queue.get(self, block, timeout)
    166     if not self._qsize():
--> 167         raise Empty
    168 elif timeout is None:

Empty: 

During handling of the above exception, another exception occurred:

AttributeError                            Traceback (most recent call last)
Cell In[5], line 6
      4 estimator = KerasClassifier(model, epochs=500, batch_size=10) #, verbose = 0
      5 kfold = KFold(n_splits=5, shuffle=True) #seed, damit shuffle gleich bleibt , random_state=1337
----> 6 results = cross_validate(estimator, X, y, cv=kfold, scoring=['accuracy', 'precision_weighted', 'recall_weighted', 'f1_weighted'], return_train_score=True)
      8 print(results)

File ~/tensorflow-test/env/lib/python3.8/site-packages/sklearn/model_selection/_validation.py:266, in cross_validate(estimator, X, y, groups, scoring, cv, n_jobs, verbose, fit_params, pre_dispatch, return_train_score, return_estimator, error_score)
    263 # We clone the estimator to make sure that all the folds are
    264 # independent, and that it is pickle-able.
    265 parallel = Parallel(n_jobs=n_jobs, verbose=verbose, pre_dispatch=pre_dispatch)
--> 266 results = parallel(
    267     delayed(_fit_and_score)(
    268         clone(estimator),
    269         X,
    270         y,
    271         scorers,
    272         train,
    273         test,
    274         verbose,
    275         None,
    276         fit_params,
    277         return_train_score=return_train_score,
    278         return_times=True,
    279         return_estimator=return_estimator,
    280         error_score=error_score,
    281     )
    282     for train, test in cv.split(X, y, groups)
    283 )
    285 _warn_or_raise_about_fit_failures(results, error_score)
    287 # For callabe scoring, the return type is only know after calling. If the
    288 # return type is a dictionary, the error scores can now be inserted with
    289 # the correct key.

File ~/tensorflow-test/env/lib/python3.8/site-packages/joblib/parallel.py:1085, in Parallel.__call__(self, iterable)
   1076 try:
   1077     # Only set self._iterating to True if at least a batch
   1078     # was dispatched. In particular this covers the edge
   (...)
   1082     # was very quick and its callback already dispatched all the
   1083     # remaining jobs.
   1084     self._iterating = False
--> 1085     if self.dispatch_one_batch(iterator):
   1086         self._iterating = self._original_iterator is not None
   1088     while self.dispatch_one_batch(iterator):

File ~/tensorflow-test/env/lib/python3.8/site-packages/joblib/parallel.py:873, in Parallel.dispatch_one_batch(self, iterator)
    870 n_jobs = self._cached_effective_n_jobs
    871 big_batch_size = batch_size * n_jobs
--> 873 islice = list(itertools.islice(iterator, big_batch_size))
    874 if len(islice) == 0:
    875     return False

File ~/tensorflow-test/env/lib/python3.8/site-packages/sklearn/model_selection/_validation.py:268, in <genexpr>(.0)
    263 # We clone the estimator to make sure that all the folds are
    264 # independent, and that it is pickle-able.
    265 parallel = Parallel(n_jobs=n_jobs, verbose=verbose, pre_dispatch=pre_dispatch)
    266 results = parallel(
    267     delayed(_fit_and_score)(
--> 268         clone(estimator),
    269         X,
    270         y,
    271         scorers,
    272         train,
    273         test,
    274         verbose,
    275         None,
    276         fit_params,
    277         return_train_score=return_train_score,
    278         return_times=True,
    279         return_estimator=return_estimator,
    280         error_score=error_score,
    281     )
    282     for train, test in cv.split(X, y, groups)
    283 )
    285 _warn_or_raise_about_fit_failures(results, error_score)
    287 # For callabe scoring, the return type is only know after calling. If the
    288 # return type is a dictionary, the error scores can now be inserted with
    289 # the correct key.

File ~/tensorflow-test/env/lib/python3.8/site-packages/sklearn/base.py:89, in clone(estimator, safe)
     87 new_object_params = estimator.get_params(deep=False)
     88 for name, param in new_object_params.items():
--> 89     new_object_params[name] = clone(param, safe=False)
     90 new_object = klass(**new_object_params)
     91 params_set = new_object.get_params(deep=False)

File ~/tensorflow-test/env/lib/python3.8/site-packages/sklearn/base.py:70, in clone(estimator, safe)
     68 elif not hasattr(estimator, "get_params") or isinstance(estimator, type):
     69     if not safe:
--> 70         return copy.deepcopy(estimator)
     71     else:
     72         if isinstance(estimator, type):

File ~/tensorflow-test/env/lib/python3.8/copy.py:153, in deepcopy(x, memo, _nil)
    151 copier = getattr(x, "__deepcopy__", None)
    152 if copier is not None:
--> 153     y = copier(memo)
    154 else:
    155     reductor = dispatch_table.get(cls)

File ~/tensorflow-test/env/lib/python3.8/site-packages/scikeras/_saving_utils.py:117, in deepcopy_model(model, memo)
    116 def deepcopy_model(model: keras.Model, memo: Dict[Hashable, Any]) -> keras.Model:
--> 117     _, (model_bytes, optimizer_weights) = pack_keras_model(model)
    118     new_model = unpack_keras_model(model_bytes, optimizer_weights)
    119     memo[model] = new_model

File ~/tensorflow-test/env/lib/python3.8/site-packages/scikeras/_saving_utils.py:108, in pack_keras_model(model)
    106 optimizer_weights = None
    107 if model.optimizer is not None:
--> 108     optimizer_weights = model.optimizer.get_weights()
    109 model_bytes = np.asarray(memoryview(b.read()))
    110 return (
    111     unpack_keras_model,
    112     (model_bytes, optimizer_weights),
    113 )

AttributeError: 'Adam' object has no attribute 'get_weights'

环境信息

  • 设备:M1 Mac
  • TensorFlow版本:2.11.0
  • 可正常识别CPU和GPU设备

解决方案

1. 回退环境排查依赖冲突

安装featurewiz可能更新了TensorFlow/Keras相关依赖,导致版本不兼容:

  • 查看环境修订记录并回退到安装前状态:
    conda list --revisions
    conda install --revision <对应修订号>
    
  • 确认使用的是TensorFlow原生tf.keras.optimizers.Adam,而非其他库的实现。

2. 修改Scikeras使用方式

问题出在克隆已编译模型时的优化器权重获取,改用模型构建函数规避:

def build_model():
    # 定义你的模型结构
    model = ...
    # 编译模型
    model.compile(optimizer="adam", loss="你的损失函数", metrics=["accuracy"])
    return model

# 传入构建函数而非已编译模型
estimator = KerasClassifier(model=build_model, epochs=500, batch_size=10)

这样每个交叉验证fold会重新构建模型,避免克隆已编译模型的问题。

3. 初始化优化器权重

未训练的模型优化器可能未初始化,提前触发初始化:

# 传入一个和输入维度匹配的空数组,触发优化器初始化
model.predict(np.zeros((1, X.shape[1])))

estimator = KerasClassifier(model, epochs=500, batch_size=10)

4. 调整库版本

  • 安装兼容TensorFlow 2.11的Scikeras版本,例如scikeras==0.11.0
  • 创建新conda环境,先安装TensorFlow和Scikeras验证代码,再逐步加入featurewiz,确认冲突来源

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 15:30:59