网站开发发展趋势2018,淘宝客可以做返利网站吗,关键词林俊杰,门户网站网页设计目录
LeNet
LeNet在手写数字识别上的应用
LeNet在眼疾识别数据集iChallenge-PM上的应用 LeNet
LeNet是最早的卷积神经网络之一。1998年#xff0c;Yann LeCun第一次将LeNet卷积神经网络应用到图像分类上#xff0c;在手写数字识别任务中取得了巨大成功。LeNet通过连续使用…目录
LeNet
LeNet在手写数字识别上的应用
LeNet在眼疾识别数据集iChallenge-PM上的应用 LeNet
LeNet是最早的卷积神经网络之一。1998年Yann LeCun第一次将LeNet卷积神经网络应用到图像分类上在手写数字识别任务中取得了巨大成功。LeNet通过连续使用卷积和池化层的组合提取图像特征其架构如 图1 所示这里展示的是用于MNIST手写体数字识别任务中的LeNet-5模型 图1LeNet模型网络结构示意图 第一模块包含5×5的6通道卷积和2×2的池化。卷积提取图像中包含的特征模式激活函数使用Sigmoid图像尺寸从28减小到24。经过池化层可以降低输出特征图对空间位置的敏感性图像尺寸减到12。 第二模块和第一模块尺寸相同通道数由6增加为16。卷积操作使图像尺寸减小到8经过池化后变成4。 第三模块包含4×4的120通道卷积。卷积之后的图像尺寸减小到1但是通道数增加为120。将经过第3次卷积提取到的特征图输入到全连接层。第一个全连接层的输出神经元的个数是64第二个全连接层的输出神经元个数是分类标签的类别数对于手写数字识别的类别数是10。然后使用Softmax激活函数即可计算出每个类别的预测概率。 【提示】
卷积层的输出特征图如何当作全连接层的输入使用呢
卷积层的输出数据格式是[N,C,H,W][N, C, H, W][N,C,H,W]在输入全连接层的时候会自动将数据拉平
也就是对每个样本自动将其转化为长度为KKK的向量 LeNet在手写数字识别上的应用
LeNet网络的实现代码如下
# 导入需要的包
import paddle
import numpy as np
from paddle.nn import Conv2D, MaxPool2D, Linear## 组网
import paddle.nn.functional as F# 定义 LeNet 网络结构
class LeNet(paddle.nn.Layer):def __init__(self, num_classes1):super(LeNet, self).__init__()# 创建卷积和池化层# 创建第1个卷积层self.conv1 Conv2D(in_channels1, out_channels6, kernel_size5)self.max_pool1 MaxPool2D(kernel_size2, stride2)# 尺寸的逻辑池化层未改变通道数当前通道数为6# 创建第2个卷积层self.conv2 Conv2D(in_channels6, out_channels16, kernel_size5)self.max_pool2 MaxPool2D(kernel_size2, stride2)# 创建第3个卷积层self.conv3 Conv2D(in_channels16, out_channels120, kernel_size4)# 尺寸的逻辑输入层将数据拉平[B,C,H,W] - [B,C*H*W]# 输入size是[28,28]经过三次卷积和两次池化之后C*H*W等于120self.fc1 Linear(in_features120, out_features64)# 创建全连接层第一个全连接层的输出神经元个数为64 第二个全连接层输出神经元个数为分类标签的类别数self.fc2 Linear(in_features64, out_featuresnum_classes)# 网络的前向计算过程def forward(self, x):x self.conv1(x)# 每个卷积层使用Sigmoid激活函数后面跟着一个2x2的池化x F.sigmoid(x)x self.max_pool1(x)x F.sigmoid(x)x self.conv2(x)x self.max_pool2(x)x self.conv3(x)# 尺寸的逻辑输入层将数据拉平[B,C,H,W] - [B,C*H*W]x paddle.reshape(x, [x.shape[0], -1])x self.fc1(x)x F.sigmoid(x)x self.fc2(x)return x
飞桨会根据实际图像数据的尺寸和卷积核参数自动推断中间层数据的W和H等只需要用户表达通道数即可。下面的程序使用随机数作为输入查看经过LeNet-5的每一层作用之后输出数据的形状。
# 输入数据形状是 [N, 1, H, W]
# 这里用np.random创建一个随机数组作为输入数据
x np.random.randn(*[3,1,28,28])
x x.astype(float32)# 创建LeNet类的实例指定模型名称和分类的类别数目
model LeNet(num_classes10)
# 通过调用LeNet从基类继承的sublayers()函数
# 查看LeNet中所包含的子层
print(model.sublayers())
x paddle.to_tensor(x)
for item in model.sublayers():# item是LeNet类中的一个子层# 查看经过子层之后的输出数据形状try:x item(x)except:x paddle.reshape(x, [x.shape[0], -1])x item(x)if len(item.parameters())2:# 查看卷积和全连接层的数据和参数的形状# 其中item.parameters()[0]是权重参数witem.parameters()[1]是偏置参数bprint(item.full_name(), x.shape, item.parameters()[0].shape, item.parameters()[1].shape)else:# 池化层没有参数print(item.full_name(), x.shape)
卷积Conv2D的padding参数默认为0stride参数默认为1当输入形状为[Bx1x28x28]时B是batch_size经过第一层卷积kernel_size5, out_channels6和maxpool之后得到形状为[Bx6x12x12]的特征图经过第二层卷积(kernel_size5, out_channels16)和maxpool之后得到形状为[Bx16x4x4]的特征图经过第三层卷积(out_channels120, kernel_size4)之后得到形状为[Bx120x1x1]的特征图在FC层计算之前将输入特征从卷积得到的四维特征reshape到格式为[B, 120x1x1]的特征这也是LeNet中第一层全连接层输入shape为120的原因。
# -*- coding: utf-8 -*-
# LeNet 识别手写数字
import os
import random
import paddle
import numpy as np
import paddle
from paddle.vision.transforms import ToTensor
from paddle.vision.datasets import MNIST# 定义训练过程
def train(model, opt, train_loader, valid_loader):# 开启0号GPU训练use_gpu Truepaddle.device.set_device(gpu:0) if use_gpu else paddle.device.set_device(cpu)print(start training ... )model.train()for epoch in range(EPOCH_NUM):for batch_id, data in enumerate(train_loader()):img data[0]label data[1] # 计算模型输出logits model(img)# 计算损失函数loss_func paddle.nn.CrossEntropyLoss(reductionnone)loss loss_func(logits, label)avg_loss paddle.mean(loss)if batch_id % 2000 0:print(epoch: {}, batch_id: {}, loss is: {:.4f}.format(epoch, batch_id, float(avg_loss.numpy())))avg_loss.backward()opt.step()opt.clear_grad()model.eval()accuracies []losses []for batch_id, data in enumerate(valid_loader()):img data[0]label data[1] # 计算模型输出logits model(img)pred F.softmax(logits)# 计算损失函数loss_func paddle.nn.CrossEntropyLoss(reductionnone)loss loss_func(logits, label)acc paddle.metric.accuracy(pred, label)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(), mnist.pdparams)# 创建模型
model LeNet(num_classes10)
# 设置迭代轮数
EPOCH_NUM 5
# 设置优化器为Momentum学习率为0.001
opt paddle.optimizer.Momentum(learning_rate0.001, momentum0.9, parametersmodel.parameters())
# 定义数据读取器
train_loader paddle.io.DataLoader(MNIST(modetrain, transformToTensor()), batch_size10, shuffleTrue)
valid_loader paddle.io.DataLoader(MNIST(modetest, transformToTensor()), batch_size10)
# 启动训练过程
train(model, opt, train_loader, valid_loader)
通过运行结果可以看出LeNet在手写数字识别MNIST验证数据集上的准确率高达92%以上。那么对于其它数据集效果如何呢我们通过眼疾识别数据集iChallenge-PM验证一下。 LeNet在眼疾识别数据集iChallenge-PM上的应用
iChallenge-PM是百度大脑和中山大学中山眼科中心联合举办的iChallenge比赛中提供的关于病理性近视Pathologic MyopiaPM的医疗类数据集包含1200个受试者的眼底视网膜图片训练、验证和测试数据集各400张。下面我们详细介绍LeNet在iChallenge-PM上的训练过程。 说明
如今近视已经成为困扰人们健康的一项全球性负担在近视人群中有超过35%的人患有重度近视。近视会拉长眼睛的光轴也可能引起视网膜或者络网膜的病变。随着近视度数的不断加深高度近视有可能引发病理性病变这将会导致以下几种症状视网膜或者络网膜发生退化、视盘区域萎缩、漆裂样纹损害、Fuchs斑等。因此及早发现近视患者眼睛的病变并采取治疗显得非常重要。