1主要参考

(1)paddle的API官方地址

Conv2D-API文档-PaddlePaddle深度学习平台

(2)本教程和以下教程不够详细,还是推荐下面这个大佬的blog看一下

计算机视觉——眼疾图片识别(数据集iChallenge-PM)_「已注销」的博客-CSDN博客

(3)blibli视频

252-06_预测病理性近视_图片数据读取_dec_哔哩哔哩_bilibili

 (4)数据集地址

眼疾识别数据集iChallenge-PM - 飞桨AI Studio

2、数据集介绍

(1)数据集

(2)所使用的文件

1)解压3个压缩包,拷贝出来需要的

(3)paddle---近视眼睛分类的例子-LMLPHP

 2)将valid_gt.zip中的压缩包中的excel另存为.csv文件,另存后,注意删除最后的两行空数据

3)剩下来,建议看大佬的代码吧

(3)paddle---近视眼睛分类的例子-LMLPHP

计算机视觉——眼疾图片识别(数据集iChallenge-PM)_「已注销」的博客-CSDN博客

3、基于Lenet的程序实现(基础实现) 

(1)程序测试代码

import cv2
import random
import numpy as np
import os
import paddle
import paddle.nn.functional as F
from paddle.nn import Conv2D, MaxPool2D, Linear, Dropout

#对读入的图像数据进行预处理
def transform_img(img):
    #将图片尺寸缩放到 224 * 224
    img = cv2.resize(img, (224,224))
    #读取的图像数据格式是[H, W, C]
    #使用转置操作将其变成[C, H, W]
    img = np.transpose(img,(2,0,1))
    #归一化操作,将数据范围调整到[-1.0, 1.0]之间
    img = img / 255
    img = img * 2.0 -1.0
    return img


#定义训练集数据读取器
def data_loader(datadir, batch_size=10, mode='train'):
    #将datadir目录下的文件列出来,每条文件都读入
    filenames = os.listdir(datadir)
    def reader():
        # print("chen_filenames")
        # print(filenames)
        #只有在训练的时随机打乱数据顺序,测试的时候不打乱
        if mode == 'train':
            random.shuffle(filenames)
        batch_imgs = []
        batch_labels = []
        for name in filenames:
            filepath = os.path.join(datadir,name)
            img = cv2.imread(filepath)
            img = transform_img(img)
            if name[0] == 'H' or name[0] == 'N':
                # H开头的文件名表示高度近似,N开头的文件名表示正常视力
                # 高度近似和正常视力的样板,都不是病理性的,属于负样本,标签为0
                label = 0
            elif name[0] == 'P':
                # P开头的是病理性近似,属于正样本,标签为1
                label = 1
            else:
                raise('Not excepted file name')
            #每读取一个样板的数据,就将其放入数据列表中
            batch_imgs.append(img)
            batch_labels.append(label)
            if len(batch_imgs) == batch_size:
                # 当数据列表的长度等于batch_size的时候
                # 把这些数据当做一个mini-batch,并作为数据生成器的一个输出
                imgs_array = np.array(batch_imgs).astype('float32')
                labels_array = np.array(batch_labels).astype('float32').reshape(-1,1)
                # yield的作用:返回一个可以用来迭代(for循环)的生成器,
                # 它的应用场景通常为一个需要返回一系列值的,含有循环的函数中
                yield imgs_array, labels_array
                batch_imgs = []
                batch_labels = []
        
        #上面都循环结束了,如何还有剩下的,也就是样板数/batch_size数没有整除
        if len(batch_imgs) > 0:
            imgs_array = np.array(batch_imgs).astype('float32')
            labels_array = np.array(batch_labels).astype('float32').reshape(-1,1)
            # yield的作用:返回一个可以用来迭代(for循环)的生成器,
            # 它的应用场景通常为一个需要返回一系列值的,含有循环的函数中
            yield imgs_array, labels_array

    return reader


EPOCH_NUM = 5

