【问题标题】:Tensorflow/Keras model output is constantTensorflow/Keras 模型输出是恒定的
【发布时间】:2020-07-16 21:51:05
【问题描述】:

我正在尝试训练 CNN 使用 keras。输入是 128x128x3 的 rbg 图像,输出是 0 到 1 之间的单个值(这不是分类器模型)。我已经标准化了输入。最初,我的模型取得了一些合理的结果,平均绝对误差小于 0.1。当我尝试稍微调整模型时,我发现损失会很快稳定在 0.23 左右。我进一步调查发现它为每个输入输出相同的值

所以我将我的代码恢复到它工作的时候,但它不再工作了。我最终发现大约 90% 的时间它会卡在这个局部最小值,输出一个恒定值(我怀疑这是训练参考值的平均值(0.39)。另外 10% 的时间它会表现得很好并且回归到

我试过了:

  • 更改输入大小
  • 将学习率提高/降低 10 倍
  • 删除几个密集层
  • 将“relu”更改为“泄漏的 relu”
  • 增加/消除辍学
def load_data(dir):
    csv_data = get_csv_data()
    xs = []
    ys = []
    for (name, y) in csv_data:
        path = DIR + dir + "/" + name
        img = tf.keras.preprocessing.image.load_img(path)
        xs.append(tf.keras.preprocessing.image.img_to_array(img) * (1 / 255.0))
        ys.append(normalize_output(float(y)))
    return np.array(xs).reshape(len(csv_data), IMAGE_DIM, IMAGE_DIM, 3), np.array(ys).reshape(len(csv_data), 1)

def gen_model():
    model = tf.keras.Sequential()
    model.add(tf.keras.layers.Conv2D(filters=64, kernel_size = (5, 5), activation='relu', input_shape=(IMAGE_DIM, IMAGE_DIM, CHAN_COUNT)))
    model.add(tf.keras.layers.MaxPool2D())
    model.add(tf.keras.layers.Conv2D(filters=64, kernel_size = (5, 5), activation='relu'))
    model.add(tf.keras.layers.MaxPool2D())
    model.add(tf.keras.layers.Conv2D(filters=128, kernel_size = (5, 5), activation='relu'))
    model.add(tf.keras.layers.MaxPool2D())
    model.add(tf.keras.layers.Flatten())
    model.add(tf.keras.layers.Dense(256, activation='relu'))
    model.add(tf.keras.layers.Dropout(0.1))
    model.add(tf.keras.layers.Dense(128, activation='relu'))
    model.add(tf.keras.layers.Dropout(0.1))
    model.add(tf.keras.layers.Dense(64, activation='relu'))
    model.add(tf.keras.layers.Dropout(0.1))
    model.add(tf.keras.layers.LeakyReLU())
    model.add(tf.keras.layers.Dense(16, activation='sigmoid'))
    model.add(tf.keras.layers.LeakyReLU())
    model.add(tf.keras.layers.Dense(1, activation='sigmoid'))
    model.compile(loss=keras.losses.MeanSquaredError(),
                  optimizer=tf.keras.optimizers.Adam(),
                  metrics=[keras.metrics.MeanAbsoluteError()])
    return model

def run():
    model = gen_model()

    xs, ys = load_data("output")
   
    generator = tf.keras.preprocessing.image.ImageDataGenerator(featurewise_center=False,
                                                                samplewise_center=False,
                                                                featurewise_std_normalization=False,
                                                                samplewise_std_normalization=False,
                                                                validation_split=0.1,
                                                                rotation_range=12,
                                                                horizontal_flip=True,
                                                                vertical_flip=True)

    model.fit(generator.flow(xs, ys, batch_size=32, shuffle=True),
              steps_per_epoch=len(xs) / 32,
              epochs = 10,
              use_multiprocessing=False)

【问题讨论】:

  • 嗨!您可以尝试使用 BatchNormalization 吗?并且您的 16 大小的 Dense 层具有 sigmoid 激活,然后是 LeakyReLU 激活!如果你想对这些层使用 LeakyReLU,你应该考虑删除activation='sigmoid'。在 Dense(64) 之后您也有相同的配置。对于 0 到 1 之间的值,只有最后一层必须是 activation='sigmoid'。

标签: python tensorflow machine-learning keras conv-neural-network


【解决方案1】:

我重新安排了层上的激活。请试一试:

def gen_model():
   model = tf.keras.Sequential()
   model.add(tf.keras.layers.Conv2D(filters=64, kernel_size = (5, 5), activation='relu', input_shape=(IMAGE_DIM, IMAGE_DIM, CHAN_COUNT)))
   model.add(tf.keras.layers.MaxPool2D())
   model.add(tf.keras.layers.Conv2D(filters=64, kernel_size = (5, 5), activation='relu'))
   model.add(tf.keras.layers.MaxPool2D())
   model.add(tf.keras.layers.Conv2D(filters=128, kernel_size = (5, 5), activation='relu'))
   model.add(tf.keras.layers.MaxPool2D())
   model.add(tf.keras.layers.Flatten())
   model.add(tf.keras.layers.Dense(256, activation='relu'))
   model.add(tf.keras.layers.Dropout(0.1))
   model.add(tf.keras.layers.Dense(128, activation='relu'))
   model.add(tf.keras.layers.Dropout(0.1))
   model.add(tf.keras.layers.Dense(64, activation='relu'))
   model.add(tf.keras.layers.Dropout(0.1))
   model.add(tf.keras.layers.Dense(16, activation='relu'))
   model.add(tf.keras.layers.Dense(1, activation='sigmoid'))
   model.compile(loss=keras.losses.MeanSquaredError(),
              optimizer=tf.keras.optimizers.Adam(),
              metrics=[keras.metrics.MeanAbsoluteError()])
   return model

【讨论】:

  • 谢谢!将 sigmoid 更改为 relu 似乎可以解决问题。我应该在哪些层应用批量标准化?
  • 在 Conv2D 层之后使用 model.add(BatchNormalization())。如果您投票,我将不胜感激!
猜你喜欢
  • 2021-12-26
  • 1970-01-01
  • 2021-12-04
  • 1970-01-01
  • 2022-12-24
  • 2017-06-02
  • 1970-01-01
  • 2020-03-20
  • 2017-02-23
相关资源
最近更新 更多