飞桨常规赛:PALM眼底彩照中黄斑中央凹定位-11月第1名方案

本文分享飞桨常规赛PALM眼底彩照黄斑中央凹定位11月第1名方案。介绍赛事与数据后,详述自定义数据集读取、新数据增强方法,给出具体实现代码,包括数据处理、模型组网、训练评估等,还提及结果投票集成,最后总结改善方向与飞桨使用建议。

☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

飞桨常规赛:palm眼底彩照中黄斑中央凹定位-11月第1名方案 - 创想鸟

飞桨常规赛:PALM眼底彩照中黄斑中央凹定位-11月第1名方案

(1)比赛介绍

赛题介绍

榜首个人主页,戳此处查看

PALM黄斑定位常规赛的重点是研究和发展与患者眼底照片黄斑结构定位相关的算法。该常规赛的目标是评估和比较在一个常见的视网膜眼底图像数据集上定位黄斑的自动算法。具体目的是预测黄斑中央凹在图像中的坐标值。

飞桨常规赛:PALM眼底彩照中黄斑中央凹定位-11月第1名方案 - 创想鸟        

中央凹是视网膜中辨色力、分辨力最敏锐的区域。以人为例,在视盘颞侧约3.5mm处,有一黄色小区,称黄斑,其中央的凹陷,就是中央凹。中央凹的准确定位可辅助医生完成糖尿病视网膜、黄斑变性等病变的诊断。

赛程赛制

(1)飞桨常规赛面向全社会公开报名,直至赛题下线;

(2)飞桨常规赛不设初赛、复赛,以当月每位参赛选手提交的最优成绩排名。每月竞赛周期为本月 1 日至本月最后 1 日;

(3)比赛期间选手每天最多可提交 5 次作品(预测结果+原始代码),系统自动选取最高成绩作为榜单记录;

(4)每个月 1-5 日公布上一个月总榜。当月排名前10 且通过代码复查的选手可获得由百度飞桨颁发的荣誉证书。对于初次上榜的参赛选手,还可额外获得1份特别礼包(1个飞桨周边奖品+ 100小时GPU算力卡)。工作人员将以邮件形式通知上一月排名前10的选手提交材料供代码复查,请各位参赛选手留意邮箱通知。特别提醒: 已获得过特别礼包的参赛选手,如果基于本赛题撰写新的studio项目并被评为精选,才可再次获得1份特别礼包;

(5) score超过0.04的第一位选手可额外获得大奖:小度在家;

(6) 鼓励选手报名多个主题的飞桨常规赛,以赛促学,全方面提升开发者的深度学习能力。

(2)数据介绍

PALM病理性近视预测常规赛由中山大学中山眼科中心提供800张带黄斑中央凹坐标标注的眼底彩照供选手训练模型,另提供400张带标注数据供平台进行模型测试。

数据说明

本次常规赛提供的金标准由中山大学中山眼科中心的7名眼科医生手工进行标注,之后由另一位高级专家将它们融合为最终的标注结果。本比赛提供数据集对应的黄斑中央凹坐标信息存储在xlsx文件中,名为“Fovea_Location_train”,第一列对应眼底图像的文件名(包括扩展名“.jpg”),第二列包含x坐标,第三列包含y坐标。 图

训练数据集

文件名称:Train Train文件夹里有一个文件夹fundus_images和一个xlsx文件。

fundus_images文件夹内包含800张眼底彩照,分辨率为1444×1444,或2124×2056。命名形如H0001.jpg、P0001.jpg、N0001.jpg和V0001.jpg。 xlsx文件中包含800张眼底彩照对应的x、y坐标信息。

测试数据集

文件名称:PALM-Testing400-Images 文件夹里包含400张眼底彩照,命名形如T0001.jpg。

(3)个人思路+个人方案亮点

自定义数据集读取图片和标签

class dataset(paddle.io.Dataset):    def __init__(self,img_list,label_listx,label_listy,transform=None,transform2=None,mode='train'):        self.image=img_list        self.labelx=label_listx        self.labely=label_listy        self.mode=mode        self.transform=transform        self.transform2=transform2    def load_img(self, image_path):        img=cv2.imread(image_path,1)        img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)        h,w,c=img.shape        return img,h,w    def __getitem__(self,index):        img,h,w = self.load_img(self.image[index])        labelx = self.labelx[index]        labely = self.labely[index]        img_size=img.shape        if self.transform:            if self.mode=='train':                img, label = self.transform([img, [labelx,labely]])            else:                img, label = self.transform2([img, [labelx,labely]])                        label=np.array(label,dtype='float32')        img=np.array(img,dtype='float32')/255.0        return img,label    def __len__(self):        return len(self.image)

       

使用新的数据增强方法对数据进行增广

