【问题标题】:Keras: Callbacks Requiring Validation Split?Keras:需要验证拆分的回调?
【发布时间】:2019-03-14 19:11:37
【问题描述】:

我正在使用 Keras 2.1.3 和 Tensorflow 后端解决多类分类问题。我有两个 numpy 数组,xy,我正在使用 tf.data.Dataset,如下所示:

dataset = tf.data.Dataset.from_tensor_slices(({"sequence": x}, y))
dataset = dataset.apply(tf.contrib.data.batch_and_drop_remainder(self.batch_size))
dataset = dataset.repeat()
xt, yt = dataset.make_one_shot_iterator().get_next()

然后我制作我的 Keras 模型(为简洁起见,省略)、编译和拟合:

model.compile(
    loss='categorical_crossentropy',
    optimizer='adam',
    metrics=['accuracy'],
)
model.fit(xt, yt, steps_per_epoch=100, epochs=10)

这很好用。但是当我添加回调时,我遇到了问题。具体来说,如果我这样做:

callbacks = [
    tf.keras.callbacks.ModelCheckpoint("model_{epoch:04d}_{val_acc:.4f}.h5",
                    monitor='val_acc',
                    verbose=1,
                    save_best_only=True,
                    mode='max'),
    tf.keras.callbacks.TensorBoard(os.path.join('.', 'logs')),
    tf.keras.callbacks.EarlyStopping(monitor='val_acc', patience=5, min_delta=0, mode='max')
]
model.fit(xt, yt, steps_per_epoch=10, epochs=100, callbacks=callbacks)

我明白了:

KeyError: 'val_acc'

另外,如果我在model.fit(...) 通话中包含validation_split=0.1,我会被告知:

ValueError: If your data is in the form of symbolic tensors, you cannot use validation_split.`

tf.data.Dataset(张量)中使用回调和验证拆分的常规方法是什么?

谢谢!

【问题讨论】:

  • 您没有在此培训电话中使用datasetmodel.fit(x, y, steps_per_epoch=10, epochs=100, callbacks=callbacks)。如果你使用 x 和 y (numpy) 而不使用 TF dataset,那么 validation_split 应该可以工作。
  • @GergesDib 抱歉,之前打错了。那个电话应该是model.fit(xt, yt, steps_per_epoch=10, epochs=100, callbacks=callbacks)。鉴于此,我将如何验证拆分 + 回调?
  • 什么是xtyt? tensorflow 数据集定义为dataset
  • @GergesDib 刚刚更新以澄清。来自这一行:xt, yt = dataset.make_one_shot_iterator().get_next()
  • 您可能需要先拆分数据,然后再将其提供给fit,并使用validation_data 来提供val 集。在此处查看如何使用它的示例tensorflow.org/guide/keras#input_tfdata_datasets

标签: python tensorflow keras


【解决方案1】:

使用 tensorflow keras API,您可以提供一个Dataset 用于训练,另一个用于验证。

首先是一些导入

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.layers import Dense
import numpy as np

定义将 numpy 数组拆分为 training/val 的函数

def split(x, y, val_size=50):
    idx = np.random.choice(x.shape[0], size=val_size, replace=False)
    not_idx = list(set(range(x.shape[0])).difference(set(idx)))

    x_val = x[idx]
    y_val = y[idx]
    x_train = x[not_idx]
    y_train = y[not_idx]
    return x_train, y_train, x_val, y_val

定义 numpy 数组和 train/val tensorflow Datasets

x = np.random.randn(150, 9)
y = np.random.randint(0, 10, 150)

x_train, y_train, x_val, y_val = split(x, y)

train_dataset = tf.data.Dataset.from_tensor_slices((x_train, tf.one_hot(y_train, depth=10)))
train_dataset = train_dataset.batch(32).repeat()

val_dataset = tf.data.Dataset.from_tensor_slices((x_val, tf.one_hot(y_val, depth=10)))
val_dataset = val_dataset.batch(32).repeat()

制作模型(注意我们使用的是 tensorflow keras API)

model = keras.models.Sequential([Dense(64, input_shape=(9,), activation='relu'),
                                 Dense(64, activation='relu'),
                                 Dense(10, activation='softmax')
                                ])
model.compile(optimizer='Adam', loss='categorical_crossentropy',
              metrics=['accuracy'])
model.summary()


model.fit(train_dataset,
          epochs=10, 
          steps_per_epoch=int(100/32)+1,
          validation_data=val_dataset,
          validation_steps=2)

和模型火车,种类(输出):

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 64)                640       
_________________________________________________________________
dense_1 (Dense)              (None, 64)                4160      
_________________________________________________________________
dense_2 (Dense)              (None, 10)                650       
=================================================================
Total params: 5,450
Trainable params: 5,450
Non-trainable params: 0
_________________________________________________________________
Epoch 1/10
4/4 [==============================] - 0s 69ms/step - loss: 2.3170 - acc: 0.1328 - val_loss: 2.3877 - val_acc: 0.0712
Epoch 2/10
4/4 [==============================] - 0s 2ms/step - loss: 2.2628 - acc: 0.2500 - val_loss: 2.3850 - val_acc: 0.0712
Epoch 3/10
4/4 [==============================] - 0s 2ms/step - loss: 2.2169 - acc: 0.2656 - val_loss: 2.3838 - val_acc: 0.0712
Epoch 4/10
4/4 [==============================] - 0s 2ms/step - loss: 2.1743 - acc: 0.3359 - val_loss: 2.3830 - val_acc: 0.0590
Epoch 5/10
4/4 [==============================] - 0s 2ms/step - loss: 2.1343 - acc: 0.3594 - val_loss: 2.3838 - val_acc: 0.0590
Epoch 6/10
4/4 [==============================] - 0s 2ms/step - loss: 2.0959 - acc: 0.3516 - val_loss: 2.3858 - val_acc: 0.0590
Epoch 7/10
4/4 [==============================] - 0s 4ms/step - loss: 2.0583 - acc: 0.3750 - val_loss: 2.3887 - val_acc: 0.0590
Epoch 8/10
4/4 [==============================] - 0s 2ms/step - loss: 2.0223 - acc: 0.4453 - val_loss: 2.3918 - val_acc: 0.0747
Epoch 9/10
4/4 [==============================] - 0s 2ms/step - loss: 1.9870 - acc: 0.4609 - val_loss: 2.3954 - val_acc: 0.1059
Epoch 10/10
4/4 [==============================] - 0s 2ms/step - loss: 1.9523 - acc: 0.4609 - val_loss: 2.3995 - val_acc: 0.1059

回调

添加回调也可以,

callbacks = [ tf.keras.callbacks.ModelCheckpoint("model_{epoch:04d}_{val_acc:.4f}.h5",
                    monitor='val_acc',
                    verbose=1,
                    save_best_only=True,
                    mode='max'),
    tf.keras.callbacks.TensorBoard('./logs'),
    tf.keras.callbacks.EarlyStopping(monitor='val_acc', patience=5, min_delta=0, mode='max')
]


model.fit(train_dataset, epochs=10, steps_per_epoch=int(100/32)+1, validation_data=val_dataset,
          validation_steps=2, callbacks=callbacks)

输出:

Epoch 1/10
4/4
 [==============================] - 0s 59ms/step - loss: 2.3274 - acc: 0.1094 - val_loss: 2.3143 - val_acc: 0.0833

Epoch 00001: val_acc improved from -inf to 0.08333, saving model to model_0001_0.0833.h5
Epoch 2/10
4/4 [==============================] - 0s 2ms/step - loss: 2.2655 - acc: 0.1094 - val_loss: 2.3204 - val_acc: 0.1389

Epoch 00002: val_acc improved from 0.08333 to 0.13889, saving model to model_0002_0.1389.h5
Epoch 3/10
4/4 [==============================] - 0s 5ms/step - loss: 2.2122 - acc: 0.1250 - val_loss: 2.3289 - val_acc: 0.1111

Epoch 00003: val_acc did not improve from 0.13889
Epoch 4/10
4/4 [==============================] - 0s 2ms/step - loss: 2.1644 - acc: 0.1953 - val_loss: 2.3388 - val_acc: 0.0556

Epoch 00004: val_acc did not improve from 0.13889
Epoch 5/10
4/4 [==============================] - 0s 2ms/step - loss: 2.1211 - acc: 0.2734 - val_loss: 2.3495 - val_acc: 0.0556

Epoch 00005: val_acc did not improve from 0.13889
Epoch 6/10
4/4 [==============================] - 0s 4ms/step - loss: 2.0808 - acc: 0.2969 - val_loss: 2.3616 - val_acc: 0.0556

Epoch 00006: val_acc did not improve from 0.13889
Epoch 7/10
4/4 [==============================] - 0s 2ms/step - loss: 2.0431 - acc: 0.2969 - val_loss: 2.3749 - val_acc: 0.0712

Epoch 00007: val_acc did not improve from 0.13889

【讨论】:

  • 这非常有帮助!当你说Make the model (notice we are using the tensorflow keras API)时,你能详细说明一下吗?我正在使用tf.keras.layers.Inputtf.keras.layers.Conv1D 之类的东西。你是说我不应该?
  • 你使用正确,tensorflow-keras API是tf.keras.....。这与我在这里所做的相同(但我使用 import 语句做捷径)...
【解决方案2】:

我认为你的问题是数据集的类型,其中xtyt不是列表或数组,所以它不能切片或拆分。

假设x(1000,2) 987654324 @填写随机数使用numpy和y是10个类的类。

# Define x and y
import numpy as np
np.random.seed(2018)
n_cat = 10
x = np.random.rand(1000,2)  # Generate random 2 variables and 1000 rows
y = [np.random.randint(1,n_cat) for i in range(len(x))]     # Make 10 class

然后组装模型并编译

model.compile(
    loss='categorical_crossentropy',
    optimizer='adam',
    metrics=['accuracy'],
)

为检查点模型创建回调

callbacks = [
    tf.keras.callbacks.ModelCheckpoint("model_{epoch:04d}_{val_acc:.4f}.h5",
                    monitor='val_acc',
                    verbose=1,
                    save_best_only=True,
                    mode='max'),
    tf.keras.callbacks.TensorBoard(os.path.join('.', 'logs')),
    tf.keras.callbacks.EarlyStopping(monitor='val_acc', patience=5, min_delta=0, mode='max')
]

适合模型

model.fit(x, y, batch_size=32, epochs=100, callbacks=callbacks, validation_split=0.1)

它适合我。

【讨论】:

    猜你喜欢
    • 2017-09-05
    • 2019-04-20
    • 2019-07-06
    • 1970-01-01
    • 1970-01-01
    • 2021-06-12
    • 1970-01-01
    • 1970-01-01
    • 2017-01-18
    相关资源
    最近更新 更多