#定义训练过程
def train_pm(model, optimizer):
    # 开启0号GPU训练
    use_gpu = True
    paddle.device.set_device('gpu:0') if use_gpu else paddle.device.set_device('cpu')

    print('start training ...')
    model.train()
    # 定义数据读取器,训练数据读取器和验证数据读取器
    train_loader = data_loader(DATADIR, batch_size=10, mode='train')
    for epoch in range(EPOCH_NUM):
        for batch_id, data in enumerate(train_loader()):  #在返回的reader里面调用函数,调用的就是yield中的枚举返回值
            x_data, y_data = data
            img = paddle.to_tensor(x_data)
            label = paddle.to_tensor(y_data)
            # 运行模型进行前向推理计算,得到预测值
            logits = model(img)
            loss = F.binary_cross_entropy_with_logits(logits, label)
            avg_loss = paddle.mean(loss)

            if batch_id % 20 == 0:
                print("epoch: {},batch_id: {}, loss is: {:.4f}".format(epoch, batch_id, float(avg_loss.numpy())))
            #反向传播,更新权重,清除梯度
            avg_loss.backward()
            optimizer.step()
        
        #每一个epoch结束都测试一下
        model.eval()
        accuracies = []
        losses = []
        valid_loader = data_loader(DATADIR, batch_size=10, mode='eval')
        for batch_id, data in enumerate(valid_loader()):
            x_data, y_data = data
            img = paddle.to_tensor(x_data)
            label = paddle.to_tensor(y_data)
            #运行模型前向计算,得到预测值
            logits = model(img)
            # 二分类,sigmoid计算后的结果以0.5为阈值分两个类型
            # 计算sigmoid后的预测概率,进行loss计算
            pred = F.sigmoid(logits)   # P正的概率
            loss = F.binary_cross_entropy_with_logits(logits,label)
            #计算概率小于0.5的类别
            pred2 = pred*(-1.0) + 1.0  # P负的概率,也就是1-P正
            #得到两个类别的预测概率,并沿第一个维度级联
            pred = paddle.concat([pred2, pred],axis=1)
            #原因是paddle.metric.accuracy的输入要是每个类别的概率,所以拼接了一下
            acc = paddle.metric.accuracy(pred, paddle.cast(label,dtype='int64'))


            accuracies.append(acc.numpy())
            losses.append(loss.numpy())
        print("[validation] accuracy /loss: {:.4f}/{:.4f}".format(np.mean(accuracies),np.mean(losses))) #求平均
        model.train()

        paddle.save(model.state_dict(),'palm.pdparams')        
        paddle.save(optimizer.state_dict(),'palm.pdopt')


#定义评国过程
def evaluation(model, params_file_path):
    # 开启0号GPU预估
    use_gpu = True
    paddle.device.set_device('gpu:0') if use_gpu else paddle.device.set_device('cpu')

    print('start evaluation ...')
    #加载模型参数
    model_state_dict = paddle.load(params_file_path)
    model.load_dict(model_state_dict)
    
    model.eval()
    eval_loader = data_loader(DATADIR, batch_size=10, mode='eval')

    acc_set = []
    avg_loss_set = []
    for batch_id, data in enumerate(eval_loader()):
        x_data, y_data =data
        img = paddle.to_tensor(x_data)
        label = paddle.to_tensor(y_data)
        y_data = y_data.astype(np.int64)
        label_64 = paddle.to_tensor(y_data)
        #计算预测和精度
        #模型的forward方法这两个封装了对img, label_64的判断,如果传入了label,则也返回acc
        prediction, acc = model(img, label_64)
        # 计算损失函数值
        loss = F.binary_cross_entropy_with_logits(prediction, label)
        avg_loss = paddle.mean(loss)
        acc_set.append(float(acc.numpy()))
        avg_loss_set.append(float(avg_loss.numpy()))
    
    #求平均精度
    acc_val_mean = np.array(acc_set).mean()
    avg_loss_val_mean = np.array(avg_loss_set).mean()

    print('loss={:.4f}, acc={:.4f}'.format(avg_loss_val_mean,acc_val_mean))



