使用keras类和字符串编译训练tensorflow 模型的不同结果

7fhtutme  于 2022-11-16  发布在  其他
关注(0)|答案(1)|浏览(142)

你好,我正在尝试训练一个tensorflow卷积模型的一小部分kaggle狗对猫的数据集。
我以下列方式建立模型:

from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.utils import image_dataset_from_directory
import pathlib

new_base_dir = pathlib.Path("../8/cats_vs_dogs_small")
data_augmentation = keras.Sequential(
    [
        layers.RandomFlip("horizontal"),
        layers.RandomRotation(0.1),
        layers.RandomZoom(0.2),
    ]
)

inputs = keras.Input(shape=(180, 180, 3))
x = data_augmentation(inputs)
x = layers.Rescaling(1./255)(x)
x = layers.Conv2D(filters=32, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=64, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=128, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=256, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=256, kernel_size=3, activation="relu")(x)
x = layers.Flatten()(x)
x = layers.Dropout(0.5)(x)
outputs = layers.Dense(1, activation="sigmoid")(x)
model = keras.Model(inputs=inputs, outputs=outputs)

train_dataset = image_dataset_from_directory(
    new_base_dir/"train",
    image_size=(180,180),
    batch_size=32
)

validation_dataset = image_dataset_from_directory(
    new_base_dir/"validation",
    image_size=(180,180),
    batch_size=32
)

test_dataset = image_dataset_from_directory(
    new_base_dir/"test",
    image_size=(180,180),
    batch_size=32
)

我试着用两种方法编译,我希望是一样的:

model.compile(optimizer=keras.optimizers.RMSprop(),
              loss=keras.losses.BinaryCrossentropy(),
             metrics=[keras.metrics.Accuracy()])

model.compile(loss="binary_crossentropy",
              optimizer="rmsprop",
              metrics=["accuracy"])

然后用

history = model.fit(
    train_dataset,
    validation_data=validation_dataset,
    epochs=5)

然而,我在两个编译中得到了不同的结果:在第一个例子中,模型似乎根本没有训练(见第一张图);而在第二个例子中,模型正在学习(见第二张图)。
这两个版本有什么不同吗?为什么?

获取数据集若要获取数据集并使用较小的版本(如果您有kaggle帐户),您可以执行以下操作

!kaggle competitions download -c dogs-vs-cats
!unzip -qq train.zip

(if从终端而不是从Jupyter笔记本删除!),要获得较小版本的数据集,可以使用以下脚本

import os, shutil, pathlib

original_dir = pathlib.Path("./train")
new_base_dir = pathlib.Path("cats_vs_dogs_small")

def make_subset(subset_name, start_index, end_index):
    for category in ("cat", "dog"):
        dir = new_base_dir / subset_name / category
        os.makedirs(dir)
        fnames = [f"{category}.{i}.jpg" for i in range(start_index, end_index)]
        for fname in fnames:
            shutil.copyfile(src=original_dir / fname,
                            dst=dir / fname)

make_subset("train", start_index=0, end_index=1000)
make_subset("validation", start_index=1000, end_index=1500)
make_subset("test", start_index=1500, end_index=2500)

示例取自here

erhoui1w

erhoui1w1#

这是因为字符串“accuracy”被转换为tf.keras.metrics.BinaryAccuracy()(它将浮点数自动转换为0-1,阈值为0.5)。在第一种情况下,您使用的是tf.keras.metrics.Accuracy(),它要求精确匹配,而您的模型只输出浮点数概率,而不是0-1。
参见官方文档:
当您传递字符串'accuracy'或'acc'时,我们根据所使用的损失函数和模型输出形状将其转换为tf.keras.metrics.BinaryAccuracy、tf. keras.metrics.CategoricalAccuracy、tf.keras.metrics.SparseCategoricalAccuracy中的一个。

相关问题