简体   繁体   English

将 Keras model 与 Tensorflow 数据集拟合

[英]Fitting Keras model with Tensorflow datasets

I'm reading Aurélien Géron's book , and on chapter 13, I'm trying to use Tensorflow datasets (rather than Numpy arrays) to train Keras models.我正在阅读Aurélien Géron 的书,在第 13 章,我正在尝试使用 Tensorflow 数据集(而不是 Numpy 数组)来训练 Z7FEE7BB66F4294C3E32783EFAFCZ9 模型。

1. The dataset 1. 数据集

The dataset comes from sklearn.datasets.fetch_california_housing , which I've exported to CSV.数据集来自sklearn.datasets.fetch_california_housing ,我已将其导出到 CSV。 The first few lines look like this:前几行如下所示:

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

As you can see there's 8 features and 1 target ( MedHouseVal , on the last column).如您所见,有 8 个功能和 1 个目标( MedHouseVal ,在最后一列)。

I reimport it using the following code:我使用以下代码重新导入它:

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")

So far so good:到目前为止,一切都很好:

>>> 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, first try 2. Model,先试试

Then I define my model:然后我定义我的 model:

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,
)

but I get the following error:但我收到以下错误:

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. Model, second try 3. Model,第二次尝试

If I set the input shape to (8, 1) instead of (8,) , then I get this warning如果我将输入形状设置为(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).

When I try to make a prediction, I get this weird result:当我试图做出预测时,我得到了这个奇怪的结果:

>>> 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)

I understand that Tensorflow is displeased with the shape of the tensors, still, why is it giving me 8 predictions?我知道 Tensorflow 对张量的形状不满意,但为什么它给了我 8 个预测?

4. Model, third try 4. Model,第三次尝试

At this point I'm not really sure what to do, so I tried adding a Flatten layer:在这一点上,我不太确定该怎么做,所以我尝试添加一个Flatten层:

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

This time I get no warning or error, but when I try to make a prediction, I still get 8 results:这次我没有收到警告或错误,但是当我尝试进行预测时,我仍然得到 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)

I don't really understand what I'm doing wrong.我真的不明白我做错了什么。 Trying to train the first model (with input shape (8,) and no Flatten ) with Numpy arrays instead works just fine.尝试使用 Numpy arrays 训练第一个 model (输入形状(8,)且没有Flatten )效果很好。

Any help would be really appreciated.任何帮助将非常感激。

Thanks in advance!提前致谢!

Just as the official docs for tf.keras.Sequential suggest, no batch_size needs to be provided when inputs are instances of tf.data.Dataset while calling tf.keras.Sequential.fit() ,正如tf.keras.Sequential官方文档所建议的那样,当调用tf.keras.Sequential.fit()inputstf.data.Dataset的实例时,不需要提供batch_size

Integer or None. Integer 或无。 Number of samples per gradient update.每次梯度更新的样本数。 If unspecified, batch_size will default to 32. Do not specify the batch_size if your data is in the form of datasets, generators, or keras.utils.Sequence instances (since they generate batches).如果未指定,batch_size 将默认为 32。如果您的数据是数据集、生成器或 keras.utils.Sequence 实例(因为它们生成批次)的形式,请不要指定 batch_size。

In case of tf.data.Dataset , the fit() method expects a batched dataset.tf.data.Dataset的情况下, fit()方法需要一个批处理数据集。

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

batched_ds = ds.batch( batch_size )

Thus the dataset will now provide batches of data ( of shape ( batch_size, 8 ) ) instead of the entire data ie of shape ( num_samples, 8 ) .因此,数据集现在将提供批量数据(形状( batch_size, 8 ) )而不是整个数据,即形状( num_samples, 8 )

Tip:小费:

To unbatch a dataset ie to reshape the data to ( num_samples, 8 again, use the unbatch() method provided.要取消批处理数据集,即将数据重新整形为( num_samples, 8 ,请使用提供的unbatch()方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM