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

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)数据集

iChallenge-PM是百度大脑和中山大学中山眼科中心联合举办的iChallenge比赛中,提供的关于病理性近视(Pathologic Myopia,PM)的医疗类数据集,包含1200个受试者的眼底视网膜图片,训练、验证和测试数据集各400张。 training.zip:包含训练中的图片和标签
validation.zip:包含验证集的图片
valid_gt.zip:包含验证集的标签  

iChallenge-PM中既有病理性近视患者的眼底图片,也有非病理性近视患者的图片,命名规则如下: 病理性近视(PM):文件名以P开头
非病理性近视(non-PM): 高度近似(high myopia):文件名以H开头
正常眼睛(normal):文件名以N开头

(2)所使用的文件

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

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

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

计算机视觉——眼疾图片识别(数据集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的测试结果

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

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

 (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')

  • in_channels (int) - 输入图像的通道数。

  • out_channels (int) - 由卷积操作产生的输出的通道数。

  • kernel_size (int|list|tuple) - 卷积核大小。可以为单个整数或包含两个整数的元组或列表,分别表示卷积核的高和宽。如果为单个整数,表示卷积核的高和宽都等于该整数。

  • stride (int|list|tuple,可选) - 步长大小。可以为单个整数或包含两个整数的元组或列表,分别表示卷积沿着高和宽的步长。如果为单个整数,表示沿着高和宽的步长都等于该整数。默认值:1。

  • padding (int|list|tuple|str,可选) - 填充大小。如果它是一个字符串,可以是"VALID"或者"SAME",表示填充算法,计算细节可参考上述 padding = "SAME"或 padding = "VALID" 时的计算公式。如果它是一个元组或列表,它可以有3种格式:(1)包含4个二元组:当 data_format 为"NCHW"时为 [[0,0], [0,0], [padding_height_top, padding_height_bottom], [padding_width_left, padding_width_right]],当 data_format 为"NHWC"时为[[0,0], [padding_height_top, padding_height_bottom], [padding_width_left, padding_width_right], [0,0]];(2)包含4个整数值:[padding_height_top, padding_height_bottom, padding_width_left, padding_width_right];(3)包含2个整数值:[padding_height, padding_width],此时padding_height_top = padding_height_bottom = padding_height, padding_width_left = padding_width_right = padding_width。若为一个整数,padding_height = padding_width = padding。默认值:0。

(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)

  • ernel_size (int|list|tuple): 池化核大小。如果它是一个元组或列表,它必须包含两个整数值, (pool_size_Height, pool_size_Width)。若为一个整数,则它的平方值将作为池化核大小,比如若pool_size=2, 则池化核大小为2x2。

  • stride (int|list|tuple,可选):池化层的步长。如果它是一个元组或列表,它将包含两个整数,(pool_stride_Height, pool_stride_Width)。若为一个整数,则表示H和W维度上stride均为该值。默认值为None, 这时会使用kernel_size作为stride。

  • padding (str|int|list|tuple,可选) 池化填充。如果它是一个字符串,可以是"VALID"或者"SAME",表示填充算法。如果它是一个元组或列表,它可以有3种格式:(1)包含2个整数值:[pad_height, pad_width];(2)包含4个整数值:[pad_height_top, pad_height_bottom, pad_width_left, pad_width_right];(3)包含4个二元组:当 data_format 为"NCHW"时为 [[0,0], [0,0], [pad_height_top, pad_height_bottom], [pad_width_left, pad_width_right]],当 data_format 为"NHWC"时为[[0,0], [pad_height_top, pad_height_bottom], [pad_width_left, pad_width_right], [0,0]]。若为一个整数,则表示H和W维度上均为该值。默认值:0。

  • ceil_mode (bool,可选):是否用ceil函数计算输出高度和宽度。如果是True,则使用 ceil 计算输出形状的大小。

  • return_mask (bool,可选):是否返回最大索引和输出。默认为False.

  • data_format (str,可选): 输入和输出的数据格式,可以是"NCHW"和"NHWC"。N是批尺寸,C是通道数,H是特征高度,W是特征宽度。默认值:"NCHW"

  • name (str,可选):函数的名字,默认为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)

  • in_features (int) – 线性变换层输入单元的数目。

  • out_features (int) – 线性变换层输出单元的数目。

  • weight_attr (ParamAttr, 可选) – 指定权重参数的属性。默认值为None,表示使用默认的权重参数属性,将权重参数初始化为0。具体用法请参见 ParamAttr 。

  • bias_attr (ParamAttr|bool, 可选) – 指定偏置参数的属性。 bias_attrbias_attr 为bool类型且设置为False时,表示不会为该层添加偏置。 bias_attrbias_attr 如果设置为True或者None,则表示使用默认的偏置参数属性,将偏置参数初始化为0。具体用法请参见 ParamAttr 。默认值为None。

  • name (str,可选) – 具体用法请参见 Name ,一般无需设置,默认值为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的定义

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

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)

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值