#定义Lenet网络结果
# class Lenet(paddle.nn.Layer):
#     pass 

# 定义 LeNet 网络结构
class LeNet(paddle.nn.Layer):
    def __init__(self, num_classes=1):
        super(LeNet, self).__init__()

        # 创建卷积和池化层块,每个卷积层使用Sigmoid激活函数,后面跟着一个2x2的池化
        self.conv1 = Conv2D(in_channels=3, out_channels=6, kernel_size=5)
        self.max_pool1 = MaxPool2D(kernel_size=2, stride=2)
        self.conv2 = Conv2D(in_channels=6, out_channels=16, kernel_size=5)
        self.max_pool2 = MaxPool2D(kernel_size=2, stride=2)
        # 创建第3个卷积层
        self.conv3 = Conv2D(in_channels=16, out_channels=120, kernel_size=4)
        # 创建全连接层,第一个全连接层的输出神经元个数为64, 第二个全连接层输出神经元个数为分类标签的类别数
        self.fc1 = Linear(in_features=300000, out_features=64)
        self.fc2 = Linear(in_features=64, out_features=num_classes)
    # 网络的前向计算过程
    def forward(self, x, label=None):
        x = self.conv1(x)
        x = F.sigmoid(x)
        x = self.max_pool1(x)
        x = self.conv2(x)
        x = F.sigmoid(x)        
        x = self.max_pool2(x)
        x = self.conv3(x)
        x = F.sigmoid(x)          
        x = paddle.reshape(x, [x.shape[0], -1])
        x = self.fc1(x)
        x = self.fc2(x)
        if label is not None:
            acc = paddle.metric.accuracy(input=x,label=label)
            return x,acc
        else:
            return x


# 数据的路径
DATADIR = '/home/chen/deep_data/eye_ill/training/PALM-Training400'
#创建模型
model = LeNet(num_classes=1)
#启动训练过程
opt = paddle.optimizer.Momentum(learning_rate=0.001,momentum=0.9,
                                parameters=model.parameters())
train_pm(model,optimizer=opt)
evaluation(model,params_file_path='palm.pdparams')

(2)5个epoch的测试结果

(3)paddle---近视眼睛分类的例子-LMLPHP

4、基于paddle.nn的程序实现(修改了大佬代码,丢弃paddle.fluid) 

(1)看了一下paddle的api, paddle.fluid已经被丢弃

(3)paddle---近视眼睛分类的例子-LMLPHP

 (2)主要修改注意事项

4.1 Conv2D函数

Conv2D-API文档-PaddlePaddle深度学习平台

class paddle.nn.Conv2D(in_channelsout_channelskernel_sizestride=1padding=0dilation=1groups=1padding_mode='zeros'weight_attr=Nonebias_attr=Nonedata_format='NCHW')

(2)fluid和nn的主要的修改对比如下

self.conv1 = paddle.fluid.dygraph.nn.Conv2D(num_channels=3, num_filters=6, filter_size=5,act='sigmoid')

self.conv1= paddle.nn.Conv2D(in_channels=3,out_channels=6,kernel_size=5)  #sigmoid单独在forward中实现

4.2MaxPool2D

(1)函数说明

MaxPool2D-API文档-PaddlePaddle深度学习平台

paddle.nn.MaxPool2D(kernel_sizestride=Nonepadding=0ceil_mode=Falsereturn_mask=Falsedata_format='NCHW'name=None)

 (2)fluid和nn的主要的修改对比如下

self.pool1 = paddle.fluid.dygraph.nn.Pool2D(pool_size=2, pool_stride=2, pool_type='max')

self.pool1 = paddle.nn.MaxPool2D(kernel_size=2, stride=2)

4.3 Linear

Linear-API文档-PaddlePaddle深度学习平台

(1)函数定义

class paddle.nn.Linear(in_featuresout_featuresweight_attr=Nonebias_attr=Nonename=None)

