在将图片转成npy格式的时候,想查看矩阵是否有问题,刚开始时没有乘以255,用cv2.imwrite保存图片,打开后发现全部都是黑的,在查阅资料后发现自己当初对图片进行了归一化处理,也就是除以了255,导致图片的像素值都在0~1之间,所以保存图片时显示全黑。因此在保存时乘以255恢复到原来的像素值就可以了
print (imgs_mask_train[0][0])
min, max, minLoc, maxLoc = cv2.minMaxLoc(imgs_mask_train[0][0])
print(imgs_mask_train[0][0].shape)
print("min: %.2f, max: %.2f"% (min, max))
print("min loc: ", minLoc)
print("max loc: ", maxLoc)
out = imgs_mask_train[0][0] * 255
cv2.imwrite('imgs_mask_train.jpg',out)
原因:损失函数使用的binary_crossentropy。这种loss函数将正样本和负样本均拿来计算loss值。
由于医学图像格式比较特殊。医学图像分割的例子中,正样本(目标、器官等)非常的少,仅仅占图像面积中极少的一部分,但是负样本(背景或者无关区域)面积非常大,因此刚开始训练的时候,负样本就已经使得loss变得非常小了,准确率非常高了。
解决方案方案是:选用Dice loss函数;这种loss(直观理解)约束的是正样本的准确率。
# unet模型损失函数
def dice_coef(y_true, y_pred):
y_true_f = K.flatten(y_true)
y_pred_f = K.flatten(y_pred)
intersection = K.sum(y_true_f * y_pred_f)
return (2. * intersection + 100) / (K.sum(y_true_f) + K.sum(y_pred_f) + 100)
# unet模型损失函数
def dice_coef_np(y_true, y_pred):
y_true_f = y_true.flatten()
y_pred_f = y_pred.flatten()
intersection = numpy.sum(y_true_f * y_pred_f)
return (2. * intersection + 100) / (numpy.sum(y_true_f) + numpy.sum(y_pred_f) + 100)
# unet模型损失函数
def dice_coef_loss(y_true, y_pred):
return -dice_coef(y_true, y_pred)
再在函数里定义loss函数处修改:
model.compile(optimizer=Adam(lr=1e-4), loss=dice_loss, metrics = ['accuracy',sensitivity,ppv,dice_coef])
如果在Keras内部多次使用同一个Model,例如在不同的数据集上训练同一个模型进而得到结果,会存在内存泄露的问题。在运行几次循环之后,就会报错OOM。
在调试程序的时候碰到这个问题,显卡内存不够,分析原因主要有两个个:
1, batch_size太大,内存不够。
2,显卡内存被别的程序占用没有退出,可以在后台查看占用线程并终止。
3.如果还不行再试试在jupyter的running里面把有些没用的文件关掉
4.或者在每个代码后面接clear_session()函数,显示的关闭TFGraph,再重启。
( 不知道为啥我先试的这种结果没用,猜测是位置没放对,待学习)
import tensorflow as tf
from keras import backend as K
K.clear_session()
tf.reset_default_graph()
为了方便后期的作图,需要把训练过程记录下来
首先配置好神经网络以后,进行训练
history=model.fit(imgs_train, imgs_mask_train, batch_size=2, nb_epoch=20, verbose=1,validation_split=0.2, shuffle=True, callbacks=c_backs)
保存训练记录:
import pickle
with open('trainHistoryDict.txt', 'wb') as file_pi:
pickle.dump(history.history, file_pi)
读取训练记录:
with open('trainHistoryDict.txt','rb') as file_pi:
history=pickle.load(file_pi)