class py1(object):    # 将输入图像调整为指定大小    def __init__(self, output_size):        assert isinstance(output_size, (int, tuple))        self.output_size = output_size    def __call__(self, data):        image = data[0]    # 获取图片        key_pts = data[1]  # 获取标签        image_copy = np.copy(image)              key_pts_copy = np.copy(key_pts)        h, w = image_copy.shape[:2]        if key_pts_copy[0]<self.output_size:            left=np.random.random()*key_pts_copy[0]        elif w-key_pts_copy[0]<self.output_size:            left=w-(w-key_pts_copy[0])*np.random.random()-self.output_size        else:            left=key_pts_copy[0]-self.output_size*np.random.random()                                            if key_pts_copy[1]<self.output_size:            top=np.random.random()*key_pts_copy[1]        elif h-key_pts_copy[1]<self.output_size:            top=w-(h-key_pts_copy[1])*np.random.random()-self.output_size        else:            top=key_pts_copy[1]-self.output_size*np.random.random()         left=int(left)        top=int(top)        x=(key_pts_copy[0]-left)/self.output_size        y=(key_pts_copy[1]-top)/self.output_size        img=image_copy[top:top+self.output_size,left:left+self.output_size]        return img, [x,y]class py2(object):    # 将输入图像调整为指定大小    def __init__(self, output_size):        assert isinstance(output_size, (int, tuple))        self.output_size = output_size    def __call__(self, data):        image = data[0]    # 获取图片        key_pts = data[1]  # 获取标签        image_copy = np.copy(image)              key_pts_copy = np.copy(key_pts)        h, w = image_copy.shape[:2]        if key_pts_copy[0]<self.output_size/2:            left=0        elif w-key_pts_copy[0]<self.output_size/2:            left=w-self.output_size        else:            left=key_pts_copy[0]-self.output_size/2                                     if key_pts_copy[1]<self.output_size/2:            top=0        elif h-key_pts_copy[1]<self.output_size/2:            top=w-self.output_size        else:            top=key_pts_copy[1]-self.output_size/2        left=int(left)        top=int(top)        x=(key_pts_copy[0]-left)/self.output_size        y=(key_pts_copy[1]-top)/self.output_size        img=image_copy[top:top+self.output_size,left:left+self.output_size]        return img, [x,y]class GrayNormalize(object):    # 将图片变为灰度图,并将其值放缩到[0, 1]    # 将 label 放缩到 [-1, 1] 之间    def __call__(self, data):        image = data[0]   # 获取图片        key_pts = data[1] # 获取标签                image_copy = np.copy(image)        key_pts_copy = np.copy(key_pts)        # 灰度化图片        gray_scale = paddle.vision.transforms.Grayscale(num_output_channels=3)        image_copy = gray_scale(image_copy)                ## 将图片值放缩到 [0, 1]        #image_copy = (image_copy-127.5) /127.5                # 将坐标点放缩到 [-1, 1]        #mean = data_mean # 获取标签均值        #std = data_std   # 获取标签标准差        #key_pts_copy = (key_pts_copy - mean)/std        return image_copy, key_pts_copyclass ToCHW(object):    # 将图像的格式由HWC改为CHW    def __call__(self, data):        image = data[0]        key_pts = data[1]        transpose = T.Transpose((2, 0, 1)) # 改为CHW        image = transpose(image)                return image, key_pts

   

(4)具体方案分享

代码参考:『深度学习7日打卡营』人脸关键点检测

解压数据集

In [1]

!unzip -oq /home/aistudio/data/data116960/常规赛:PALM眼底彩照中黄斑中央凹定位.zip!mv │г╣ц╚№г║PALM╤█╡╫▓╩╒╒╓╨╗╞░▀╓╨╤ы░╝╢и╬╗ 常规赛:PALM眼底彩照中黄斑中央凹定位 #不知道为什么会出现乱码,可用此代码恢复中文!rm -rf __MACOSX

   

查看数据标签

In [1]

import blackhole.dataframe as pddf=pd.read_excel('常规赛:PALM眼底彩照中黄斑中央凹定位/Train/Fovea_Location_train.xlsx')df.head()

       


               

     imgName  Fovea_X  Fovea_Y0  H0001.jpg   743.96   790.541  H0002.jpg  1394.82   725.542  H0003.jpg  1361.74   870.723  H0004.jpg   703.15   742.444  H0005.jpg  1070.95  1037.54

               

数据增强

In [2]

import paddle.vision.transforms.functional as Fclass py1(object):    # 将输入图像调整为指定大小    def __init__(self, output_size):        assert isinstance(output_size, (int, tuple))        self.output_size = output_size    def __call__(self, data):        image = data[0]    # 获取图片        key_pts = data[1]  # 获取标签        image_copy = np.copy(image)              key_pts_copy = np.copy(key_pts)        h, w = image_copy.shape[:2]        if key_pts_copy[0]<self.output_size:            left=np.random.random()*key_pts_copy[0]        elif w-key_pts_copy[0]<self.output_size:            left=w-(w-key_pts_copy[0])*np.random.random()-self.output_size        else:            left=key_pts_copy[0]-self.output_size*np.random.random()                                            if key_pts_copy[1]<self.output_size:            top=np.random.random()*key_pts_copy[1]        elif h-key_pts_copy[1]<self.output_size:            top=w-(h-key_pts_copy[1])*np.random.random()-self.output_size        else:            top=key_pts_copy[1]-self.output_size*np.random.random()         left=int(left)        top=int(top)        x=(key_pts_copy[0]-left)/self.output_size        y=(key_pts_copy[1]-top)/self.output_size        img=image_copy[top:top+self.output_size,left:left+self.output_size]        return img, [x,y]class py2(object):    # 将输入图像调整为指定大小    def __init__(self, output_size):        assert isinstance(output_size, (int, tuple))        self.output_size = output_size    def __call__(self, data):        image = data[0]    # 获取图片        key_pts = data[1]  # 获取标签        image_copy = np.copy(image)              key_pts_copy = np.copy(key_pts)        h, w = image_copy.shape[:2]        if key_pts_copy[0]<self.output_size/2:            left=0        elif w-key_pts_copy[0]<self.output_size/2:            left=w-self.output_size        else:            left=key_pts_copy[0]-self.output_size/2                                     if key_pts_copy[1]<self.output_size/2:            top=0        elif h-key_pts_copy[1]<self.output_size/2:            top=w-self.output_size        else:            top=key_pts_copy[1]-self.output_size/2        left=int(left)        top=int(top)        x=(key_pts_copy[0]-left)/self.output_size        y=(key_pts_copy[1]-top)/self.output_size        img=image_copy[top:top+self.output_size,left:left+self.output_size]        return img, [x,y]class GrayNormalize(object):    # 将图片变为灰度图,并将其值放缩到[0, 1]    # 将 label 放缩到 [-1, 1] 之间    def __call__(self, data):        image = data[0]   # 获取图片        key_pts = data[1] # 获取标签                image_copy = np.copy(image)        key_pts_copy = np.copy(key_pts)        # 灰度化图片        gray_scale = paddle.vision.transforms.Grayscale(num_output_channels=3)        image_copy = gray_scale(image_copy)                ## 将图片值放缩到 [0, 1]        #image_copy = (image_copy-127.5) /127.5                # 将坐标点放缩到 [-1, 1]        #mean = data_mean # 获取标签均值        #std = data_std   # 获取标签标准差        #key_pts_copy = (key_pts_copy - mean)/std        return image_copy, key_pts_copyclass ToCHW(object):    # 将图像的格式由HWC改为CHW    def __call__(self, data):        image = data[0]        key_pts = data[1]        transpose = T.Transpose((2, 0, 1)) # 改为CHW        image = transpose(image)                return image, key_pts

   In [3]