(2)fluid和nn的主要的修改对比如下

self.fc1 = paddle.fluid.dygraph.nn.Linear(input_dim=300000, output_dim=64, act='sigmoid')

self.fc1 = paddle.nn.Linear(in_features=300000, out_features=64)#sigmoid单独在forward中实现 

4.4sigmoid_cross_entropy_with_logits

binary_cross_entropy_with_logits-API文档-PaddlePaddle深度学习平台

(1)fluid.layers.sigmoid_cross_entropy_with_logits的定义

(3)paddle---近视眼睛分类的例子-LMLPHP

 (2)paddle.nn.functional.binary_cross_entropy_with_logits的定义

(3)paddle---近视眼睛分类的例子-LMLPHP

4.5 基于新版API的paddle.nn的实现

(1)测试代码

import cv2
import os
import random
import numpy as np
#已丢弃
# import paddle.fluid as fluid
# from paddle.fluid.dygraph.nn import Conv2D, Pool2D, Linear
import paddle
import paddle.nn.functional as F
from paddle.nn import Conv2D, MaxPool2D, Linear, Dropout

"""
数据集iChallenge-PM(眼疾识别)
"""


def transform_img(img):
    img = cv2.resize(img, (224, 224))
    img = np.transpose(img, (2, 0, 1))
    img = img.astype('float32')
    img = img / 255.
    img = img * 2.0 - 1.0
    return img


def data_loader(datadir, batch_size=10, mode='train'):
    filenames = os.listdir(datadir)

    def reader():
        if mode == 'train':
            random.shuffle(filenames)
        batch_imgs = []
        batch_labels = []
        for name in filenames:
            filepath = os.path.join(datadir, name)
            img = cv2.imread(filepath)
            img = transform_img(img)
            if name[0] == 'H':
                label = 0
            elif name[0] == 'N':
                label = 0
            elif name[0] == 'P':
                label = 1
            else:
                print('Not excepted file name')
                print(name[0])
                exit(-1)
            batch_imgs.append(img)
            batch_labels.append(label)
            if len(batch_imgs) == batch_size:
                imgs_array = np.array(batch_imgs).astype('float32')
                labels_array = np.array(batch_labels).astype(
                    'float32').reshape(-1, 1)
                yield imgs_array, labels_array
                batch_imgs = []
                batch_labels = []
        if len(batch_imgs) > 0:
            imgs_array = np.array(batch_imgs).astype('float32')
            labels_array = np.array(batch_labels).astype('float32').reshape(
                -1, 1)
            yield imgs_array, labels_array

    return reader


def valid_data_loader(datadir, csvfile, batch_size=10, mode='valid'):
    filelists = open(csvfile).readlines()

    def reader():
        batch_imgs = []
        batch_labels = []
        for line in filelists[1:]:
            line = line.strip().split(',')
            name = line[1]
            label = int(line[2])
            filepath = os.path.join(datadir, name)
            img = cv2.imread(filepath)
            img = transform_img(img)
            batch_imgs.append(img)
            batch_labels.append(label)
            if len(batch_imgs) == batch_size:
                imgs_array = np.array(batch_imgs).astype('float32')
                labels_array = np.array(batch_labels).astype(
                    'float32').reshape(-1, 1)
                yield imgs_array, labels_array
                batch_imgs = []
                batch_labels = []
        if len(batch_imgs) > 0:
            imgs_array = np.array(batch_imgs).astype('float32')
            labels_array = np.array(batch_labels).astype('float32').reshape(
                -1, 1)
            yield imgs_array, labels_array

    return reader


DATADIR = 'D:/pytorch_learning2022/data/eye/PALM-Training400'
DATADIR2 = 'D:/pytorch_learning2022/data/eye/PALM-Validation400'
CSCVFILE = 'D:/pytorch_learning2022/data/eye/PM_Label_and_Fovea_Location.csv'


