Keras CNN 模型中的零损失和验证损失
Zero loss and validation loss in Keras CNN model
我正在尝试 运行 人群估计模型,该模型根据图像中有多少人将图像分为三个不同的大类。 1200 张图像用于训练,其中 20% 用于验证。我使用 sentdex's tutorial on Youtube 作为参考将图像数据加载到模型中;我将图像加载为 zip 文件,将其解压缩并根据它们所在的文件夹对它们进行分类。
我的问题是,每当我尝试训练模型时,我注意到损失和验证损失始终为 0,这导致模型无法完全训练并且验证精度始终保持不变,如所见 here。我怎样才能让损失真正改变?在实施方面我做错了什么吗?
到目前为止,我尝试过的是:
- 我尝试添加第三个卷积层,但收效甚微。
- 我也尝试将最后一个 Dense 层更改为 model.add(Dense(3)),但我收到一条错误消息“Shapes (None, 1) and (None, 3) 不兼容
- 我尝试使用较低的学习率(0.001?),但模型最终返回 0 以验证准确性
- 更改优化器对我来说似乎没有产生任何变化
下面是我目前的代码片段,展示了我的模型尝试:
import keras.backend as K
logdir = "logs/scalars/" + datetime.now().strftime("%Y%m%d-%H%M%S")
tensorboard_callback = keras.callbacks.TensorBoard(log_dir=logdir)
X = X/255.0
model = Sequential()
model.add(Conv2D(64, (3,3), input_shape = X.shape[1:])) #[1:] to skip the -1
model.add(Activation("relu"))
model.add(Conv2D(64, (3,3), input_shape = X.shape[1:])) #[1:] to skip the -1
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(128, (3,3)))
model.add(Activation('relu'))
model.add(Conv2D(128, (3,3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(128))
model.add(Activation('relu'))
#fully connected layer
model.add(Dense(1))
model.add(Activation('softmax'))
opt = keras.optimizers.Adam(lr=0.01)
model.compile(loss='categorical_crossentropy',
optimizer = opt,
metrics=['accuracy'])
model.fit(x_train, y_train, batch_size = 100, epochs = 30, validation_data = (x_val, y_val), callbacks=[tensorboard_callback], shuffle=True)
完整代码可以在 Colab here.
上找到
你的最后一层包含一个节点,所以你只输出一个数字。但是,你需要输出 3 个数字,因为你有 3 个 classes。这些输出中的每一个都对应于该特定 class 的非标准化概率。在softmax之后,你得到归一化的概率分布。
你有 3 个 class。因此更改代码
model.add(Dense(1))
至
model.addDense(3))
现在,如果您使用模型对图像进行预测,model.predict 将生成包含 3 个概率值的列表。这些概率的总和将为 1.0。模型的实际预测是列表中具有最高概率值的索引。
例如,如果 model.predict 的输出是 [.1, .7。 .2] 概率值为 .7 的索引 1 是预测值 class。您的 classes 被索引为 0、1、2,因此模型预测 class 1。您可以获得模型输出的预测 class。预测
class_index=np.argmax(model,predict(....))
某处你可能有一个 class 的列表,比如
classes=['less_than 5', 'between 5 and 10', 'more than 10']
所以实际预测的class名字是
predicted_class=classes[class_index]
我正在尝试 运行 人群估计模型,该模型根据图像中有多少人将图像分为三个不同的大类。 1200 张图像用于训练,其中 20% 用于验证。我使用 sentdex's tutorial on Youtube 作为参考将图像数据加载到模型中;我将图像加载为 zip 文件,将其解压缩并根据它们所在的文件夹对它们进行分类。
我的问题是,每当我尝试训练模型时,我注意到损失和验证损失始终为 0,这导致模型无法完全训练并且验证精度始终保持不变,如所见 here。我怎样才能让损失真正改变?在实施方面我做错了什么吗?
到目前为止,我尝试过的是:
- 我尝试添加第三个卷积层,但收效甚微。
- 我也尝试将最后一个 Dense 层更改为 model.add(Dense(3)),但我收到一条错误消息“Shapes (None, 1) and (None, 3) 不兼容
- 我尝试使用较低的学习率(0.001?),但模型最终返回 0 以验证准确性
- 更改优化器对我来说似乎没有产生任何变化
下面是我目前的代码片段,展示了我的模型尝试:
import keras.backend as K
logdir = "logs/scalars/" + datetime.now().strftime("%Y%m%d-%H%M%S")
tensorboard_callback = keras.callbacks.TensorBoard(log_dir=logdir)
X = X/255.0
model = Sequential()
model.add(Conv2D(64, (3,3), input_shape = X.shape[1:])) #[1:] to skip the -1
model.add(Activation("relu"))
model.add(Conv2D(64, (3,3), input_shape = X.shape[1:])) #[1:] to skip the -1
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(128, (3,3)))
model.add(Activation('relu'))
model.add(Conv2D(128, (3,3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(128))
model.add(Activation('relu'))
#fully connected layer
model.add(Dense(1))
model.add(Activation('softmax'))
opt = keras.optimizers.Adam(lr=0.01)
model.compile(loss='categorical_crossentropy',
optimizer = opt,
metrics=['accuracy'])
model.fit(x_train, y_train, batch_size = 100, epochs = 30, validation_data = (x_val, y_val), callbacks=[tensorboard_callback], shuffle=True)
完整代码可以在 Colab here.
上找到你的最后一层包含一个节点,所以你只输出一个数字。但是,你需要输出 3 个数字,因为你有 3 个 classes。这些输出中的每一个都对应于该特定 class 的非标准化概率。在softmax之后,你得到归一化的概率分布。
你有 3 个 class。因此更改代码
model.add(Dense(1))
至
model.addDense(3))
现在,如果您使用模型对图像进行预测,model.predict 将生成包含 3 个概率值的列表。这些概率的总和将为 1.0。模型的实际预测是列表中具有最高概率值的索引。 例如,如果 model.predict 的输出是 [.1, .7。 .2] 概率值为 .7 的索引 1 是预测值 class。您的 classes 被索引为 0、1、2,因此模型预测 class 1。您可以获得模型输出的预测 class。预测
class_index=np.argmax(model,predict(....))
某处你可能有一个 class 的列表,比如
classes=['less_than 5', 'between 5 and 10', 'more than 10']
所以实际预测的class名字是
predicted_class=classes[class_index]