我正在尝试使用Keras训练一个CNN。输入是一个128x128x3的RGB图像,输出是一个介于0到1之间的单一值(这不是一个分类模型)。我已经对输入进行了归一化处理。最初,我的模型取得了一些合理的结果,将平均绝对误差降低到< 0.1。当我尝试稍作调整时,我发现损失很快就会稳定在0.23左右。我进一步调查,发现它对每个输入都输出相同的值。
因此,我将代码恢复到之前工作的状态,但它不再工作了。我最终发现,大约90%的时间它会卡在一个局部最小值上,输出一个恒定值(我怀疑这是训练参考值的平均值(0.39))。其余10%的时间,它会表现良好,并将误差回归到< 0.1。所以它基本上是随机地给出质的不同行为,并且很少能得到期望的结果。奇怪的是,我发誓它之前一直是正常工作的。
我尝试过以下方法:
- 改变输入大小
- 将学习率增加/减少10倍
- 移除几个全连接层
- 将’relu’改为’leaky 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 modeldef 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)
回答:
我重新排列了层的激活函数。请尝试一下:
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