# 定义LeNet的网络结构
class LeNet(paddle.nn.Layer):
    def __init__(self, name_scope, num_classes=1):
        super(LeNet, self).__init__(name_scope)

        # self.conv1 = paddle.fluid.dygraph.nn.Conv2D(num_channels=3, num_filters=6, filter_size=5,act='sigmoid')
        # self.conv1= paddle.nn.Conv2D(in_channels=3,out_channels=6,kernel_size=5)  #sigmoid单独在forward中实现
        self.conv1= Conv2D(in_channels=3,out_channels=6,kernel_size=5)  #sigmoid单独在forward中实现
        # self.pool1 = paddle.fluid.dygraph.nn.Pool2D(pool_size=2, pool_stride=2, pool_type='max')
        # self.pool1 = paddle.nn.MaxPool2D(kernel_size=2, stride=2)
        self.pool1 = MaxPool2D(kernel_size=2, stride=2)

        # self.conv2 = Conv2D(num_channels=6,num_filters=16,filter_size=5,act='sigmoid')
        self.conv2= Conv2D(in_channels=6,out_channels=16,kernel_size=5)  #sigmoid单独在forward中实现        
        # self.pool2 = Pool2D(pool_size=2, pool_stride=2, pool_type='max')
        self.pool2 = MaxPool2D(kernel_size=2, stride=2)
        # self.conv3 = Conv2D(num_channels=16,num_filters=120, filter_size=4, act='sigmoid')
        self.conv3= Conv2D(in_channels=16,out_channels=120,kernel_size=4)  #sigmoid单独在forward中实现 
               
        # self.fc1 = paddle.fluid.dygraph.nn.Linear(input_dim=300000, output_dim=64, act='sigmoid')
        # self.fc1 = paddle.nn.Linear(in_features=300000, out_features=64)#sigmoid单独在forward中实现 
        self.fc1 = Linear(in_features=300000, out_features=64) #sigmoid单独在forward中实现 
        # self.fc2 = Linear(input_dim=64, output_dim=num_classes)
        self.fc2 = Linear(in_features=64, out_features=num_classes) 

    def forward(self, x):
        x = self.conv1(x)
        x = F.sigmoid(x)
        x = self.pool1(x)

        x = self.conv2(x)
        x = F.sigmoid(x)
        x = self.pool2(x)
        x = self.conv3(x)
        x = F.sigmoid(x)

        # x = fluid.layers.reshape(x, [x.shape[0], -1])
        x = paddle.reshape(x, [x.shape[0], -1])
        x = self.fc1(x)
        x = F.sigmoid(x)
        x = self.fc2(x)
        return x


