338. APTOS 2019 Blindness Detection | aptos2019-blindness-detection
首先,我要感谢所有参与、分享内核并积极参与讨论的人。
正如大家已经听说和读到的,许多顶尖团队的解决方案都使用了一种非常简单的“两步法”,实际上这在 这里 被广泛讨论过,我也在我的内核 这里 中部分提到过:
步骤 1: 在 2015 年数据上预训练
步骤 2: 在 2019 年数据上微调
这种方法不错。但当我亲自开始实验时,我非常担心我们的本地 CV(交叉验证)分数约为 0.931,而 LB(排行榜)分数为 0.811。这是一个巨大的差距,我们担心会发生排名剧烈波动。此外,仅在旧数据上预训练并使用 2019 年数据作为验证集,结果 LB 分数仅为 0.75。这表明我们的模型泛化能力不佳。
我们的想法非常简单,与其分两个不同的阶段进行训练,我们将直接合并 2019 年和 2015 年的所有数据,并以此为基础努力提高我们的泛化能力。
问题 1:
去除黑色背景。
关于图像预处理,我使用了这个很棒的内核 https://www.kaggle.com/ratthachat/aptos-updatedv14-preprocessing-ben-s-cropping 中的脚本和信息。感谢 @ratthachat
该脚本基本上去除了所有的黑色背景。
def resize_to(img, targ_sz:int, use_min:bool=False):
h,w = img.shape[:2]
min_sz = (min if use_min else max)(w,h)
ratio = targ_sz/min_sz
return int(w*ratio),int(h*ratio)
def crop_image_from_gray(img,tol=7):
if img.ndim ==2:
mask = img>tol
return img[np.ix_(mask.any(1),mask.any(0))]
elif img.ndim==3:
gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
mask = gray_img>tol
check_shape = img[:,:,0][np.ix_(mask.any(1),mask.any(0))].shape[0]
if (check_shape == 0): # 图像太暗,导致我们把所有内容都裁剪掉了,
return img # 返回原始图像
else:
img1=img[:,:,0][np.ix_(mask.any(1),mask.any(0))]
img2=img[:,:,1][np.ix_(mask.any(1),mask.any(0))]
img3=img[:,:,2][np.ix_(mask.any(1),mask.any(0))]
img = np.stack([img1,img2,img3],axis=-1)
return img
def load_ben_color(path, size):
image = cv2.imread(str(path))
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image = crop_image_from_gray(image)
target_size = resize_to(image, size, use_min=True)
image = cv2.resize(image, target_size)
return PIL.Image.fromarray(image)
我唯一修改的是添加了 resize_to 函数以保留原始宽高比,使图像看起来更自然。(我的函数名为 load_ben_color,这与 ben 处理无关,我只是太懒了没改名字)。
问题 2:
去除混淆标签和重复项。
由于我们将 2015 年和 2019 年的数据合并到一个数据集中,去除所有重复项和混淆标签以防止任何泄漏非常重要。我们使用了这个很棒的内核来完成这项工作。感谢 @h4211819
问题 3。
解决缩放问题。
在预处理所有图像以去除黑色背景后,我们观察到(论坛上也广泛讨论过)2019 年的数据看起来像是放大到了中心(下面是一个例子)。