import paddle.vision.transforms as Tdata_transform = T.Compose([                        py1(224),                                                GrayNormalize(),                        ToCHW(),                         ])data_transform2 = T.Compose([                        py2(224),                        GrayNormalize(),                        ToCHW(),                        ])

   

自定义数据集

In [4]

path='常规赛:PALM眼底彩照中黄斑中央凹定位/Train/fundus_image/'df=df.sample(frac=1)image_list=[]label_listx=[]label_listy=[]for i in range(len(df)):        image_list.append(path+df['imgName'][i])        label_listx.append(df['Fovea_X'][i])        label_listy.append(df['Fovea_Y'][i])

   In [5]

import ostest_path='常规赛:PALM眼底彩照中黄斑中央凹定位/PALM-Testing400-Images'test_list=[]test_labelx=[]test_labely=[]#list=pd.read_csv('result54.70313.csv')list=pd.read_csv('????.csv')   #????.csv为以前提交的结果文件,选一个成绩好的。#list = os.listdir(test_path)  # 列出文件夹下所有的目录与文件for i in range(0, len(list)):    path = os.path.join(test_path, list['FileName'][i])    test_list.append(path)    test_labelx.append(list['Fovea_X'][i])    test_labely.append(list['Fovea_Y'][i])

   In [6]

import paddleimport cv2import numpy as npclass dataset(paddle.io.Dataset):    def __init__(self,img_list,label_listx,label_listy,transform=None,transform2=None,mode='train'):        self.image=img_list        self.labelx=label_listx        self.labely=label_listy        self.mode=mode        self.transform=transform        self.transform2=transform2    def load_img(self, image_path):        img=cv2.imread(image_path,1)        img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)        h,w,c=img.shape        return img,h,w    def __getitem__(self,index):        img,h,w = self.load_img(self.image[index])        labelx = self.labelx[index]        labely = self.labely[index]        img_size=img.shape        if self.transform:            if self.mode=='train':                img, label = self.transform([img, [labelx,labely]])            else:                img, label = self.transform2([img, [labelx,labely]])                        label=np.array(label,dtype='float32')        img=np.array(img,dtype='float32')/255.0        return img,label    def __len__(self):        return len(self.image)

   

训练集、验证集、测试集

In [7]

radio=0.8train_list=image_list[:int(len(image_list)*radio)]train_labelx=label_listx[:int(len(label_listx)*radio)]train_labely=label_listy[:int(len(label_listy)*radio)]val_list=image_list[int(len(image_list)*radio):]val_labelx=label_listx[int(len(label_listx)*radio):]val_labely=label_listy[int(len(label_listy)*radio):]train_ds=dataset(train_list,train_labelx,train_labely,data_transform,data_transform2,'train')val_ds=dataset(val_list,val_labelx,val_labely,data_transform,data_transform2,'valid')test_ds=dataset(test_list,test_labelx,test_labely,data_transform,data_transform2,'test')

   

查看图片

In [14]

import matplotlib.pyplot as pltfor i,data in enumerate(train_ds):        img,label=data    img=img.transpose([1,2,0])    print(img.shape)    plt.title(label*224)    plt.imshow(img)    plt.show()    if i==0:        break

       

(224, 224, 3)

       

               

模型组网

以下两个网络结构任选一

In [15]

class MyNet1(paddle.nn.Layer):    def __init__(self,num_classes=2):        super(MyNet1,self).__init__()        self.net=paddle.vision.resnet152(pretrained=True)        self.fc1=paddle.nn.Linear(1000,512)        self.relu=paddle.nn.ReLU()        self.fc2=paddle.nn.Linear(512,num_classes)    def forward(self,inputs):        out=self.net(inputs)        out=self.fc1(out)        out=self.relu(out)        out=self.fc2(out)        return out

   In [17]