# 定义AlexNet网络结构
class AlexNet(paddle.nn.Layer):
    def __init__(self, name_scope, num_classes=1):
        super(AlexNet, self).__init__(name_scope)
        name_scope = self.full_name
        # self.conv1 = Conv2D(num_channels=3, num_filters=96,filter_size=11, stride=4, padding=5,act='relu')
        self.conv1= Conv2D(in_channels=3,out_channels=96,kernel_size=5,stride=4,padding=5)  #relu单独在forward中实现
        # self.pool1 = Pool2D(pool_size=2, pool_stride=2, pool_type='max')
        self.pool1 = MaxPool2D(kernel_size=2, stride=2)
        
        # self.conv2 = Conv2D(num_channels=96,num_filters=256,filter_size=5,stride=1,padding=2, act='relu')
        self.conv2= Conv2D(in_channels=96,out_channels=256,kernel_size=5,stride=1,padding=2)  #relu单独在forward中实现        
        # self.pool2 = Pool2D(pool_size=2, pool_stride=2, pool_type='max')
        self.pool2 = MaxPool2D(kernel_size=2, stride=2)
        
        # self.conv3 = Conv2D(num_channels=256,num_filters=384,filter_size=3,stride=1,padding=1,act='relu')
        self.conv3 = Conv2D(in_channels=256,out_channels=384,kernel_size=3,stride=1,padding=1)  #relu单独在forward中实现                
        # self.conv4 = Conv2D(num_channels=384,num_filters=384,filter_size=3,stride=1,padding=1,act='relu')
        self.conv4 = Conv2D(in_channels=384,out_channels=384,kernel_size=3,stride=1,padding=1)  #relu单独在forward中实现                        
        # self.conv5 = Conv2D(num_channels=384,num_filters=256,filter_size=3,stride=1,padding=1,act='relu')
        self.conv5 = Conv2D(in_channels=384,out_channels=256,kernel_size=3,stride=1,padding=1)  #relu单独在forward中实现                        
        # self.pool5 = Pool2D(pool_size=2, pool_stride=2, pool_type='max')
        self.pool5 = MaxPool2D(kernel_size=2, stride=2)        

        # self.fc1 = Linear(input_dim=12544, output_dim=4096, act='relu')
        self.fc1 = Linear(in_features=12544, out_features=4096) #relu单独在forward中实现 
        self.drop_ratio1 = 0.5
        # self.fc2 = Linear(input_dim=4096, output_dim=4096, act='relu')
        self.fc2 = Linear(in_features=4096, out_features=4096) #relu单独在forward中实现 
        self.drop_ratio2 = 0.5
        # self.fc3 = Linear(input_dim=4096, output_dim=num_classes)
        self.fc3 = Linear(in_features=4096, out_features=num_classes) 

    def forward(self, x):
        x = self.conv1(x)
        x = F.relu(x)
        x = self.pool1(x)
        x = self.conv2(x)
        x = F.relu(x)
        x = self.pool2(x)
        x = self.conv3(x)
        x = F.relu(x)
        x = self.conv4(x)
        x = F.relu(x)
        x = self.conv5(x)
        x = F.relu(x)
        x = self.pool5(x)

        # x = fluid.layers.reshape(x, [x.shape[0], -1])
        x = paddle.reshape(x, [x.shape[0], -1])
        x = self.fc1(x)
        x = F.relu(x)
        x = F.dropout(x, self.drop_ratio1)
        x = self.fc2(x)
        x = F.relu(x)
        x = F.dropout(x, self.drop_ratio2)
        x = self.fc3(x)
        return x


# 定义训练过程
def train(model):
    print("---- start training ----")
    model.train()
    epoch_num = 5
    # opt = fluid.optimizer.Momentum(learning_rate=0.001,momentum=0.9, parameter_list=model.parameters())
    opt = paddle.optimizer.Momentum(learning_rate=0.001, momentum=0.9, parameters=model.parameters())
   
    train_loader = data_loader(DATADIR, batch_size=10, mode='train')
    valid_loader = valid_data_loader(DATADIR2, CSCVFILE)
    for epoch in range(epoch_num):
        for batch_id, data in enumerate(train_loader()):
            x_data, y_data = data
            img = paddle.to_tensor(x_data)
            label = paddle.to_tensor(y_data)
            logits = model(img)
            # loss = fluid.layers.sigmoid_cross_entropy_with_logits(logits, label)
            loss = F.binary_cross_entropy_with_logits(logits, label)  #是否有问题待确认
            avg_loss = paddle.mean(loss)

            if batch_id % 10 == 0:
                print("epoch: {}, batch_id: {}, loss is: {}".format(
                    epoch, batch_id, avg_loss.numpy()))
            avg_loss.backward()
            opt.minimize(avg_loss)
            model.clear_gradients()

        model.eval()
        accuracies = []
        losses = []
        for batch_id, data in enumerate(valid_loader()):
            x_data, y_data = data
            img = paddle.to_tensor(x_data)
            label = paddle.to_tensor(y_data)
            logits = model(img)
            pred = F.sigmoid(logits)
            # loss = fluid.layers.sigmoid_cross_entropy_with_logits(logits, label)
            loss = F.binary_cross_entropy_with_logits(logits, label)

            pred2 = pred * (-1.0) + 1.0
            # pred = fluid.layers.concat([pred2, pred], axis=1)
            pred = paddle.concat([pred2, pred], axis=1)
            # acc = fluid.layers.accuracy(pred, fluid.layers.cast(label, dtype='int64'))
            acc = paddle.metric.accuracy(pred, paddle.cast(label,dtype='int64'))
            accuracies.append(acc.numpy())
            losses.append(loss.numpy())
        print("[validation accuracy/loss: {}/{}]".format(
            np.mean(accuracies), np.mean(losses)))
        model.train()
    # fluid.save_dygraph(model.state_dict(), 'D:/pytorch_learning2022/00_01paddle_learning/result/iChallengePM')
    # fluid.save_dygraph(opt.state_dict(), 'D:/pytorch_learning2022/00_01paddle_learning/result/iChallengePM')
    paddle.save(model.state_dict(),'palm.pdparams')        
    paddle.save(opt.state_dict(),'palm.pdopt')

