TypeError:“NoneType”类型的对象在尝试适合 KerasCLassifier 时没有 len()

Posted

技术标签:

【中文标题】TypeError:“NoneType”类型的对象在尝试适合 KerasCLassifier 时没有 len()【英文标题】:TypeError: object of type 'NoneType' has no len() when trying to fit a KerasCLassifier 【发布时间】:2021-09-13 16:42:05 【问题描述】:

我正在尝试为使用 keras 创建的神经网络创建部分依赖图。为了实现这一点,我必须创建一个 KerasClassifier 或 KerasRegressor。在使用此导入无法正常工作后:

from keras.wrappers.scikit_learn import KerasClassifier

我尝试使用 scikeras 但使用以下代码

import numpy as np
import lime
import lime.lime_tabular
import matplotlib.pyplot as plt

df=pd.read_csv("heart.csv")
df.columns=["age", "sex", "chest_pain_type", "resting_blood_pressure", "cholesterol", "fasting_blood_sugar",
            "resting_ecg", "max_heart_rate", "exercise_induced_angina", "st_depression", "st_slope",
            "number_major_vessels", "thalassemia", "heart_attack"]
X=df.drop("heart_attack", axis=1).to_numpy()
y=df["heart_attack"].to_numpy()

from sklearn.model_selection import train_test_split
import keras
from keras.layers import Dense, Dropout, BatchNormalization
from keras.models import Sequential
from keras.callbacks import EarlyStopping
from scikeras.wrappers import KerasClassifier

def split_data(X, y):
        return train_test_split(X, y, train_size=0.8, random_state=10)

#   KerasClassifier for PDP
###############################################################################

def create_model_classifier():
    model=Sequential()
    model.add(BatchNormalization())
    model.add(Dense(70, activation="relu", input_shape=(13,)))
    model.add(Dense(70, activation="relu"))
    model.add(Dropout(0.2))
    model.add(Dense(70, activation="relu"))
    model.add(Dense(70, activation="relu"))
    model.add(Dense(1,activation="sigmoid"))

    opt=keras.optimizers.Adam(learning_rate=0.0001)
    model.compile(optimizer=opt, loss="binary_crossentropy", metrics=["accuracy", keras.metrics.FalseNegatives(), keras.metrics.FalsePositives()])


    return model

X_train, X_test, y_train, y_test=split_data(X, y)
model_reg = KerasClassifier(model=create_model_classifier)
    
early_stopping=EarlyStopping(monitor="val_loss", patience=10, verbose=0, mode="auto")
history=model_reg.fit(
    X_train,
    y_train,
    epochs=500,
    batch_size=32,
    shuffle=True,
    validation_data=(X_test, y_test),
    callbacks=[early_stopping]
    )

我得到这个错误代码:

Traceback (most recent call last):

  File "C:\Users\Leonard\Desktop\X AI - Heart Attacks\main.py", line 95, in <module>
    history=model_reg.fit(

  File "C:\Users\Leonard\anaconda3\lib\site-packages\scikeras\wrappers.py", line 1416, in fit
    super().fit(X=X, y=y, sample_weight=sample_weight, **kwargs)

  File "C:\Users\Leonard\anaconda3\lib\site-packages\scikeras\wrappers.py", line 747, in fit
    self._fit(

  File "C:\Users\Leonard\anaconda3\lib\site-packages\scikeras\wrappers.py", line 866, in _fit
    self._check_model_compatibility(y)

  File "C:\Users\Leonard\anaconda3\lib\site-packages\scikeras\wrappers.py", line 536, in _check_model_compatibility
    if self.n_outputs_expected_ != len(self.model_.outputs):

TypeError: object of type 'NoneType' has no len()

还有一些警告,因为我的 fit 方法中的参数似乎不是问题。即使我的 fit 方法中只有 X_train 和 y_train,我也会收到此错误。

【问题讨论】:

【参考方案1】:

scikeras.wrappers.KerasClassifierkeras.wrappers.scikit_learn.KerasClassifier 不同。它需要一个tf.keras.Model,它有不同的语法。

以下只是一个例子

import tensorflow as tf

def create_model_classifier():
    inputs = tf.keras.Input(shape=(13,))
    x = tf.keras.layers.Dense(70, activation=tf.nn.relu)(inputs)
    outputs = tf.keras.layers.Dense(70, activation=tf.nn.relu)(x)
    model = tf.keras.Model(inputs=inputs, outputs=outputs)
    return model

文档: https://scikeras.readthedocs.io/en/latest/generated/scikeras.wrappers.KerasClassifier.html

【讨论】:

你确定这会导致错误,因为来自 scikeras 文档的 link 中的模型的实现与我的几乎相同 是的,我确定。在教程中,它使用tf.keras.Sequential 帮助您自动推断输入和输出。但是,keras.Sequential 似乎不适合您。也许,您可以改用tf.keras.Sequential 我现在已经尝试过了。我导入了 tensorflow 并尝试使用 tf.keras.Sequentialtf.keras.models.Sequential 但得到了同样的错误,所以很遗憾似乎还有另一个问题。 仅供参考 @Leonard 的链接指向正确的文档 (adriangb.com/scikeras),readthedocs.io 链接已损坏【参考方案2】:

SciKeras 支持序列模型。

问题似乎是批处理规范层与tf.keras.Model.outputs 属性混淆。我认为它应该遵循您的输入。

这是一个可重现的最小示例:

import numpy as np

X = np.ones((100,1))
y = np.zeros((100,))

from keras.layers import Dense, BatchNormalization
from keras.models import Sequential
from scikeras.wrappers import KerasClassifier

def create_model_classifier():
    model=Sequential()
    model.add(BatchNormalization())
    model.add(Dense(1, activation="relu", input_shape=(1,)))
    model.add(Dense(1,activation="sigmoid"))
    model.compile(optimizer="adam", loss="binary_crossentropy", metrics=["accuracy"])
    return model

model_reg = KerasClassifier(model=create_model_classifier)
    
model_reg.fit(X, y)

在输入层之后注释掉或移动BatchNormalization 层,它应该可以工作(后者可能是您想要的)。

另外,您应该使用import tensorflow.keras ... 而不是import keras ...

【讨论】:

以上是关于TypeError:“NoneType”类型的对象在尝试适合 KerasCLassifier 时没有 len()的主要内容,如果未能解决你的问题,请参考以下文章

Pandas 合并 TypeError:“NoneType”类型的对象没有 len()

Anvil 错误:TypeError:“NoneType”对象不可下标

TypeError: *: 'int' 和 'NoneType' 不支持的操作数类型

TypeError:调用键函数时“NoneType”对象不可迭代

TypeError:“NoneType”对象在 Python 中不可迭代

运行测试时突然出现“TypeError:'NoneType'对象不可迭代