首页 文章

在训练阶段,损失和准确性不会改变

提问于
浏览
0

我 Build 了一个模型来着色灰度图像,在训练阶段我向网络提供100个森林的RGB图像,然后我将图像转换为LAB颜色空间,将训练集分割为L和AB,基于训练在AB数据中,模型将在测试阶段预测这两个通道用于灰度输入图像 . 现在我有一个问题,我用不同的架构训练模型,有10个图像,损失减少到0.0035并且效果很好,为此,我想增加数据集的大小以获得更好的结果,但是作为交换,损失和准确性保持不变,模型输出是一团糟,我的代码如下,我希望任何人都可以指导我做错了什么,是因为优化器?损失功能?批量大小?或者我不知道的任何其他事情,提前谢谢你 .

# Import images
MODEL_NAME = 'forest'

X = []
Y = []
for filename in os.listdir('forest/'):
    if (filename != '.DS_Store'):
        image = img_to_array(load_img("/Users/moos/Desktop/Project-Master/forest/" + filename))
        image = np.array(image, dtype=float)
        imL = rgb2lab(1.0 / 255 * image)[:, :,0]
        X.append(imL)
        imAB = rgb2lab(1.0 / 255 * image)[:, :,1:]
        imAB = imAB/128
        Y.append(imAB)

X = np.array(X)
Y = np.array(Y)

X = X.reshape(1, 256 , np.size(X)/256, 1)
Y = Y.reshape(1, 256, np.size(Y)/256/2, 2)

# Building the neural network
model = Sequential()
model.add(InputLayer(input_shape=(256, np.size(X)/256, 1)))
model.add(Conv2D(8, (3, 3), activation='relu', padding='same', strides=2))
model.add(Conv2D(32, (3, 3), activation='relu', padding='same'))
model.add(Conv2D(32, (3, 3), activation='relu', padding='same', strides=2))
model.add(Conv2D(64, (3, 3), activation='relu', padding='same', strides=1))
model.add(Conv2D(64, (3, 3), activation='relu', padding='same', strides=2))
model.add(Conv2D(128, (3, 3), activation='relu', padding='same', strides=1))
model.add(Conv2D(128, (3, 3), activation='relu', padding='same', strides=1))
model.add(Conv2D(64, (3, 3), activation='relu', padding='same', strides=1))
model.add(Conv2D(32, (3, 3), activation='relu', padding='same', strides=1))
model.add(UpSampling2D((2, 2)))
model.add(Conv2D(8, (3, 3), activation='relu', padding='same'))
model.add(Conv2D(8, (3, 3), activation='relu', padding='same'))
model.add(UpSampling2D((2, 2)))
model.add(Conv2D(2, (3, 3), activation='relu', padding='same'))
model.add(Conv2D(2, (3, 3), activation='tanh', padding='same'))
model.add(UpSampling2D((2, 2)))

# Finish model
model.compile(optimizer='rmsprop',loss='mse', metrics=['acc'])

#Train the neural network
model.fit(x=X, y=Y, batch_size=100, epochs=1000)
print(model.evaluate(X, Y, batch_size=100))

输出

Epoch 1/1000 1/1 [==============================] - 7s 7s /步 - 损失:0.0214 - acc :0.4987 Epoch 2/1000 1/1 [==============================] - 7s 7s /步 - 损失:0.0214 - acc:0.4987 Epoch 3/1000 1/1 [==============================] - 9s 9s / step - loss :0.0214 - acc:0.4987 Epoch 4/1000 1/1 [==============================] - 8s 8s /步 - 损失:0.0214 - acc:0.4987 . . . .

