首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >TypeError:“list”对象不是迭代器- Tensorflow自定义回调

TypeError:“list”对象不是迭代器- Tensorflow自定义回调
EN

Stack Overflow用户
提问于 2020-09-11 06:31:41
回答 1查看 654关注 0票数 0

遇到一个问题,试图让自定义的度量回调与Tensorflow一起工作。我在下面创建了一个最小的工作示例,以帮助解决问题。我在跑:

代码语言:javascript
运行
复制
Windows 10
Python 3.6

scikit-learn==0.23.2
pandas==0.25.3
numpy==1.18.5
tensorflow==2.3.0

使用乳腺癌二进制数据集,我试图调用显示为解在这里的自定义度量,但是遇到了上述错误,可能是因为我没有正确地使用它。

这个密码..。

代码语言:javascript
运行
复制
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import precision_score, recall_score, f1_score
import pandas as pd
import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.callbacks import Callback

# Get binary classification dataset
data = load_breast_cancer(as_frame=True)
print(data)
df = data['data']
df['target'] = data['target']

# Train Test split
train, test = train_test_split(data, test_size = 0.10, shuffle=False)

# Define features and labels
x_train = train.iloc[:, :-1]
y_train = train.iloc[:, -1]
x_test = test.iloc[:, :-1]
y_test = test.iloc[:, -1]

# https://github.com/keras-team/keras/issues/10472#issuecomment-472543538
class Metrics(Callback):
    
    def __init__(self, val_data, batch_size=20):
        super().__init__()
        self.validation_data = val_data
        self.batch_size = batch_size
    
    def on_train_begin(self, logs={}):
        # print(self.validation_data)
        self.val_f1s = []
        self.val_recalls = []
        self.val_precisions = []
        
    def on_epoch_end(self, epoch, logs={}):
        batches = len(self.validation_data)
        total = batches * self.batch_size
        
        val_pred = np.zeros((total,1))
        val_true = np.zeros((total))
        
        for batch in range(batches):
            xVal, yVal = next(self.validation_data)
            val_pred[batch * self.batch_size : (batch+1) * self.batch_size] = np.asarray(self.model.predict(xVal)).round()
            val_true[batch * self.batch_size : (batch+1) * self.batch_size] = yVal
            
        val_pred = np.squeeze(val_pred)
        _val_f1 = f1_score(val_true, val_pred)
        _val_precision = precision_score(val_true, val_pred)
        _val_recall = recall_score(val_true, val_pred)
        
        self.val_f1s.append(_val_f1)
        self.val_recalls.append(_val_recall)
        self.val_precisions.append(_val_precision)
        
        return

# Define a function that creates a basic model
def make_deep_learning_classifier():
    model = Sequential()
    model.add(Dense(64, activation='relu', input_dim=x_train.shape[1], kernel_initializer='normal'))
    model.add(Dense(32, activation='relu', input_dim=x_train.shape[1], kernel_initializer='normal'))
    model.add(Dense(1, kernel_initializer='normal', activation='sigmoid'))
    model.compile(loss='binary_crossentropy', optimizer=Adam(), metrics=['accuracy'])
    return model

# Get our model
model = make_deep_learning_classifier()
print(model.summary())

# Define some params
batch_size = 32

# Call our custom callback
callback = [Metrics(val_data=[x_test, y_test], batch_size=batch_size)] # < Issue here?

# Start training
model.fit(x_train, y_train, epochs=1000, batch_size=batch_size, verbose=1, callbacks=callback, validation_data=(x_test, y_test))
print(Metrics.val_precisions) # < Issue here?

...produces这个回溯..。

代码语言:javascript
运行
复制
  File "test.py", line 91, in <module>
    model.fit(x_train, y_train, epochs=1000, batch_size=batch_size, verbose=1, callbacks=callback, validation_data=(x_test, y_test))
  File "C:\Users\...\AppData\Local\Programs\Python\Python36\lib\site-packages\tensorflow\python\keras\engine\training.py", line 108, in _method_wrapper
    return method(self, *args, **kwargs)
  File "C:\Users\...\AppData\Local\Programs\Python\Python36\lib\site-packages\tensorflow\python\keras\engine\training.py", line 1137, in fit
    callbacks.on_epoch_end(epoch, epoch_logs)
  File "C:\Users\...\AppData\Local\Programs\Python\Python36\lib\site-packages\tensorflow\python\keras\callbacks.py", line 416, in on_epoch_end
    callback.on_epoch_end(epoch, numpy_logs)
  File "test.py", line 54, in on_epoch_end
    xVal, yVal = next(self.validation_data)
TypeError: 'list' object is not an iterator

当我在val_data=[x_test, y_test]变量中将val_data=(x_test, y_test)改为val_data=(x_test, y_test)时,我得到.

代码语言:javascript
运行
复制
TypeError: 'tuple' object is not an iterator

提出此回调解决方案的用户提到了一些有关生成器的内容,但我不确定这些生成器是如何工作的。只想为Tensorflow/Keras定义我自己的自定义度量。我不会使用这个确切的回调,但是一旦我运行了这个回调,我就可以将它修改为自己的回调。我只是把它作为一个似乎在GitHub文章中起作用的例子,希望有人能指出我做错了什么。

谢谢!

更新

使用下面的解决方案,我尝试通过以下方法正确地调用我的val_data上的迭代器函数

代码语言:javascript
运行
复制
iter_val_data = iter(self.validation_data)
for batch in range(batches):
    xVal, yVal = next(iter_val_data)

但是,我得到的值太多,无法打开错误包,因此我将其更改为:

代码语言:javascript
运行
复制
iter_val_data = iter(self.validation_data)
for batch in range(batches):
    xVal = next(iter_val_data)
    yVal = next(iter_val_data)

然后我得到了错误:

代码语言:javascript
运行
复制
Traceback (most recent call last):
  File "test.py", line 89, in <module>
    model.fit(x_train, y_train, epochs=1000, batch_size=batch_size, verbose=1, callbacks=callback, validation_data=(x_test, y_test))
  File "C:\Users\...\AppData\Local\Programs\Python\Python36\lib\site-packages\tensorflow\python\keras\engine\training.py", line 108, in _method_wrapper
    return method(self, *args, **kwargs)
  File "C:\Users\...\AppData\Local\Programs\Python\Python36\lib\site-packages\tensorflow\python\keras\engine\training.py", line 1137, in fit
    callbacks.on_epoch_end(epoch, epoch_logs)
  File "C:\Users\...\AppData\Local\Programs\Python\Python36\lib\site-packages\tensorflow\python\keras\callbacks.py", line 416, in on_epoch_end
    callback.on_epoch_end(epoch, numpy_logs)
  File "test.py", line 53, in on_epoch_end
    val_pred[batch * self.batch_size : (batch+1) * self.batch_size] = np.asarray(self.model.predict(xVal)).round()
ValueError: could not broadcast input array from shape (57,1) into shape (32,1)

这里有什么想法吗?如果可以的话,试着在上面描述的相同环境中运行代码。谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-09-11 06:59:50

当您看到这里时,当您的错误消息声明时,您需要在迭代器中使用next()。您在列表中调用next()next()如何知道下一个元素是哪个?为此,您需要一个迭代器,以保存该状态。所以这应该可以解决你的问题:

代码语言:javascript
运行
复制
iter_val_data = iter(self.validation_data)
for batch in range(batches):
    xVal, yVal = next(iter_val_data)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63841876

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档