model.evaluate () сильно зависит от количества шагов при использовании генераторов - PullRequest
1 голос
/ 25 марта 2020

Запуск tenorflow 2.x в Colab с его внутренней версией keras (tf.keras). Моя модель - 3D сверточная UNET для мультиклассовой сегментации (не уверена, уместна ли она). Я успешно обучил (достаточно высокую точность проверки) эту модель традиционным способом, но я хотел бы сделать дополнения, чтобы улучшить ее, поэтому я переключаюсь на (рукописные) генераторы. Когда я использую генераторы, я вижу, что мои потери увеличиваются, а моя точность уменьшается много (например, потери увеличиваются в 4 раза, а не на несколько%) в подгонке.

Чтобы попытаться локализовать проблему Я попытался загрузить свои обученные веса и вычислить метрики на данных, возвращаемых генераторами. И то, что происходит, не имеет смысла. Я вижу, что результаты визуально в порядке.

model.evaluate(validationGenerator,steps=1)
2s 2s/step - loss: 0.4037 - categorical_accuracy: 0.8716

model.evaluate(validationGenerator,steps=2)
2s/step - loss: 1.7825 - categorical_accuracy: 0.7158

model.evaluate(validationGenerator,steps=4)
7s 2s/step - loss: 1.7478 - categorical_accuracy: 0.7038

Почему потеря будет зависеть от количества шагов? Я мог бы предположить, что некоторые% из-за статистических отклонений ... не 4-кратное увеличение!

Если я попытаюсь

x,y = next(validationGenerator)
nSamples = x.shape[0]
meanLoss = np.zeros(nSamples)
meanAcc = np.zeros(nSamples)
for pIdx in range(nSamples):
  y_pred = model.predict(np.expand_dims(x[pIdx,:,:,:,:],axis=0))
  meanAcc[pIdx]=np.mean(tf.keras.metrics.categorical_accuracy(np.expand_dims(y[pIdx,:,:,:,:],axis=0),y_pred))
  meanLoss[pIdx]=np.mean(tf.keras.metrics.categorical_crossentropy(np.expand_dims(y[pIdx,:,:,:,:],axis=0),y_pred))
print(np.mean(meanAcc))
print(np.mean(meanLoss))

, я получу точность ~ 85% и потери ~ 0,44. Это то, что я ожидаю от предыдущей посадки, и она мало меняется от одной партии к другой. И это те же самые точные числа, которые я получаю, если я выполняю model.evaluate () за 1 шаг (используя ту же функцию генератора).
Однако мне нужно около 30 шагов, чтобы выполнить весь набор обучающих данных. Что мне делать? Если я подгоню свою и без того хорошую модель к этому генератору, это действительно значительно ухудшит характеристики (от хорошей сегментации изображения до единообразных прогнозов 25% для каждого из 4 классов !!!!)

Есть идеи, где можно решить проблему? Я также визуально посмотрел на изображения, полученные генератором, и на предсказания модели, и все выглядит правильно (о чем свидетельствуют цифры, которые я нашел при оценке с использованием одного шага). Я попытался написать минимальный рабочий пример с двухслойной моделью, но ... в этом проблема не возникает.

ОБНОВЛЕНИЕ: Код генератора Итак, как меня просили это код генераторов. Они написаны от руки

def dataGen (X,Y_train):
    patchS = 64 #set the size of the patch I extract
    batchS = 16 #number of samples per batch
    nSamples = X.shape[0] #get total number of samples
    immSize = X.shape[1:] #get the shape of the iamge to crop
    #Get 4 patches from each image
    #extract them randomly, and in random patient order
    patList = np.array(range(0,nSamples),dtype='int16')
    patList = patList.reshape(nSamples,1)
    patList = np.tile(patList,(4,2))
    patList[:nSamples,0]=0 #Use this index to tell the code where to get the patch from
    patList[nSamples:2*nSamples,0]=1
    patList[2*nSamples:3*nSamples,0]=2
    patList[3*nSamples:4*nSamples,0]=3
    np.random.shuffle(patList)
    patStart=0
    Xout = np.zeros((batchS,patchS,patchS,patchS,immSize[3])) #allocate output vector   
    while True:
     Yout = np.zeros((batchS,patchS,patchS,patchS)) #allocate vector of labels
     for patIdx in range(batchS): 
       XSR = 32* (patList[patStart+patIdx,0]//2) #get the index of where to extract the patch
       YSR = 32* (patList[patStart+patIdx,0]%2)
       xStart = random.randrange(XSR,XSR+32) #get a patch randomly somewhere between a range
       yStart = random.randrange(YSR,YSR+32) 
       zStart = random.randrange(0,26)  
       patInd = patList[patStart+patIdx,1]
       Xout[patIdx,:,:,:,:] = X[patInd,xStart:(xStart+patchS),yStart:(yStart+patchS),zStart:(zStart+patchS),:]
       Yout[patIdx,:,:,:] = Y_train[patInd,xStart:(xStart+patchS),yStart:(yStart+patchS),zStart:(zStart+patchS)]
       if((patStart+patIdx)>(patList.shape[0]-2)):
         np.random.shuffle(patList) #after going through the whole list restart
         patStart=0
     patStart = patStart+batchS 
     Yout = tf.keras.utils.to_categorical (Yout, num_classes=4, dtype='float32') #convert to one hot encoding
     yield Xout, Yout

Ответы [ 2 ]

1 голос
/ 27 марта 2020

Отправка обходного пути Я нашел для будущего человека, пришедшего сюда из Google.

Видимо проблема заключается в том, как keras вызывает рукописный генератор. Когда он вызывался несколько раз подряд с помощью метода define (gen, steps = N), по-видимому, он возвращал неверные результаты. Нет документации о том, как решить эту проблему или как должен быть написан генератор.

В итоге я написал свой код, используя класс tf.keras.utils.sequence, и тот же предыдущий код теперь работает отлично. Нет способа узнать почему.

0 голосов
/ 27 марта 2020

Вот различные факторы, которые влияют на потери и точность:

Для точности мы знаем, что она измеряет точность прогноза: то есть правильные классы / общие классы. В то время как убыток отслеживает обратную достоверность прогноза. Высокие потери указывают на то, что, хотя модель хорошо справляется с прогнозом, становится неопределенным прогноз, который она делает.

Например, для сценария классификации изображений изображение кота передается на две части. моделей. Модель A прогнозирует {кошка: 0,8, собака: 0,2} , а модель B прогнозирует {кошка: 0,6, собака: 0,4} . Обе модели будут иметь одинаковую точность, но модель B будет иметь большую потерю .

По вашей оценочной части На основании документации

Steps: Integer or None. Total number of steps (batches of samples) before declaring the evaluation round finished. Ignored with the default value of None. If x is a tf.data dataset and steps is None, 'evaluate' will run until the dataset is exhausted. This argument is not supported by array inputs.

Так что для упрощения он получает N-ю партию ваших проверочных образцов.

Возможно, что прогноз модели становится неопределенным , так как большинство неизвестных данных приходится на эти указанные c шаги. что в вашем случае, шаги 2 и 3. Таким образом, по мере продвижения шагов оценки, прогноз становится более неопределенным, что приводит к более высоким потерям .

. Возможно, вам придется переучить вашу модель с большим количеством обучающие образцы, но, конечно, вы должны быть осторожны, поскольку вы можете столкнуться с переобучением.

С точки зрения увеличения данных, вы можете проверить эту ссылку
В Обучающей перспективе, правильные данные увеличение является одним из факторов, который приводит к хорошей производительности модели.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...