if __name__ == "__main__":
    # use_gpu = True
    use_gpu = False
    paddle.device.set_device('gpu:0') if use_gpu else paddle.device.set_device('cpu')
    # with fluid.dygraph.guard():
        # model = LeNet("LeNet")
        # model = AlexNet("AlexNet")
    

    # model = LeNet("LeNet")
    model = AlexNet("AlexNet")
    train(model)

5、使用paddle.vision中的模型来测试分类

PS:看起来paddle和torch没什么区别

(1)可以直接只用很多模型

from paddle.vision.models import resnet50,vgg16,mobilenet_v3_small,LeNet,GoogLeNet

(2)测试的时候可以直接给定分类和是否使用预训练和直接给定分类个数

    model =resnet50(pretrained=True,num_classes=1)

(3)完整测试代码如下

import cv2
import os
import random
import numpy as np
#已丢弃
# import paddle.fluid as fluid
# from paddle.fluid.dygraph.nn import Conv2D, Pool2D, Linear
import paddle
import paddle.nn.functional as F
from paddle.nn import Conv2D, MaxPool2D, Linear, Dropout
from paddle.vision.models import resnet50,vgg16,mobilenet_v3_small,LeNet,GoogLeNet


"""
数据集iChallenge-PM(眼疾识别)
"""


def transform_img(img):
    img = cv2.resize(img, (224, 224))
    img = np.transpose(img, (2, 0, 1))
    img = img.astype('float32')
    img = img / 255.
    img = img * 2.0 - 1.0
    return img


def data_loader(datadir, batch_size=10, mode='train'):
    filenames = os.listdir(datadir)

    def reader():
        if mode == 'train':
            random.shuffle(filenames)
        batch_imgs = []
        batch_labels = []
        for name in filenames:
            filepath = os.path.join(datadir, name)
            img = cv2.imread(filepath)
            img = transform_img(img)
            if name[0] == 'H':
                label = 0
            elif name[0] == 'N':
                label = 0
            elif name[0] == 'P':
                label = 1
            else:
                print('Not excepted file name')
                print(name[0])
                exit(-1)
            batch_imgs.append(img)
            batch_labels.append(label)
            if len(batch_imgs) == batch_size:
                imgs_array = np.array(batch_imgs).astype('float32')
                labels_array = np.array(batch_labels).astype(
                    'float32').reshape(-1, 1)
                yield imgs_array, labels_array
                batch_imgs = []
                batch_labels = []
        if len(batch_imgs) > 0:
            imgs_array = np.array(batch_imgs).astype('float32')
            labels_array = np.array(batch_labels).astype('float32').reshape(
                -1, 1)
            yield imgs_array, labels_array

    return reader