1 回答

  • 2

    首先,我简化了图像加载代码,并且还分别对所有通道(L,A,B)进行了归一化(减去平均值,除以标准偏差),也重命名了变量,这通常有很大帮助 . (5 minute free Coursera video about normalizing inputs (will bug you to subscribe but just click that away.).)所以加载部分现在看起来像这样:

    # Import images
    MODEL_NAME = 'forest'
    
    imgLABs = []
    for filename in os.listdir('./forest/'):
        if (filename != '.DS_Store'):
            image = img_to_array( load_img("./forest/" + filename) )
            imgLABs.append( rgb2lab( image / 255.0 ) )
    
    imgLABs_arr = np.array( imgLABs )
    
    L, A, B = imgLABs_arr[ :, :, :, 0 : 1 ], imgLABs_arr[ :, :, :, 1 : 2 ], imgLABs_arr[ :, :, :, 2 : 3 ]
    
    L_mean, L_std = np.mean( L ), np.std( L )
    A_mean, A_std = np.mean( A ), np.std( A )
    B_mean, B_std = np.mean( B ), np.std( B )
    L, A, B = ( L - L_mean ) / L_std, ( A - A_mean ) / A_std, ( B - B_mean ) / B_std
    AB = np.concatenate( ( A, B ), axis = 3)
    

    还改变了模型,增加了更多的特征深度,以及一些最大池层(不要忘记将它们包含在导入中,未显示) . 请注意,最后几层的激活函数设置为 None 以允许负值,因为我们期望标准化结果:

    # Building the neural network
    model = Sequential()
    model.add(InputLayer( input_shape = L.shape[ 1: ] ) )
    model.add(Conv2D(64, (3, 3), activation='relu', padding='same', strides=2,
                     kernel_initializer='truncated_normal'))
    model.add(MaxPooling2D( (3, 3), strides = 1, padding='same' ) )
    model.add(Conv2D(64, (3, 3), activation='relu', padding='same',
                     kernel_initializer='truncated_normal'))
    model.add(Conv2D(64, (3, 3), activation='relu', padding='same', strides=2,
                     kernel_initializer='truncated_normal'))
    model.add(Conv2D(64, (3, 3), activation='relu', padding='same', strides=1,
                     kernel_initializer='truncated_normal'))
    model.add(Conv2D(64, (3, 3), activation='relu', padding='same', strides=2,
                     kernel_initializer='truncated_normal'))
    model.add(MaxPooling2D( (3, 3), strides = 1, padding='same' ) )
    model.add(Conv2D(64, (3, 3), activation='relu', padding='same', strides=1,
                     kernel_initializer='truncated_normal'))
    model.add(Conv2D(64, (3, 3), activation='relu', padding='same', strides=1,
                     kernel_initializer='truncated_normal'))
    model.add(Conv2D(64, (3, 3), activation='relu', padding='same', strides=1,
                     kernel_initializer='truncated_normal'))
    model.add(Conv2D(64, (3, 3), activation='relu', padding='same', strides=1,
                     kernel_initializer='truncated_normal'))
    model.add(UpSampling2D((2, 2)))
    model.add(Conv2D(32, (3, 3), activation='relu', padding='same',
                     kernel_initializer='truncated_normal'))
    model.add(Conv2D(32, (3, 3), activation='relu', padding='same',
                     kernel_initializer='truncated_normal'))
    model.add(UpSampling2D((2, 2)))
    model.add(Conv2D(32, (3, 3), activation=None, padding='same',
                     kernel_initializer='truncated_normal'))
    model.add(Conv2D(2, (3, 3), activation=None, padding='same',
                     kernel_initializer='truncated_normal'))
    model.add(UpSampling2D((2, 2)))
    
    # Finish model
    optimizer = optimizers.RMSprop( lr = 0.0005, decay = 1e-5 )
    model.compile( optimizer=optimizer, loss='mse', metrics=['acc'] )
    
    #Train the neural network
    model.fit( x=L, y=AB, batch_size=1, epochs=1800 )
    model.save("forest-model-v2.h5")
    

    请注意学习率为0.0005,我将批处理_大小更改为1 - 这是 very specific to this network ,通常不建议使用 . 但是在这里你大多数都是直接卷积,所以在每个样本之后更新内核是有意义的,因为每个样本本身都会影响每个像素的权重 . 但是,如果您更改架构,那么这可能不再有意义,您应该更改批量大小 . 我也将时期增加到1,800,因为它在我的机器上运行得相当快,我有时间运行它 . 它达到了最大值1000左右 .

    尽管如此,这里是训练的输出(仅限第一行和最后几行):

    大纪元1/1800 100/100 [==============================] - 6s 63ms /步 - 损失:1.0554 - acc:0.5217 Epoch 2/1800 100/100 [==============================] - 1s 13ms /步 - 损失: 1.1097 - acc:0.5703 ... Epoch 1000/1800 100/100 [==============================] - 1s 13ms /步骤 - 损失:0.0533 - acc:0.9338 ... Epoch 1800/1800 100/100 [============================= =] - 1s 13ms /步 - 损失:0.0404 - acc:0.9422

    要打印重新着色的图像,我使用下面的代码,请注意5只是我从100中选取的图像的任意索引;我们还需要为L,A和B添加平均值和标准偏差(当你想将它们用于实际重新着色时,你必须将这六个数字视为网络的一部分 - 你需要用L_std预处理输入, L_mean,然后使用A,B表示和std-s对输出进行后处理:

    predicted = model.predict( x = L[ 5 : 6 ], batch_size = 1, verbose = 1 )
    plt.imshow( lab2rgb( np.concatenate(
        ( ( L[ 5 ] * L_std ) + L_mean,
         ( predicted[ 0, :, :, 0 : 1 ] * A_std ) + A_mean,
         ( predicted[ 0, :, :, 1 : 2 ] * B_std ) + B_mean),
        axis = 2 ) ) )
    
    img_pred = lab2rgb( np.concatenate(
        ( ( L[ 5 ] * L_std ) + L_mean,
         ( predicted[ 0, :, :, 0 : 1 ] * A_std ) + A_mean,
         ( predicted[ 0, :, :, 1 : 2 ] * B_std ) + B_mean),
        axis = 2 ) ) 
    img_orig = lab2rgb( np.concatenate(
        ( ( L[ 5 ] * L_std ) + L_mean,
          ( A[ 5 ] * A_std ) + A_mean,
          ( B[ 5 ] * B_std ) + B_mean ),
        axis = 2 ) ) 
    diff = img_orig - img_pred
    plt.imshow( diff * 10 )
    

    并且所有图像都是(原始;灰度网络输入;网络输出(颜色恢复);原始和恢复之间的差异):

    original rgb image

    greyscale negative image, the input to the network

    enter image description here

    enter image description here

    很简约! :)主要是山上的一些细节只是丢失了 . 由于它只有100张训练图像,因此可能会严重过度装配 . 不过,我希望这会给你一个良好的开端!

相关问题