class MyNet2(paddle.nn.Layer):    def __init__(self):        super(MyNet2, self).__init__()        self.resnet = paddle.vision.resnet50(pretrained=True, num_classes=0) # remove final fc 输出为[?, 2048, 1, 1]        self.flatten = paddle.nn.Flatten()        self.linear_1 = paddle.nn.Linear(2048, 512)        self.linear_2 = paddle.nn.Linear(512, 256)        self.linear_3 = paddle.nn.Linear(256, 2)        self.relu = paddle.nn.ReLU()        self.dropout = paddle.nn.Dropout(0.2)        def forward(self, inputs):        y = self.resnet(inputs)        y = self.flatten(y)        y = self.linear_1(y)        y = self.linear_2(y)        y = self.relu(y)        y = self.dropout(y)        y = self.linear_3(y)        y = paddle.nn.functional.sigmoid(y)        return y

   

异步加载数据

In [18]

train_loader = paddle.io.DataLoader(train_ds, places=paddle.CPUPlace(), batch_size=32, shuffle=True, num_workers=0)val_loader = paddle.io.DataLoader(val_ds, places=paddle.CPUPlace(), batch_size=32, shuffle=False, num_workers=0)test_loader=paddle.io.DataLoader(test_ds, places=paddle.CPUPlace(), batch_size=32, shuffle=False, num_workers=0)

   

自定义损失函数

In [19]

from sklearn.metrics.pairwise import euclidean_distances import paddle.nn as nn# 损失函数def cal_coordinate_Loss(logit, label, alpha = 0.5):    """    logit: shape [batch, ndim]    label: shape [batch, ndim]    ndim = 2 represents coordinate_x and coordinaate_y    alpha: weight for MSELoss and 1-alpha for ED loss    return: combine MSELoss and ED Loss for x and y, shape [batch, 1]    """    alpha = alpha    mse_loss = nn.MSELoss(reduction='mean')    mse_x = mse_loss(logit[:,0],label[:,0])    mse_y = mse_loss(logit[:,1],label[:,1])    mse_l = 0.5*(mse_x + mse_y)    # print('mse_l', mse_l)    ed_loss = []    # print(logit.shape[0])    for i in range(logit.shape[0]):        logit_tmp = logit[i,:].numpy()        label_tmp = label[i,:].numpy()        # print('cal_coordinate_loss_ed', logit_tmp, label_tmp)                ed_tmp = euclidean_distances([logit_tmp], [label_tmp])        # print('ed_tmp:', ed_tmp[0][0])        ed_loss.append(ed_tmp)        ed_l = sum(ed_loss)/len(ed_loss)    # print('ed_l', ed_l)    # print('alpha', alpha)    loss = alpha * mse_l + (1-alpha) * ed_l    # print('loss in function', loss)    return loss

   In [20]

class SelfDefineLoss(paddle.nn.Layer):   """   1. 继承paddle.nn.Layer   """   def __init__(self):       """       2. 构造函数根据自己的实际算法需求和使用需求进行参数定义即可       """       super(SelfDefineLoss, self).__init__()   def forward(self, input, label):       """       3. 实现forward函数,forward在调用时会传递两个参数:input和label           - input:单个或批次训练数据经过模型前向计算输出结果           - label:单个或批次训练数据对应的标签数据           接口返回值是一个Tensor,根据自定义的逻辑加和或计算均值后的损失       """       # 使用PaddlePaddle中相关API自定义的计算逻辑       output = cal_coordinate_Loss(input,label)       return output

   

模型训练与可视化

如果图片尺寸较大应适当调小Batch_size,防止爆显存。

In [22]

from utils import NMEimport warningswarnings.filterwarnings('ignore')visualdl=paddle.callbacks.VisualDL(log_dir='visual_log')#定义输入Batch_size=32EPOCHS=20step_each_epoch = len(train_ds)//Batch_size# 使用 paddle.Model 封装模型model = paddle.Model(MyNet2())#模型加载#model.load('/home/aistudio/work/lup/final')lr = paddle.optimizer.lr.CosineAnnealingDecay(learning_rate=1e-5,                                                T_max=step_each_epoch * EPOCHS)# 定义Adam优化器optimizer = paddle.optimizer.Adam(learning_rate=lr,                                weight_decay=1e-5,                                parameters=model.parameters())# 定义SmoothL1Lossloss =paddle.nn.SmoothL1Loss()#loss =SelfDefineLoss()# 使用自定义metricsmetric = NME()model.prepare(optimizer=optimizer, loss=loss, metrics=metric)# 训练可视化VisualDL工具的回调函数# 启动模型全流程训练model.fit(train_loader,  # 训练数据集          val_loader,   # 评估数据集          epochs=EPOCHS,       # 训练的总轮次          batch_size=Batch_size,  # 训练使用的批大小          save_dir="/home/aistudio/work/lup", #把模型参数、优化器参数保存至自定义的文件夹          save_freq=1,                    #设定每隔多少个epoch保存模型参数及优化器参数          verbose=1 ,      # 日志展示形式          callbacks=[visualdl]          )  # 设置可视化

       