def valid_data_loader(datadir, csvfile, batch_size=10, mode='valid'):
    filelists = open(csvfile).readlines()

    def reader():
        batch_imgs = []
        batch_labels = []
        for line in filelists[1:]:
            line = line.strip().split(',')
            name = line[1]
            label = int(line[2])
            filepath = os.path.join(datadir, name)
            img = cv2.imread(filepath)
            img = transform_img(img)
            batch_imgs.append(img)
            batch_labels.append(label)
            if len(batch_imgs) == batch_size:
                imgs_array = np.array(batch_imgs).astype('float32')
                labels_array = np.array(batch_labels).astype(
                    'float32').reshape(-1, 1)
                yield imgs_array, labels_array
                batch_imgs = []
                batch_labels = []
        if len(batch_imgs) > 0:
            imgs_array = np.array(batch_imgs).astype('float32')
            labels_array = np.array(batch_labels).astype('float32').reshape(
                -1, 1)
            yield imgs_array, labels_array

    return reader


DATADIR = 'D:/pytorch_learning2022/data/eye/PALM-Training400'
DATADIR2 = 'D:/pytorch_learning2022/data/eye/PALM-Validation400'
CSCVFILE = 'D:/pytorch_learning2022/data/eye/PM_Label_and_Fovea_Location.csv'



# 定义训练过程
def train(model):
    print("---- start training ----")
    model.train()
    epoch_num = 5
    # opt = fluid.optimizer.Momentum(learning_rate=0.001,momentum=0.9, parameter_list=model.parameters())
    opt = paddle.optimizer.Momentum(learning_rate=0.001, momentum=0.9, parameters=model.parameters())
   
    train_loader = data_loader(DATADIR, batch_size=10, mode='train')
    valid_loader = valid_data_loader(DATADIR2, CSCVFILE)
    for epoch in range(epoch_num):
        for batch_id, data in enumerate(train_loader()):
            x_data, y_data = data
            img = paddle.to_tensor(x_data)
            label = paddle.to_tensor(y_data)
            logits = model(img)
            # loss = fluid.layers.sigmoid_cross_entropy_with_logits(logits, label)
            loss = F.binary_cross_entropy_with_logits(logits, label)  #是否有问题待确认
            avg_loss = paddle.mean(loss)

            if batch_id % 10 == 0:
                print("epoch: {}, batch_id: {}, loss is: {}".format(
                    epoch, batch_id, avg_loss.numpy()))
            avg_loss.backward()
            opt.minimize(avg_loss)
            model.clear_gradients()

        model.eval()
        accuracies = []
        losses = []
        for batch_id, data in enumerate(valid_loader()):
            x_data, y_data = data
            img = paddle.to_tensor(x_data)
            label = paddle.to_tensor(y_data)
            logits = model(img)
            pred = F.sigmoid(logits)
            # loss = fluid.layers.sigmoid_cross_entropy_with_logits(logits, label)
            loss = F.binary_cross_entropy_with_logits(logits, label)

            pred2 = pred * (-1.0) + 1.0
            # pred = fluid.layers.concat([pred2, pred], axis=1)
            pred = paddle.concat([pred2, pred], axis=1)
            # acc = fluid.layers.accuracy(pred, fluid.layers.cast(label, dtype='int64'))
            acc = paddle.metric.accuracy(pred, paddle.cast(label,dtype='int64'))
            accuracies.append(acc.numpy())
            losses.append(loss.numpy())
        print("[validation accuracy/loss: {}/{}]".format(
            np.mean(accuracies), np.mean(losses)))
        model.train()
    # fluid.save_dygraph(model.state_dict(), 'D:/pytorch_learning2022/00_01paddle_learning/result/iChallengePM')
    # fluid.save_dygraph(opt.state_dict(), 'D:/pytorch_learning2022/00_01paddle_learning/result/iChallengePM')
    paddle.save(model.state_dict(),'palm.pdparams')        
    paddle.save(opt.state_dict(),'palm.pdopt')

if __name__ == "__main__":
    # use_gpu = True
    use_gpu = False
    paddle.device.set_device('gpu:0') if use_gpu else paddle.device.set_device('cpu')
    # model =resnet50()
    model =resnet50(pretrained=True,num_classes=1)
    train(model)

11-20 13:59