【问题标题】:Fitting Keras model with Tensorflow datasets用 Tensorflow 数据集拟合 Keras 模型
【发布时间】:2021-08-12 13:41:00
【问题描述】:

我正在阅读Aurélien Géron's book,在第 13 章中,我正在尝试使用 Tensorflow 数据集(而不是 Numpy 数组)来训练 Keras 模型。

1。数据集

数据集来自sklearn.datasets.fetch_california_housing,我已将其导出为 CSV。前几行如下所示:

MedInc,HouseAge,AveRooms,AveBedrms,Population,AveOccup,Latitude,Longitude,MedHouseVal
3.3083,20.0,5.387832699619772,1.0,853.0,3.2433460076045626,37.53,-120.79,1.083
2.1932,29.0,5.164444444444444,1.1288888888888888,726.0,3.2266666666666666,37.53,-120.8,0.906
1.875,15.0,5.327102803738318,1.1495327102803738,189.0,1.766355140186916,37.53,-120.81,1.813

如您所见,有 8 个功能和 1 个目标(MedHouseVal,在最后一列)。

我使用以下代码重新导入它:

def parse_csv_line(line: bytes) -> Tuple[tf.Tensor, tf.Tensor]:
    parsed = tf.io.decode_csv(line, record_defaults=[0.]*9)
    return parsed[:-1], parsed[-1:]

def load_dataset_csv(paths: Union[str, List[str]]) -> tf.Dataset:
    return tf.data.Dataset.list_files(paths)                        \
        .interleave(lambda p: tf.data.TextLineDataset(p).skip(1))   \
        .map(parse_csv_line)                                        \
        .prefetch(1)

train_set = load_dataset_csv("./housing.train.csv")
val_set = load_dataset_csv("./housing.val.csv")
test_set = load_dataset_csv("./housing.test.csv")

到目前为止一切顺利:

>>> list(test_set.take(1))
[(<tf.Tensor: shape=(8,), dtype=float32, numpy=
  array([   3.3083   ,   20.       ,    5.3878326,    1.       ,
          853.       ,    3.243346 ,   37.53     , -120.79     ],
        dtype=float32)>,
  <tf.Tensor: shape=(1,), dtype=float32, numpy=array([1.083], dtype=float32)>)]

2。模型,先试试

然后我定义我的模型:

model = keras.models.Sequential(
    [
        keras.layers.Dense(30, input_shape=(8,)),
        keras.layers.BatchNormalization(),
        keras.layers.Dense(1),
    ],
)
model.compile(loss="mean_squared_error")

model.fit(
    train_set,
    epochs=1,  # debugging
    validation_data=val_set,
)

但我收到以下错误:

ValueError: Input 0 of layer sequential_63 is incompatible with the layer: expected axis -1 of input shape to have value 8 but received input with shape (8, 1)

3。模型,第二次尝试

如果我将输入形状设置为 (8, 1) 而不是 (8,),则会收到此警告

WARNING:tensorflow:Model was constructed with shape (None, 8, 1) for input KerasTensor(type_spec=TensorSpec(shape=(None, 8, 1), dtype=tf.float32, name='input_15'), name='input_15', description="created by layer 'input_15'"), but it was called on an input with incompatible shape (8, 1, 1).

当我尝试进行预测时,我得到了这个奇怪的结果:

>>> model.predict(test_set.take(1))

WARNING:tensorflow:Model was constructed with shape (None, 8, 1) for input KerasTensor(type_spec=TensorSpec(shape=(None, 8, 1), dtype=tf.float32, name='dense_159_input'), name='dense_159_input', description="created by layer 'dense_159_input'"), but it was called on an input with incompatible shape (8, 1, 1).
WARNING:tensorflow:6 out of the last 174 calls to <function Model.make_predict_function.<locals>.predict_function at 0x169f02b80> triggered tf.function retracing. Tracing is expensive and the excessive number of tracings could be due to (1) creating @tf.function repeatedly in a loop, (2) passing tensors with different shapes, (3) passing Python objects instead of tensors. For (1), please define your @tf.function outside of the loop. For (2), @tf.function has experimental_relax_shapes=True option that relaxes argument shapes that can avoid unnecessary retracing. For (3), please refer to https://www.tensorflow.org/guide/function#controlling_retracing and https://www.tensorflow.org/api_docs/python/tf/function for  more details.
array([[[2.592609 ]],
       [[2.591457 ]],
       [[2.5924652]],
       [[2.592768 ]],
       [[2.533997 ]],
       [[2.5926137]],
       [[2.590248 ]],
       [[2.601169 ]]], dtype=float32)

我知道 Tensorflow 对张量的形状不满意,但为什么它给了我 8 个预测?

4。模型,第三次尝试

此时我不确定该怎么做,所以我尝试添加一个Flatten 层:

model = keras.models.Sequential(
    [
        keras.layers.Flatten(),
        keras.layers.Dense(30, input_shape=(8,)),
        keras.layers.BatchNormalization(),
        keras.layers.Dense(1),
    ],
)

这次我没有收到警告或错误,但是当我尝试进行预测时,我仍然得到 8 个结果:

>>> model.predict(test_set.take(1))

array([[2.5953178],
       [2.5949838],
       [2.5952766],
       [2.5953639],
       [2.5783124],
       [2.5953195],
       [2.594633 ],
       [2.5978017]], dtype=float32)

我真的不明白我做错了什么。尝试使用 Numpy 数组训练第一个模型(输入形状为 (8,) 而没有 Flatten)效果很好。

任何帮助将不胜感激。

提前致谢!

【问题讨论】:

  • 您可以尝试对数据集进行批处理。对 Keras 模型使用 dataset.batch( batch_size )。见here
  • 感谢您的回答!这似乎解决了问题。
  • 我在下面提供了详细的答案。

标签: python numpy tensorflow machine-learning keras


【解决方案1】:

正如tf.keras.Sequentialofficial docs 所建议的那样,当inputstf.data.Dataset 的实例时,不需要提供batch_size,同时调用tf.keras.Sequential.fit()

整数或无。每次梯度更新的样本数。如果 未指定,batch_size 将默认为 32。不要指定 batch_size 如果您的数据是数据集、生成器或 keras.utils.Sequence 实例(因为它们生成批次)。

对于tf.data.Datasetfit() 方法需要一个批处理数据集。

要批处理tf.data.Dataset,请使用batch() 方法,

batched_ds = ds.batch( batch_size )

因此,数据集现在将提供批量数据(形状为 ( batch_size , 8 ))而不是整个数据,即形状为 ( num_samples , 8 )

提示:

要取消批处理数据集,即将数据重新整形为 ( num_samples , 8 ,请使用提供的 unbatch() 方法。

【讨论】:

    猜你喜欢
    • 2017-07-08
    • 1970-01-01
    • 2019-10-04
    • 1970-01-01
    • 2020-05-12
    • 1970-01-01
    • 2018-12-08
    • 1970-01-01
    • 2019-09-17
    相关资源
    最近更新 更多