我正在使用Keras 2.1.1中的卷积神经网络进行3D图像分割,并将张量流作为后端 . 我正在使用fit_generator函数,因为3D图像非常耗费内存,我在每次更新之前都应用了大量的数据扩充 .

Edit :我还在github上引用了这篇文章,并添加了一个演示有问题行为的小演示:https://github.com/keras-team/keras/issues/8837

import sys
import numpy as np
import h5py
import random
import tensorflow as tf
import random
import scipy.misc as misc
import datetime
import time
import cv2


from keras.callbacks import EarlyStopping
from keras.callbacks import ModelCheckpoint
from keras.optimizers import Adam


print("Loading net")

ada = Adam(lr=0.00005, beta_1=0.1, beta_2=0.001, epsilon=1e-08, decay=0.0)
net = Net(input_shape=(128,160,144, 4),outputChannel=5,momentum=0.5)
net.compile(optimizer="Adam",loss=jaccard_distance_loss)
print("Finished loading net")

filename = 'fold0_1.hdf5'
f = h5py.File(filename, 'r')

train_gen = generateData(f[u'train_x'],f[u'train_y'],augmentor=random_geometric_transformation)
val_gen = generateData(f[u'valid_x'],f[u'valid_y'])

filepath="Model-{epoch:02d}.h5"
checkpoint = ModelCheckpoint(filepath, monitor='val_loss', verbose=1, save_best_only=True, mode='min')
callbacks_list = [checkpoint]

#Train Model
net.fit_generator(generator = train_gen,
                  steps_per_epoch = 200,
                  validation_data=val_gen,
                  validation_steps = 37,
                  epochs = 800,
                  callbacks=callbacks_list)

问题是虽然在训练期间报告的误差相对较低,但是在预测训练或测试图像时的误差与最低训练状态相当(第一个值是总损失,其他值是相应的损失,注意,在未经训练的模型中,第一类的损失接近于0,因为它只是预测背景):

#Loss before training
[3.9978203773498535, 0.032198667526245117, 0.99983119964599609, 0.99984711408615112, 0.99907118082046509, 0.96687209606170654]

在非常短暂地训练任何给定(训练/测试)样本的网络之后,评估错误将与训练期间报告的错误相匹配:

Epoch 1/5
1/1 [==============================] - 9s 9s/step - loss: 2.0542 - slice_layer_1_loss: 0.0048 - slice_layer_2_loss: 0.9998 - slice_layer_3_loss: 0.3026 - slice_layer_4_loss: 0.6302 - slice_layer_5_loss: 0.1167
Epoch 2/5
1/1 [==============================] - 1s 592ms/step - loss: 2.0278 - slice_layer_1_loss: 0.0045 - slice_layer_2_loss: 0.9998 - slice_layer_3_loss: 0.2916 - slice_layer_4_loss: 0.6191 - slice_layer_5_loss: 0.1128
Epoch 3/5
1/1 [==============================] - 1s 582ms/step - loss: 2.0066 - slice_layer_1_loss: 0.0043 - slice_layer_2_loss: 0.9998 - slice_layer_3_loss: 0.2888 - slice_layer_4_loss: 0.6066 - slice_layer_5_loss: 0.1071
Epoch 4/5
1/1 [==============================] - 1s 590ms/step - loss: 1.9909 - slice_layer_1_loss: 0.0042 - slice_layer_2_loss: 0.9998 - slice_layer_3_loss: 0.2872 - slice_layer_4_loss: 0.5959 - slice_layer_5_loss: 0.1038
Epoch 5/5
1/1 [==============================] - 1s 572ms/step - loss: 1.9787 - slice_layer_1_loss: 0.0041 - slice_layer_2_loss: 0.9998 - slice_layer_3_loss: 0.2855 - slice_layer_4_loss: 0.5875 - slice_layer_5_loss: 0.1019

#Loss after training
1/1 [==============================] - 0s 190ms/step
[2.1015677452087402, 0.0048453211784362793, 0.99983119964599609, 0.33013522624969482, 0.64043641090393066, 0.1263195276260376]

问题似乎与这篇文章非常相似:ResNet: 100% accuracy during training, but 33% prediction accuracy with the same data

但是,本演示中使用的模型已经在整个数据集上训练了200个时期,并且更多的时期不能解决问题 . 此外,在训练期间报告的验证集上的错误没有任何减少,但是对测试图像的预测显示出与上述相同的行为 .

当批量大小只有1时,使用fit_generator进行批量标准化时是否存在某种问题?

PS:这里是发电机的代码

import numpy as np
import random

def reverseArgMax(array,n):
    newArray = np.empty(list(array.shape+(n,)))

    for i in range(n):
        temp = array.copy()

        if i==1:
            temp[temp!=1] = 0
        elif i==0:
            temp[temp==1] = 2
            temp[temp==i] = 1
            temp[temp!=1] = 0
        else:
            temp[temp==1] = 0
            temp[temp==i] = 1
            temp[temp!=1] = 0
        newArray[...,i]=temp
    return newArray

def generateData(data,labels,augmentor=None,batch_size=1):
    #Generates batches of samples

    while 1:
        # Generate batches
        imax = list(range(len(data)))
        np.random.shuffle(imax)

        for i in imax:
            x = np.array(data[i])
            y = np.array((labels[i]))
            x = np.transpose(x,axes=[0,2,3,1])
            x = np.array([x])
            y = np.array([y])
            x = x.astype(np.float32)
            y = y.astype(np.float32)
            y=reverseArgMax(y,5)

            #Augment
            if augmentor!=None:
                x,y = augmentor(x,y)

            x = x.astype(np.float32)
            y = y.astype(np.float32)
            y = np.transpose(y,[4,0,1,2,3])
            y = np.reshape(y,[5,1,-1])

            yield x, list(y)