The loss value printed in the log is the current step, and the metric is the average value of previous steps.Epoch 1/20step 20/20 [==============================] - loss: 0.0604 - nme: 0.4010 - 4s/step           save checkpoint at /home/aistudio/work/lup/0Eval begin...step 5/5 [==============================] - loss: 0.0053 - nme: 0.1495 - 8s/stepEval samples: 160Epoch 2/20step 20/20 [==============================] - loss: 0.0361 - nme: 0.3705 - 2s/step           save checkpoint at /home/aistudio/work/lup/1Eval begin...step 5/5 [==============================] - loss: 0.0100 - nme: 0.1334 - 2s/stepEval samples: 160Epoch 3/20step 20/20 [==============================] - loss: 0.0350 - nme: 0.3663 - 2s/step           save checkpoint at /home/aistudio/work/lup/2Eval begin...step 5/5 [==============================] - loss: 0.0096 - nme: 0.1611 - 2s/stepEval samples: 160Epoch 4/20step 20/20 [==============================] - loss: 0.0353 - nme: 0.3423 - 2s/step           save checkpoint at /home/aistudio/work/lup/3Eval begin...step 5/5 [==============================] - loss: 0.0057 - nme: 0.1399 - 2s/stepEval samples: 160Epoch 5/20step 20/20 [==============================] - loss: 0.0325 - nme: 0.3279 - 2s/step           save checkpoint at /home/aistudio/work/lup/4Eval begin...step 5/5 [==============================] - loss: 0.0063 - nme: 0.1391 - 2s/stepEval samples: 160Epoch 6/20step 20/20 [==============================] - loss: 0.0288 - nme: 0.3110 - 2s/step           save checkpoint at /home/aistudio/work/lup/5Eval begin...step 5/5 [==============================] - loss: 0.0057 - nme: 0.1273 - 2s/stepEval samples: 160Epoch 7/20step 20/20 [==============================] - loss: 0.0219 - nme: 0.2979 - 2s/step           save checkpoint at /home/aistudio/work/lup/6Eval begin...step 5/5 [==============================] - loss: 0.0060 - nme: 0.1356 - 2s/stepEval samples: 160Epoch 8/20step 20/20 [==============================] - loss: 0.0339 - nme: 0.3089 - 2s/step           save checkpoint at /home/aistudio/work/lup/7Eval begin...step 5/5 [==============================] - loss: 0.0060 - nme: 0.1382 - 2s/stepEval samples: 160Epoch 9/20step 20/20 [==============================] - loss: 0.0246 - nme: 0.3041 - 2s/step           save checkpoint at /home/aistudio/work/lup/8Eval begin...step 5/5 [==============================] - loss: 0.0067 - nme: 0.1365 - 2s/stepEval samples: 160Epoch 10/20step 20/20 [==============================] - loss: 0.0315 - nme: 0.3006 - 2s/step           save checkpoint at /home/aistudio/work/lup/9Eval begin...step 5/5 [==============================] - loss: 0.0061 - nme: 0.1383 - 2s/stepEval samples: 160Epoch 11/20step 20/20 [==============================] - loss: 0.0254 - nme: 0.3009 - 2s/step           save checkpoint at /home/aistudio/work/lup/10Eval begin...step 5/5 [==============================] - loss: 0.0061 - nme: 0.1386 - 2s/stepEval samples: 160Epoch 12/20step 20/20 [==============================] - loss: 0.0273 - nme: 0.2984 - 2s/step           save checkpoint at /home/aistudio/work/lup/11Eval begin...step 5/5 [==============================] - loss: 0.0069 - nme: 0.1412 - 2s/stepEval samples: 160Epoch 13/20step 20/20 [==============================] - loss: 0.0365 - nme: 0.2950 - 2s/step           save checkpoint at /home/aistudio/work/lup/12Eval begin...step 20/20 [==============================] - loss: 0.0340 - nme: 0.2917 - 2s/step           save checkpoint at /home/aistudio/work/lup/13Eval begin...step 5/5 [==============================] - loss: 0.0066 - nme: 0.1376 - 2s/stepEval samples: 160Epoch 15/20step 20/20 [==============================] - loss: 0.0331 - nme: 0.2910 - 2s/step           save checkpoint at /home/aistudio/work/lup/14Eval begin...step 5/5 [==============================] - loss: 0.0070 - nme: 0.1403 - 2s/stepEval samples: 160Epoch 16/20step 20/20 [==============================] - loss: 0.0334 - nme: 0.2885 - 2s/step           save checkpoint at /home/aistudio/work/lup/15Eval begin...step 5/5 [==============================] - loss: 0.0066 - nme: 0.1383 - 2s/stepEval samples: 160Epoch 17/20step 20/20 [==============================] - loss: 0.0373 - nme: 0.2919 - 2s/step           save checkpoint at /home/aistudio/work/lup/16Eval begin...step 5/5 [==============================] - loss: 0.0069 - nme: 0.1401 - 2s/stepEval samples: 160Epoch 18/20step 20/20 [==============================] - loss: 0.0232 - nme: 0.2843 - 2s/step           save checkpoint at /home/aistudio/work/lup/17Eval begin...step 5/5 [==============================] - loss: 0.0064 - nme: 0.1348 - 2s/stepEval samples: 160Epoch 19/20step 20/20 [==============================] - loss: 0.0291 - nme: 0.2869 - 2s/step           save checkpoint at /home/aistudio/work/lup/18Eval begin...step 5/5 [==============================] - loss: 0.0068 - nme: 0.1389 - 2s/stepEval samples: 160Epoch 20/20step 20/20 [==============================] - loss: 0.0342 - nme: 0.2946 - 2s/step           save checkpoint at /home/aistudio/work/lup/19Eval begin...step 5/5 [==============================] - loss: 0.0062 - nme: 0.1368 - 2s/stepEval samples: 160save checkpoint at /home/aistudio/work/lup/final

       

