Запуск 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