Keras - 使用 HDF5Matrix 拟合模型时出错

数据挖掘 喀拉斯
2022-02-10 22:33:17

所以我这样定义我的数据:

x_train = keras.utils.io_utils.HDF5Matrix('dataset.h5', 'x_train')
y_train = keras.utils.io_utils.HDF5Matrix('dataset.h5', 'y_train')
x_test = keras.utils.io_utils.HDF5Matrix('dataset.h5', 'x_test')
y_test = keras.utils.io_utils.HDF5Matrix('dataset.h5', 'y_test')

但是当我尝试像这样拟合模型时:

model.fit(x_train, y_train, epochs=epochs, 
          validation_data=(x_test, y_test), 
          callbacks=[tensorboard, modelcheckpoint], 
          batch_size=batch_size, shuffle=False)

我收到此错误:

File "G:\CryptoForecast\cryptomodel.py", line 34, in train_model
    model.fit(x_train, y_train, epochs=epochs, validation_data=(x_test, y_test), callbacks=[tensorboard, modelcheckpoint], batch_size=batch_size, shuffle=False)
  File "C:\ProgramData\Anaconda3\envs\TradingBot\lib\site-packages\keras\engine\training.py", line 952, in fit
    batch_size=batch_size)
  File "C:\ProgramData\Anaconda3\envs\TradingBot\lib\site-packages\keras\engine\training.py", line 670, in _standardize_user_data
    'You passed: x=' + str(x))
ValueError: Please provide as model inputs either a single array or a list of arrays. You passed: x=<keras.utils.io_utils.HDF5Matrix object at 0x000002342575E4E0>

但它应该工作,不是吗?

2个回答

您可以在实例的fit()方法中看到,输入首先通过在第 643 行Model调用的方法发送_standardize_user_data

错误来源

您的错误消息来自该文件中第 650到 671 行的检查:

if not self.built:
    # We need to use `x` to set the model inputs.
    # We type-check that `x` and `y` are either single arrays
    # or lists of arrays.
    if isinstance(x, (list, tuple)):
        if not all(isinstance(v, np.ndarray) or
                   K.is_tensor(v) for v in x):
            raise ValueError('Please provide as model inputs '
                             'either a single '
                             'array or a list of arrays. '
                             'You passed: x=' + str(x))
        all_inputs += list(x)
    elif isinstance(x, dict):
        raise ValueError('Please do not pass a dictionary '
                         'as model inputs.')
    else:
        if not isinstance(x, np.ndarray) and not K.is_tensor(x):
            raise ValueError('Please provide as model inputs '
                             'either a single '
                             'array or a list of arrays. '
                             'You passed: x=' + str(x))
        all_inputs.append(x)

他们isinstance()用来检查类型,而您的 HDF5 类型在任何地方都没有涵盖。

可能的黑客攻击

我将您的 GitHub 问题链接为对您帖子的评论。然而...

您可以在本地版本的 Keras 中更改上面的代码以涵盖您的情况,基本上将接收到的输入转换为 NumPy 数组,然后该数组将通过然后检查并被使用。

我可能会在elif上述条件下输入一秒钟,如下所示:

elif isinstance(x, dict):
    raise ValueError('Please do not pass a dictionary '
                     'as model inputs.')                   # original code

#### add this snippet #############    
elif isinstance(x, h5py._hl.dataset.Dataset):
    x = np.array(x)      # you might need to find a more elegant way of converting the HDF5 block to a numpy array
###################################

else:
    if not isinstance(x, np.ndarray) and not K.is_tensor(x):   # original code

您可以h5py._hl.dataset.Dataset通过检查type(keras.utils.io_utils.HDF5Matrix('dataset.h5', 'x_train')).

这应该可以让事情正常进行,尽管它可能会让您失去 HDF5 加载系统的其他一些好处,例如指定startend索引。

测试

只是一个示例,说明上述转换应该如何真正以您的数据作为 numpy 数组馈送到模型而告终:

import numpy as np
import keras

a = np.arange(0, 75).reshape((5, 5, 3))    # like a 5x5 RGB image
f = h5py.File('tester.h5', 'w') 
f.create_dataset(name='a', data=a)                                     
  # output:  <HDF5 dataset "a": shape (5, 5), type "<i8">
f.close()

# Later on ...

data = h5py.File('trial.h5', 'r')
data = np.array(data['a'])

np.array_equal(data, a)
  # True

鉴于HDF5 实用程序的文档:

keras.utils.HDF5Matrix(datapath, dataset, start=0, end=None, normalizer=None) 要使用的 HDF5 数据集的表示,而不是 Numpy 数组。

感觉确实存在错误,或者至少文档和代码之间存在差异。

编辑

您可以通过自定义生成器进行安装,该生成器将从您的 HDF5Matrix 加载块。

def generate_arrays_from_file(path):
    while True:
        with h5py.File(path) as f:

            for batch in f:
                # read the data and reshape as necessary
                trainX, trainY, testX, testY = split_batch(batch)
                yield (trainX, trainY)

model.fit_generator(generate_arrays_from_file('dataset.h5'),
                    steps_per_epoch=100, epochs=10)

您显然必须自己编写一个与您完全匹配的 h5 格式的生成器函数。也许看看 h5 文件的精美索引选项。

可能是Keras 中的一个错误。但是,如果“validation_split”参数设置为 0.001,如相应的 Github 页面上所述,您可能会有一些运气。