模型评估

In [23]

# 模型评估model.load('/home/aistudio/work/lup/5')result = model.evaluate(val_loader, verbose=1)print(result)

       

Eval begin...step 5/5 [==============================] - loss: 0.0057 - nme: 0.1273 - 2s/stepEval samples: 160{'loss': [0.005723397], 'nme': 0.1273284799297331}

       

进行预测操作

In [24]

# 进行预测操作result = model.predict(test_loader)

       

Predict begin...step 13/13 [==============================] - 2s/step          Predict samples: 400

       In [26]

# 获取测试图片尺寸和图片名test_path='常规赛:PALM眼底彩照中黄斑中央凹定位/PALM-Testing400-Images'test_size=[]FileName=[]for i in range(len(list)):    #path = os.path.join(test_path, list[i])    path=test_list[i]    img=cv2.imread(path,1)    test_size.append(img.shape)    FileName.append(list['FileName'][i])test_size=np.array(test_size)

   In [32]

result=np.array(result)pred=[]for i in range(len(result[0])):    pred.extend(result[0][i])pred=np.array(pred) pred = paddle.to_tensor(pred)out=np.array(pred).reshape(-1,2)#Fovea_X=out[:,0]*data_std+data_mean#Fovea_Y=out[:,1]*data_std+data_meanFovea_X=out[:,0]Fovea_Y=out[:,1]#Fovea_X=Fovea_X*test_size[:,1]#Fovea_Y=Fovea_Y*test_size[:,0]for i in range(400):    if test_labelx[i](test_size[i][1]-112):        x0=test_size[i][1]-112    else:        x0=test_labelx[i]-112    if test_labely[i]test_size[i][0]-112:        y0=test_size[i][0]-112    else:        y0=test_labely[i]-112    Fovea_X[i]=x0+Fovea_X[i]*224    Fovea_Y[i]=y0+Fovea_Y[i]*224submission = pd.DataFrame(data={                            "FileName": FileName,                            "Fovea_X": Fovea_X,                            "Fovea_Y": Fovea_Y                        })submission=submission.sort_values(by='FileName')submission.to_csv("result.csv", index=False)

   

结果文件查看

In [33]

submission.head()

       

    FileName      Fovea_X      Fovea_Y0  T0001.jpg  1275.212769   947.6381231  T0002.jpg  1078.371338  1054.0875242  T0003.jpg  1079.881104  1059.2928473  T0004.jpg  1302.749023  1016.5989384  T0005.jpg  1309.635010   701.692017

               

结果投票集成

简单投票集成学习,这个可以提升效果,尽量选得分高的进行投票。

在统计学和机器学习中,集成学习方法使用多种学习算法来获得比单独使用任何单独的学习算法更好的预测性能。

使用不同超参数、不同的特征,不同的结构,运行多次模型可得到不同的预测结果。在这里我使用的是简单投票法,取平均值作为最终的预测结果。 预测出多个result后,进行投票,代码如下:

In [ ]

import numpy as npimport blackhole.dataframe as pddf1=pd.read_csv('result40.14874.csv')df2=pd.read_csv('result41.98309.csv')df3=pd.read_csv('result54.70313.csv')df4=pd.read_csv('result49.75246.csv')dfs=[df1,df2,df3,df4]File_Name=[]Fovea_X=[]Fovea_Y=[]for i in range(len(df1)):    File_Name.append(dfs[0]['FileName'][i])    avgx=(sum(np.array(dfs[x]['Fovea_X'][i]) for x in range(len(dfs))))/len(dfs)    avgy=(sum(np.array(dfs[x]['Fovea_Y'][i]) for x in range(len(dfs))))/len(dfs)        Fovea_X.append(avgx)    Fovea_Y.append(avgy)submission = pd.DataFrame(data={                            "FileName": File_Name,                            "Fovea_X": Fovea_X,                            "Fovea_Y":Fovea_Y                        })submission=submission.sort_values(by='FileName')submission.to_csv("result.csv", index=False)

   

(5)总结及改善方向

1、多试几个的预训练模型。

2、选择合适的学习率。

3、更换别的优化器。

4、投票方法能提高成绩,但是存在天花板。

5、曾专门用训练神经网络对中央凹可见、不可见情况进行了分类,结果测试集并未分到中央凹不可见的类别,但是总觉得测试集定位应该有(0,0),不是很确定。

(6)飞桨使用体验+给其他选手学习飞桨的建议

建议大家多参加百度AI Studio课程,多看别人写的AI Studio项目,也许会有灵感迸发,在比赛中取得更好的成绩。

以上就是飞桨常规赛:PALM眼底彩照中黄斑中央凹定位-11月第1名方案的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/52471.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
夸克网盘文档怎么朗读 夸克网盘文档怎么自动朗读教程
上一篇 2025年11月9日 04:37:14
三星承诺:今年将在全球 2 亿台设备上推出 Galaxy AI
下一篇 2025年11月9日 04:38:51

相关推荐

  • Java集合框架在数据处理中的应用实例

    使用Set去重:通过LinkedHashSet去除标签重复并保持顺序;2. Map统计频次:利用HashMap统计单词出现次数;3. List结合Comparator排序:按年龄升序、姓名降序排列用户;4. 集合嵌套处理数据:用Map组织部门与员工列表。集合框架提升数据处理效率与代码可读性。 Jav…

    2026年9月21日
    000
  • Chrome浏览器怎么开启数据同步功能_Chrome浏览器跨设备数据同步设置教程

    首先登录Google账户启用Chrome同步功能,确保书签、历史记录、密码等数据跨设备一致;接着在设置中自定义同步内容类型以满足隐私需求;然后通过Google账户密钥或自定义密码加密同步数据,提升安全性;最后在新设备登录同一账户,自动接收已同步的浏览数据,实现无缝体验。 如果您希望在不同设备间无缝使…

    2026年9月21日
    000
  • 如何为iPhone12Pro刷机固件下载?一步步教你操作

    首先使用爱思助手一键下载适用于iPhone 12 Pro的iOS 18固件,若失败则手动导入IPSW文件,最后可通过恢复模式配合电脑工具强制刷机完成系统重装。 如果您尝试为您的设备重新安装操作系统,但无法获取正确的系统文件,则可能是由于固件下载路径不正确或工具不支持。以下是解决此问题的步骤: 本文运…

    2026年9月21日
    000
  • 如何使用XGBoost训练AI大模型?优化机器学习模型的步骤

    XGBoost并非用于训练GPT类大模型,而是擅长处理结构化数据的高效梯度提升算法,其优势在于速度快、准确性高、支持并行计算、内置正则化与缺失值处理,适用于表格数据建模;通过分阶段超参数调优(如学习率、树深度、采样策略)、结合贝叶斯优化与交叉验证,并配合特征工程、数据预处理和集成学习等关键步骤,可显…

    2026年9月21日
    000
  • VSCode代码编辑器在线使用_VSCode网页版免安装直接进入编辑

    答案:无需安装即可在浏览器使用VSCode,主要方式包括GitHub Codespaces、Gitpod、StackBlitz、CodeSandbox和自托管code-server,适用于不同场景,如GitHub集成、前端开发或完全控制环境;但存在网络依赖、性能限制、插件兼容性、文件访问和安全等局限…

    2026年9月21日
    100
  • VSCode远程开发:配置容器与SSH连接的最佳实践解析

    使用VSCode远程开发提升效率,通过Remote-Containers和Remote-SSH实现环境标准化。1. 配置.devcontainer文件夹,用devcontainer.json定义容器环境,推荐自定义Dockerfile并预装工具;2. SSH连接需配置公钥认证、~/.ssh/conf…

    2026年9月21日
    100
  • Ubuntu20.04安装详细图文教程(双系统)[通俗易懂]

    Ubuntu20.04安装详细图文教程(双系统)[通俗易懂]Ubuntu20.04安装详细图文教程(双系统)[通俗易懂]Ubuntu20.04安装详细图文教程(双系统)[通俗易懂]Ubuntu20.04安装详细图文教程(双系统)[通俗易懂]

    大家好,很高兴再次与你们见面,我是你们的朋友全栈君。 Ubuntu安装前言最近我决定将开发环境切换到Linux系统,经过一番研究,我选择了Ubuntu桌面版,因为它不仅美观,而且作为生产系统的生态环境也非常好。于是,我开始寻找安装Ubuntu双系统的方法。安装方法有三种: 虚拟机安装:这种方法无法充…

    2026年9月21日 用户投稿
    000
  • 如何在Java中配置与数据库连接环境

    答案:Java中配置数据库连接需引入JDBC驱动,如MySQL在Maven中添加对应依赖;通过DriverManager或连接池(如HikariCP)获取Connection,使用try-with-resources管理资源;建议将连接参数存入properties文件,并处理常见问题如驱动加载、权限…

    2026年9月21日
    000
  • 蝴蝶号无人直播课程推荐:学习路径+核心技能梳理

    蝴蝶号无人直播课程推荐:学习路径+核心技能梳理蝴蝶号无人直播课程推荐:学习路径+核心技能梳理蝴蝶号无人直播课程推荐:学习路径+核心技能梳理蝴蝶号无人直播课程推荐:学习路径+核心技能梳理

    蝴蝶号无人直播的核心在于内容打磨与技术跑通。首要任务是明确直播间定位,如卖货、涨粉或娱乐,并据此准备高清视频、背景音乐及互动文案等素材。其次是技术实现,使用obs等推流工具配合虚拟摄像头软件,但需注意平台参数要求与网络稳定性,以确保直播流畅。最后是运营优化,通过短视频预热、自动回复、数据复盘等方式提…

    2026年9月21日 用户投稿
    000
  • VSCode怎么运行全部代码_VSCode批量执行代码教程

    在VSCode里“运行全部代码”或“批量执行代码”,其实很少是一个单一的、所有语言通用的按钮。它更多的是指根据你项目的具体需求,通过配置任务(Tasks)、使用集成终端(Integrated Terminal)配合脚本,或者利用特定语言的运行/调试配置(Launch Configurations)来…

    2026年9月21日
    100
  • TuxPaint的AI工具怎么裁剪图片?教你轻松完成图片裁剪步骤

    TuxPaint的AI工具怎么裁剪图片?教你轻松完成图片裁剪步骤TuxPaint的AI工具怎么裁剪图片?教你轻松完成图片裁剪步骤TuxPaint的AI工具怎么裁剪图片?教你轻松完成图片裁剪步骤TuxPaint的AI工具怎么裁剪图片?教你轻松完成图片裁剪步骤

    TuxPaint没有AI裁剪工具,只能通过橡皮擦或填充工具手动模拟裁剪效果,适合儿童创意绘画但不适合精确图像编辑。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜ TuxPaint作为一个面向儿童的绘画软件,其实并没有专门的“AI工具”来执行…

    2026年9月21日 用户投稿
    100
  • win11管理员权限不够怎么办_win11管理员权限不足解决方法

    首先以管理员身份运行程序,其次修改文件权限或启用Administrator账户,最后通过调整UAC设置或注册表禁用UAC来解决权限不足问题。 如果您在使用Windows 11时尝试执行某些系统级操作,但提示权限不足或被拒绝,即使当前账户为管理员,也可能是由于用户账户控制(UAC)或特定文件/程序的权…

    2026年9月21日
    100
  • Java Executors类提供哪些线程池方法

    Executors类提供创建线程池的静态方法:newFixedThreadPool创建固定大小线程池,适用于稳定负载;newCachedThreadPool创建可缓存线程池,适合短期异步任务;newSingleThreadExecutor创建单线程池,保证任务顺序执行;newScheduledThr…

    2026年9月21日
    200
  • Windows&Linux双系统安装流程

    Windows&Linux双系统安装流程Windows&Linux双系统安装流程Windows&Linux双系统安装流程Windows&Linux双系统安装流程

    大家好,很高兴再次见到大家,我是你们的朋友全栈君。 注意事项:在安装Windows与Linux双系统时,建议先安装Windows系统,否则可能会导致grub引导被覆盖的问题。 Windows 10系统安装 制作启动盘(优启通链接)https://www.php.cn/link/219b87ff108…

    2026年9月21日 用户投稿
    200
  • VSCode中怎么使用REM_VSCode移动端REM布局编写与换算教程

    答案:REM_VSCode插件可自动将像素转换为REM,需配置rootFontSize和precision,支持自动与手动转换,确保与html的font-size一致,配合media query适配不同屏幕,若插件异常可检查配置、重启或重装,替代工具有postcss-pxtorem、在线转换工具及浏…

    2026年9月21日
    100
  • 小红书发视频比例是多少?小红书视频是16比9还是4比3

    在当今社交媒体蓬勃发展的背景下,人们通过各种平台获取信息、娱乐和交流。其中,小红书作为一个以短视频和图文笔记为主的社交电商平台,吸引了大量用户群体。本文将围绕小红书平台上视频内容的占比情况进行分析,并探讨其背后的原因及未来发展趋势。 一、小红书视频内容占比现状 根据相关数据统计,目前小红书平台上的视…

    2026年9月21日
    200
  • UC浏览器如何开启省流模式_UC浏览器开启省流模式方法

    开启省流模式可减少UC浏览器流量消耗,通过设置菜单、首页快捷入口或搜索功能三种方式均可启用,系统会压缩网页内容以节省资源。 如果您在使用UC浏览器时希望减少数据流量消耗,尤其是在移动网络环境下,可以通过开启省流模式来优化网页加载方式。该功能会压缩页面内容,降低图片质量和资源体积,从而节省流量。 本文…

    2026年9月21日
    100
  • MySQL性能模式监控资源_MySQL瓶颈定位精确工具

    MySQL性能模式监控资源_MySQL瓶颈定位精确工具MySQL性能模式监控资源_MySQL瓶颈定位精确工具MySQL性能模式监控资源_MySQL瓶颈定位精确工具MySQL性能模式监控资源_MySQL瓶颈定位精确工具

    mysql性能模式通过事件记录精准定位瓶颈,核心步骤包括:1.启用并配置performance schema,选择性开启消费者和仪器;2.监控等待事件、sql语句、阶段、i/o、内存及锁等关键指标;3.分析events_waits_summary_global_by_event_name等表识别资源…

    2026年9月21日 用户投稿
    000
  • 三星在电视端首发Perplexity AI应用程序,带来更具创新性AI体验

    10 月 23 日消息,三星电子于美国当地时间 21 日宣布,率先在电视终端推出 perplexity ai 应用程序,为三星电视用户带来更富创新的 ai 使用体验。 借助该应用程序,用户在安排日常生活、查找特定影视内容、创建梦幻体育联赛阵容或策划万圣节活动等场景中,可获得 AI 以卡片式回复框形式…

    2026年9月21日
    500
  • 帕鲁高管回应《幻兽帕鲁:帕鲁农场》疑似碰瓷《宝可梦 pokopia》:乱讲阴谋论

    帕鲁高管回应《幻兽帕鲁:帕鲁农场》疑似碰瓷《宝可梦 pokopia》:乱讲阴谋论帕鲁高管回应《幻兽帕鲁:帕鲁农场》疑似碰瓷《宝可梦 pokopia》:乱讲阴谋论帕鲁高管回应《幻兽帕鲁:帕鲁农场》疑似碰瓷《宝可梦 pokopia》:乱讲阴谋论帕鲁高管回应《幻兽帕鲁:帕鲁农场》疑似碰瓷《宝可梦 pokopia》:乱讲阴谋论

    在不久前的任天堂直面会上,官方公布了一款宝可梦ip的衍生新作——《宝可梦 pokopia》。这款作品让玩家化身一只能够变身成人类训练家的百变怪,主打种田与建造玩法,属于模拟经营类游戏。 视频欣赏: 无独有偶,几天后,《幻兽帕鲁》的开发商PocketPair也正式公布了他们的全新衍生作《幻兽帕鲁:帕鲁…

    2026年9月21日 用户投稿
    000

发表回复

登录后才能评论
关注微信