精华内容
下载资源
问答
  • LeNet

    2020-06-02 10:13:20
    LeNet

    图像分类

    图像分类是根据图像的语义信息对不同类别图像进行区分,是计算机视觉中重要的基础问题,是物体检测、图像分割、物体跟踪、行为分析、人脸识别等其他高层视觉任务的基础。

    本节使用LeNet和AlexNet解决图像分类问题。

    LeNet:Yan LeCun等人于1998年第一次将卷积神经网络应用到图像分类任务上,在手写数字识别任务中取得了巨大成功。LeNet通过连续使用卷积层和池化层的组合提取图像特征,其构架如图所示,这里展示的是作者论文中的LeNet-5模型。

                                                                          图:LeNet模型网络结构示意图

    • 第一轮卷积和池化:卷积提取图像中包含的特征模式(激活函数使用sigmoid),图像尺寸从32减小到28.经过池化层可以降低输出特征图对空间位置的敏感性,图像尺寸减到14.
    • 第二轮卷积和池化:卷积操作使得图像尺寸减小到10,经过池化后变成5.
    • 第三轮卷积:将经过第3次卷积提取到的特征图输入到全连接层。第一杆全连接层的输出神经元的个数是64,第二个全连接层的输出神经元个数是分类标签的类别数,对于手写数字识别其大小是10.然后使用softmax激活函数即可计算出每个类别的预测概率。

    卷积层的输出特征图的输出数据格式是[N,C,H,W],当输入全连接层时,会自动将数据拉平,也就是对每个样本,自动将其转化为长度为K的向量,其中K=C*H*W.一个mini-batch的数据维度变成了N*K的二维向量。

    LeNet在手写数字识别上的应用

    lenet网络的实现代码如下:

    #导入需要的包
    import paddle
    import paddle.fluid as fluid
    import numpy as np
    from paddle.fluid.dygraph.nn import Conv2D , Pool2D,Linear
    
    #定义LeNet网络结构
    class LeNet(fluid.dygrapy.Layer):
        def __init__(self,name_scope,num_classes=1):
            super(LeNet, self).__init__(name_scope)
    
            #创建卷积和池化层块,每个卷积层使用sigmoid激活函数,后面跟着一个2*2的池化层
            self.conv1 = Conv2D(num_channels=1,num_filters=6, filter_size=5,act='sigmoid')
            self.pool1 = Pool2D(pool_size=2,pool_stride=2, pool_type='max')
            self.conv2 = Conv2D(num_channels=6,num_filters=16, filter_size=5,act='sigmoid')
            self.pool2 = Pool2D(pool_size=2,pool_stride=2, pool_type='max')
            #创建第三个卷积层
            self.conv3 = Conv2D(num_channels=16,num_filters=120,filter_size=4, act='sigmoid')
            #创建全连接层,第一个全连接层的输出神经元个数为64,第二个全连接层输出神经元个数为标签的类别数
             self.fc1 = Linear(input_dim=120, output_dim=64, act='sigmoid')
             self.fc2 = Linear(input_dim=64,output_dim=num_classes)
    
         #网络前向计算过程
         def forward(self ,x):
             x = self.conv1(x)
             x = self.pool1(x)
             x = self.conv2(x)
             x = self.pool2(x)
             x = self.conv3(x)
             x = fluid.layers.reshape(x,[x.shape[0], -1])
             x = self.fc1(x)
             x = self.fc2(x)
             return x

    下面的程序使用随机数作为输入,查看经过LeNet-5的每一层作用之后,输出数据的形状。

    #输入数据形状是[N,1,H,W]
    #这里用np.random创建一个随机数组作为输入数据
    x = np.random.randn(*[3,1,28,28])
    x = x.astype('float32')
    with fluid.dygraph.guard():
        #创建LeNet类的实例,指定模型名称和分类的类别数目
        m = LeNet('LeNet' ,num_classes=10)
        #通过调用LeNet继承的sublayers()函数,查看LeNet中所包含的子层
        print(m.sublayers())
        x = fluid.dygraph.to_varible(x)
        for item in m.sublayers():
            #item是LeNet类中的一个子层,查看经过子层之后的输出数据形状
            try:
                x = item(x)
            except:
                x = fluid.layers.reshape(x,[x.shape[0], -1])
                x = item(x)
            if len(item.parameters())==2:
            #查看卷积和全连接层的数据和参数的形状,其中item.parameters()[0]是权重参数w,item.parameters()[1]是偏置参数b
            print(item.full_name(),x.shape,item.parameters()[0].shape, item.parameters()[1].shape)
            else:
            #池化层没有参数
            print(item.full_name(), x.shape)

    代码结果如下所示:

    接下来就使用LeNet进行手写数字识别

    #LeNet  识别手写数字
    
    import os
    import random
    import paddle
    import paddle.fluid as fluid
    import numpy as np
    
    #定义训练过程
    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())
        #使用paddle自带数据读取器
        train_loader = paddle.batch(paddle.dataset.mnist.train(),batch_size=10)
        valid_loader = paddle.batch(paddle.dataset.mnist.test(),batch_size=10)
        for epoch in range(epoch_num):
            for batch_id ,data in enumerate(train_loader()):
                # 调整输入数据形状和类型
               x_data = np.array([item[0] for item in data], dtype='float32').reshape(-1, 1, 28, 28)
                y_data = np.array([item[1] for item in data], dtype='int64').reshape(-1, 1)
                # 将numpy.ndarray转化成Tensor
                img = fluid.dygraph.to_variable(x_data)
                label = fluid.dygraph.to_variable(y_data)
                # 计算模型输出
                logits = model(img)
                # 计算损失函数
                loss = fluid.layers.softmax_with_cross_entropy(logits, label)
                avg_loss = fluid.layers.mean(loss)
                if batch_id % 1000 == 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 = np.array([item[0] for item in data], dtype='float32').reshape(-1, 1, 28, 28)
                y_data = np.array([item[1] for item in data], dtype='int64').reshape(-1, 1)
                # 将numpy.ndarray转化成Tensor
                img = fluid.dygraph.to_variable(x_data)
                label = fluid.dygraph.to_variable(y_data)
                # 计算模型输出
                logits = model(img)
                pred = fluid.layers.softmax(logits)
                # 计算损失函数
                loss = fluid.layers.softmax_with_cross_entropy(logits, label)
                acc = fluid.layers.accuracy(pred, label)
                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(), 'mnist')
    
    
    if __name__ == '__main__':
        # 创建模型
        with fluid.dygraph.guard():
            model = LeNet("LeNet", num_classes=10)
            #启动训练过程
            train(model)
     
    

    结果如下所示:

    start training ... 
    
    Cache file /home/aistudio/.cache/paddle/dataset/mnist/train-images-idx3-ubyte.gz not found, downloading https://dataset.bj.bcebos.com/mnist/train-images-idx3-ubyte.gz 
    Begin to download
    
    Download finished
    Cache file /home/aistudio/.cache/paddle/dataset/mnist/train-labels-idx1-ubyte.gz not found, downloading https://dataset.bj.bcebos.com/mnist/train-labels-idx1-ubyte.gz 
    Begin to download
    ........
    Download finished
    Cache file /home/aistudio/.cache/paddle/dataset/mnist/t10k-images-idx3-ubyte.gz not found, downloading https://dataset.bj.bcebos.com/mnist/t10k-images-idx3-ubyte.gz 
    Begin to download
    
    Download finished
    Cache file /home/aistudio/.cache/paddle/dataset/mnist/t10k-labels-idx1-ubyte.gz not found, downloading https://dataset.bj.bcebos.com/mnist/t10k-labels-idx1-ubyte.gz 
    Begin to download
    ..
    Download finished
    
    epoch: 0, batch_id: 0, loss is: [2.8019154]
    epoch: 0, batch_id: 1000, loss is: [2.2887921]
    epoch: 0, batch_id: 2000, loss is: [2.3337946]
    epoch: 0, batch_id: 3000, loss is: [2.2778637]
    epoch: 0, batch_id: 4000, loss is: [2.2619343]
    epoch: 0, batch_id: 5000, loss is: [2.3197517]
    [validation] accuracy/loss: 0.3272000253200531/2.2573952674865723
    epoch: 1, batch_id: 0, loss is: [2.2457855]
    epoch: 1, batch_id: 1000, loss is: [2.1932871]
    epoch: 1, batch_id: 2000, loss is: [2.232579]
    epoch: 1, batch_id: 3000, loss is: [1.9601866]
    epoch: 1, batch_id: 4000, loss is: [1.4367704]
    epoch: 1, batch_id: 5000, loss is: [1.6037204]
    [validation] accuracy/loss: 0.7105000019073486/1.0988653898239136
    epoch: 2, batch_id: 0, loss is: [0.9293951]
    epoch: 2, batch_id: 1000, loss is: [0.7314283]
    epoch: 2, batch_id: 2000, loss is: [0.7332459]
    epoch: 2, batch_id: 3000, loss is: [0.48880863]
    epoch: 2, batch_id: 4000, loss is: [0.38987648]
    epoch: 2, batch_id: 5000, loss is: [0.6705998]
    [validation] accuracy/loss: 0.8681000471115112/0.49554571509361267
    epoch: 3, batch_id: 0, loss is: [0.438795]
    epoch: 3, batch_id: 1000, loss is: [0.33228877]
    epoch: 3, batch_id: 2000, loss is: [0.29587844]
    epoch: 3, batch_id: 3000, loss is: [0.15542315]
    epoch: 3, batch_id: 4000, loss is: [0.18254852]
    epoch: 3, batch_id: 5000, loss is: [0.3203889]
    [validation] accuracy/loss: 0.9107999801635742/0.3208836317062378
    epoch: 4, batch_id: 0, loss is: [0.29746038]
    epoch: 4, batch_id: 1000, loss is: [0.24129651]
    epoch: 4, batch_id: 2000, loss is: [0.20082739]
    epoch: 4, batch_id: 3000, loss is: [0.0723183]
    epoch: 4, batch_id: 4000, loss is: [0.11514989]
    epoch: 4, batch_id: 5000, loss is: [0.1840646]
    [validation] accuracy/loss: 0.929099977016449/0.24536828696727753

    通过运行结果可以看出,LeNet在手写数字识别任务中的准确率高达92%以上。下面我们通过眼疾识别数据集iChallenge-PM验证一下。LeNet在手写数字识别方面效果好是否在其他数据集上效果也优。

    AlexNet:Alex Krizhevsky等人在2012年提出了AlexNet,并应用在大尺度数据集ImageNet上,并获得比赛冠军。

    LeNet在眼疾识别数据集iChallenge-PM上的应用:

    iChallenge-PM数据集包含1200个受试者的眼底视网膜图片,训练、验证和测试数据集各400张。将病理性患者的图片作为正样本,标签为1;非病理患者的图片作为负样本,标签为0.。

    • training.zip:包含训练中的图片和标签
    • validation.zip:包含验证集的图片
    • valid_gz.zip:包含验证集的标签
    #解压数据集
    !unzip -o -q -d /home/aistudio/work/palm /home/aistudio/data/data19065/training.zip
    %cd /home/aistudio/work/palm/PALM-Training400/
    !unzip -o -q PALM-Training400.zip
    !unzip -o -q -d /home/aistudio/work/palm /home/aistudio/data/data19065/validation.zip
    !unzip -o -q -d /home/aistudio/work/palm /home/aistudio/data/data19065/valid_gt.zip

    从数据集中选取两张图片,通过LeNet提取特征,构建分类器,对正负样本进行分类,并将图片显示出来

    import os
    import numpy as np
    import matplotlib.pyplot as plt
    %matplotlib inline
    from PIL import Image
    
    DATADIR = '/home/aistudio/work/palm/PALM-Training400/PALM-Training400'
    # 文件名以N开头的是正常眼底图片,以P开头的是病变眼底图片
    file1 = 'N0012.jpg'
    file2 = 'P0095.jpg'
    
    #读取图片
    img1 = Image.open(os.path.join(DATADIR, file1))
    img1 = np.array(img1)
    img2 = Image.open(os.path.join(DATADIR,file2))
    img2 = np.array(img2)
    
    #画出读取图片
    plt.figure(figsize=(16, 8))
    f = plt.subplot(121)
    f.set_title('Normal', fontsize=20)
    plt.imshow(img1)
    f = plt.subplot(122)
    f.set_title('PM', fontsize=20)
    plt.imshow(img2)
    plt.show()

    #查看图片形状
    img1.shape, img2.shape
    

    代码结果:

     

    ((2056, 2124, 3), (2056, 2124, 3))

    定义数据读取器:

    将读取的图片每张缩放到224*224大小,并且将像素值调整到【-1,1】之间,代码如下所示:

    import  cv2
    import random
    import numpy as np
    
    #对读入的图像数据进行预处理
    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))
        img = img.astype('float32')
        #将数据范围调整到[-1.0,1.0]之间
        img = img / 225.
        img = img * 2.0 -1.0
        return img
    
    #定义训练集数据读取器
    def data_loader(datadir, batch_size=10,mode = 'train')
        # 将datadir目录下的文件列出来,每条文件都要读入
        filenames = os.listdir(datadir)
        def reader():
            if mode =='train':
               #训练时随机打乱数据顺序
               random.shuffle(filenames)
            batch_imgs = []
            batch_labels = []
            for name in filenames:
                filepath = os.path.join(fatadir, 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 imgs_array, labels_array
                    batch_imgs = []
                    batch_labels = []
    
            if len(batch_imgs) > 0:
                # 剩余样本数目不足一个batch_size的数据,一起打包成一个mini-batch
                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'):
      #训练集读取时通过文件名来确定样本标签,验证集则通过csvfile来读取每个图片对应的标签。
      #打开包含验证集标签的csvfile,并读取其中的内容
      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:
                    # 当数据列表的长度等于batch_size的时候,
                    # 把这些数据当作一个mini-batch,并作为数据生成器的一个输出
                    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:
                # 剩余样本数目不足一个batch_size的数据,一起打包成一个mini-batch
                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 = '/home/aistudio/work/palm/PALM-Training400/PALM-Training400'
    train_loader = data_loader(DATADIR,batch_size=10,mode='train')
    data_reader = train_loader()
    data = next(data_reader)
    data[0].shape,data[1].shape
    

    代码结果如图所示‘

    启动训练:

    #LeNet 识别眼疾图片
    
    import os
    import random
    import paddle
    import paddle.fluid as fluid
    import numpy as np
    
    #DATADIR是训练数据集的地址,DATADIR2是验证数据集的地址,CSVFILE是验证集的标签
    DATADIR = '/home/aistudio/work/palm/PALM-Training400/PALM-Training400'
    DATADIR2 = '/home/aistudio/work/palm/PALM-Validation400'
    CSVFILE = '/home/aistudio/work/palm/PALM-Validation-GT/labels.csv'
    
    #定义训练过程
    def train(model):
        with fluid.dygraph.guard():
            print('start training ... ')
            model,train()
            epoch_num= 5
            #定义优化器
            opt = fluid.optimizer.Momentum(learning_rate=0.001,momentum=0.9,parameter_list=mode.parameters())
            #定义数据读取器,训练数据读取器和验证数据读取器
            train_loader = data_loader(DATADIR,batch_size=10,mode='train')
            valid_loader = valid_data_loader(DATADIR2, CSVFILE)
            for epoch in range(epoch_num):
                 for batch_id, data in enumerate(train_loader()):
                 x_data,y_data = data
                 img = fluid.dygraph.to_variable(x_data)
                 label = fluid.dygraph.to_variable(y_data)
                 #运行模型前向计算,得到预测值
                 logits = model(img)
                 #进行loss计算
                 loss = fluid.layers.sigmoid_cross_entropy_with_logits(logits ,label)
                 avg_loss = fluid.layers.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)
                 mode.clear_gradients()
    
              model.eval()
              accuracies = []
              losses = []
              for batch_id, data in enumerate(valid_loader()):
                  x_data,y_data = data
                  img = fluid.dygraph.to_variable(x_data)
                  label = fluid.dygraph.to_variable(y_data)
              #运行模型前向计算,得到预测值
              logits = model(img)
              #二分类,sogmoid计算后的结果以0.5为阈值分两个类别
              #计算sigmoid后的预测概率,进行loss计算
              pred = fluid.layers.sigmoid(logits)
              loss = fluid.layers.sigmoid_cross_entropy_with_logits(logits, label)
              # 计算预测概率小于0.5的类别
              pred2 = pred * (-1.0) + 1.0
              # 得到两个类别的预测概率,并沿第一个维度级联
                    pred = fluid.layers.concat([pred2, pred], axis=1)
                    acc = fluid.layers.accuracy(pred, fluid.layers.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()
    
              #save params of model
              fluid.save_dygraph(model.state_dict(),'mnist')
              #save optimizer state
              fluid.save_dygraph(opt.state_dict(),'mnist')
    #定义评估过程
    def evaluation(model, params_file_path):
        with fluid.dygraph.guard():
            print('start evaluation ......')
            #加载模型参数
            model_state_dict, __= fluid.load_dygraph(params_file_path)
            model.load_dict(model_state_dict)
    
            model.eval()
             eval_loader = load_data('eval')
    
            acc_set = []
            avg_loss_set = []
            for batch_id, data in enumerate(eval_loader()):
                x_data, y_data = data
                img = fluid.dygraph.to_variable(x_data)
                label = fluid.dygraph.to_variable(y_data)
                # 计算预测和精度
                prediction, acc = model(img, label)
                # 计算损失函数值
                loss = fluid.layers.cross_entropy(input=prediction, label=label)
                avg_loss = fluid.layers.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={}, acc={}'.format(avg_loss_val_mean, acc_val_mean))
    
    #导入需要的包
    import paddle 
    import paddle.fluid as fluid
    import numpy as np
    from paddle.fluid.dygraph.nn import Conv2D,Pool2D,Linear
    
    # 定义 LeNet 网络结构
    class LeNet(fluid.dygraph.Layer):
        def __init__(self, name_scope, num_classes=1):
            super(LeNet, self).__init__(name_scope)
    
            # 创建卷积和池化层块,每个卷积层使用Sigmoid激活函数,后面跟着一个2x2的池化
            self.conv1 = Conv2D(num_channels=3, num_filters=6, filter_size=5, act='sigmoid')
            self.pool1 = Pool2D(pool_size=2, pool_stride=2, pool_type='max')
            self.conv2 = Conv2D(num_channels=6, num_filters=16, filter_size=5, act='sigmoid')
            self.pool2 = Pool2D(pool_size=2, pool_stride=2, pool_type='max')
            # 创建第3个卷积层
            self.conv3 = Conv2D(num_channels=16, num_filters=120, filter_size=4, act='sigmoid')
            # 创建全连接层,第一个全连接层的输出神经元个数为64, 第二个全连接层输出神经元个数为分裂标签的类别数
            self.fc1 = Linear(input_dim=300000, output_dim=64, act='sigmoid')
            self.fc2 = Linear(input_dim=64, output_dim=num_classes)
        # 网络的前向计算过程
        def forward(self, x):
            x = self.conv1(x)
            x = self.pool1(x)
            x = self.conv2(x)
            x = self.pool2(x)
            x = self.conv3(x)
            x = fluid.layers.reshape(x, [x.shape[0], -1])
            x = self.fc1(x)
            x = self.fc2(x)
            return x
    
    if __name__ == '__main__':
        # 创建模型
        with fluid.dygraph.guard():
            model = LeNet("LeNet_", num_classes=1)
    
        train(model)

    代码结果如下所示:

    start training ... 
    epoch: 0, batch_id: 0, loss is: [0.7495805]
    epoch: 0, batch_id: 10, loss is: [1.636447]
    epoch: 0, batch_id: 20, loss is: [0.723161]
    epoch: 0, batch_id: 30, loss is: [0.71356595]
    [validation] accuracy/loss: 0.5275000333786011/0.6923364400863647
    epoch: 1, batch_id: 0, loss is: [0.6789056]
    epoch: 1, batch_id: 10, loss is: [0.66355455]
    epoch: 1, batch_id: 20, loss is: [0.6578954]
    epoch: 1, batch_id: 30, loss is: [0.65324485]
    [validation] accuracy/loss: 0.5275000333786011/0.6920405626296997
    epoch: 2, batch_id: 0, loss is: [0.68819726]
    epoch: 2, batch_id: 10, loss is: [0.6819553]
    epoch: 2, batch_id: 20, loss is: [0.7818572]
    epoch: 2, batch_id: 30, loss is: [0.70672405]
    [validation] accuracy/loss: 0.5275000333786011/0.6923947334289551
    epoch: 3, batch_id: 0, loss is: [0.69647765]
    epoch: 3, batch_id: 10, loss is: [0.6738097]
    epoch: 3, batch_id: 20, loss is: [0.6926111]
    epoch: 3, batch_id: 30, loss is: [0.714018]
    [validation] accuracy/loss: 0.5275000333786011/0.6918395161628723
    epoch: 4, batch_id: 0, loss is: [0.67984945]
    epoch: 4, batch_id: 10, loss is: [0.6825234]
    epoch: 4, batch_id: 20, loss is: [0.69415]
    epoch: 4, batch_id: 30, loss is: [0.6940319]
    [validation] accuracy/loss: 0.5275000333786011/0.698182225227356

    通过运行结果可以看出,在眼疾筛查数据集上,LeNet的loss很难下降,模型没有收敛。这是因为MNIST数据集的图片尺寸较小(28*28),但在眼疾数据集上尺寸较大(原始尺寸约为2000*2000,经过缩放之后变成224*224),LeNet模型很难进行有效分类。这说明在图片尺寸较大时,LeNet在图像分类任务上存在局限性。

    展开全文
  • LeNet神经网络

    千次阅读 2017-03-16 18:04:00
    LeNet神经网络

    文章作者:Tyan
    博客:noahsnail.com  |  CSDN  |  简书

    1. LeNet神经网络介绍

    LeNet神经网络由深度学习三巨头之一的Yan LeCun提出,他同时也是卷积神经网络 (CNN,Convolutional Neural Networks)之父。LeNet主要用来进行手写字符的识别与分类,并在美国的银行中投入了使用。LeNet的实现确立了CNN的结构,现在神经网络中的许多内容在LeNet的网络结构中都能看到,例如卷积层,Pooling层,ReLU层。虽然LeNet早在20世纪90年代就已经提出了,但由于当时缺乏大规模的训练数据,计算机硬件的性能也较低,因此LeNet神经网络在处理复杂问题时效果并不理想。虽然LeNet网络结构比较简单,但是刚好适合神经网络的入门学习。

    2. LeNet神经网络结构

    LeNet的神经网络结构图如下:

    LeNet网络图

    LeNet网络的执行流程图如下:

    LeNet图像处理流程

    2.1 LeNet第一层(卷积运算)

    接下来我们来具体的一层层的分析LeNet的网络结构。首先要了解图像(输入数据)的表示。在LeNet网络中,输入图像是手写字符,图像的表示形式为二维数据矩阵,如下图所示:

    图像的表示

    LeNet网络除去输入输出层总共有六层网络。第一层是卷积层(C1层),卷积核的大小为5\*5,卷积核数量为6个,输入图像的大小为32*32,因此输入数据在进行第一层卷积之后,输出结果为大小为28*28,数量为6个的feature map。卷积操作如下面两幅图所示:

    卷积演示

    卷积演示

    卷积操作的过程可描述为:卷积核在图像上滑动,滑动步长为1(即每次移动一格,水平方向从左到右,到最右边之后再从最左边开始,向下移动一格,重复从左到右滑动),当卷积核与图像的一个局部块重合时进行卷积运行,卷积计算方式为图像块对应位置的数与卷积核对应位置的数相乘,然后将所有相乘结果相加即为feature map的值,相乘累加之后的结果位于卷积核中心点的位置,因此如果是3\*3的卷积核,feature map比原图像在水平和垂直方向上分别减少两行(上下各一行)和两列(左右各一列),因此上面图像原图为5*5,卷积核为3\*3,卷积结果大小为3*3,即(5-2)*(5-2),如果卷积核为5*5,则卷积结果大小为(5-4)*(5-4)。上图中的卷积核为:
    卷积核

    由于神经网络层与层的结构是通过连接来实现的,因此输入层与第一个卷积层的连接数量应为(32-2-2)\*(32-2-2)\*(5\*5+1)\*6= 28\*28\*156 =122304

    卷积的作用主要是:通过卷积运算,可以使原信号特征增强,并且降低噪音。在图像上卷积之后主要是减少图像噪声,提取图像的特征。例如sobel算子就是一种卷积运算,主要是提取图像的边缘特征。卷积网络能很好地适应图像的平移不变性:例如稍稍移动一幅猫的图像,它仍然是一幅猫的图像。卷积操作保留了图像块之间的空间信息,进行卷积操作的图像块之间的相对位置关系没有改变。图像在不同卷积核上进行卷积之后的效果图如下:

    同一幅图像用不同卷积核处理的效果

    2.2 LeNet第二层(pooling运算)

    图像在LeNet网络上进行第一层卷积之后,结果为大小为28*28,数量为6个的feature map。LeNet网络的第二层为pooling层(S2层),也称为下采样。在图像处理中,下采样之后,图像的大小会变为原来的1/4,即水平方向和垂直方向上图像大小分别减半。Pooling有多种,这里主要介绍两种,max-pooling和average-pooling。max-pooling即为从四个元素中选取一个最大的来表示这四个元素,average-pooling则用四个元素的平均值来表示这四个元素。Pooling示意图如下:

    Pooling示意图

    Pooling示意图

    在LeNet在进行第二层Pooling运算后,输出结果为14*146个feature map。其连接数为(2*2+1) * 14 * 14 *6 = 5880。Pooling层的主要作用就是减少数据,降低数据纬度的同时保留最重要的信息。在数据减少后,可以减少神经网络的纬度和计算量,可以防止参数太多过拟合。LeNet在这一层是将四个元素相加,然后乘以参数w再加上偏置b,然后计算sigmoid值。

    2.3 LeNet第三层(卷积运算)

    LeNet第三层(C3层)也是卷积层,卷积核大小仍为5*5,不过卷积核的数量变为16个。第三层的输入为14*146个feature map,卷积核大小为5*5,因此卷积之后输出的feature map大小为10*10,由于卷积核有16个,因此希望输出的feature map也为16个,但由于输入有6个feature map,因此需要进行额外的处理。输入的6个feature map与输出的16个feature map的关系图如下:

    S2层与C3层的关系图

    如上图所示,第一个卷积核处理前三幅输入的feature map,得出一个新的feature map。

    2.4 LeNet第四层(Pooling运算)

    上一层卷积运算之后,结果为大小为10*1016个feature map,因此在第四层(S4层)进行pooling运算之后,输出结果为16个大小为5*5的feature map。与S2层进行同样的操作。

    2.5 LeNet第五层

    LeNet第五层是卷积层(C5层),卷积核数目为120个,大小为5*5,由于第四层输出的feature map大小为5*5,因此第五层也可以看成全连接层,输出为120个大小为1*1的feature map。

    2.6 LeNet第六层

    LeNet第六层是全连接层(F6层),有84个神经元(84与输出层的设计有关),与C5层全连接。

    2.7 LeNet各层的参数变化

    • C1
      输入大小:32*32
      核大小:5*5
      核数目:6
      输出大小:28*28*6
      训练参数数目:(5*5+1)*6=156
      连接数:(5*5+1)*6*(32-2-2)*(32-2-2)=122304

    • S2
      输入大小:28*28*6
      核大小:2*2
      核数目:1
      输出大小:14*14*6
      训练参数数目:2*6=12,2=(w,b)
      连接数:(2*2+1)*1*14*14*6 = 5880

    • C3
      输入大小:14*14*6
      核大小:5*5
      核数目:16
      输出大小:10*10*16
      训练参数数目:6*(3*5*5+1) + 6*(4*5*5+1) + 3*(4*5*5+1) + 1*(6*5*5+1)=1516
      连接数:(6*(3*5*5+1) + 6*(4*5*5+1) + 3*(4*5*5+1) + 1*(6*5*5+1))*10*10=151600

    • S4
      输入大小:10*10*16
      核大小:2*2
      核数目:1
      输出大小:5*5*16
      训练参数数目:2*16=32
      连接数:(2*2+1)*1*5*5*16=2000

    • C5
      输入大小:5*5*16
      核大小:5*5
      核数目:120
      输出大小:120*1*1
      训练参数数目:(5*5*16+1)*120*1*1=48120(因为是全连接)
      连接数:(5*5*16+1)*120*1*1=48120

    • F6
      输入大小:120
      输出大小:84
      训练参数数目:(120+1)*84=10164
      连接数:(120+1)*84=10164

    3. LeNet在Caffe中的配置

    LeNet神经网络结构在Caffe中的配置文件如下:

    name: "LeNet" //神经网络名字
    //本层只有top,没有bottom,说明是数据输入层
    layer {
      name: "mnist" //layer名字
      type: "Data" //层的数据类型,如果是Data,说明是leveldb或lmdb
      top: "data" //top表示输入数据,类型为data
      top: "label" //top表示输入数据,类型为label,(data,label)配对是分类模型所必需的
      //一般训练的时候和测试的时候,模型的层是不一样的。该层(layer)是属于训练阶段的层,还是属于测试阶段的层,需要用include来指定。如果没有include参数,则表示该层既在训练模型中,又在测试模型中。
      include {
        phase: TRAIN
      }
      //数据的预处理,可以将数据变换到定义的范围内。如设置scale为0.00390625,实际上就是1/255, 即将输入数据由0-255归一化到0-1之间
      transform_param {
        scale: 0.00390625
      }
      data_param {
        source: "examples/mnist/mnist_train_lmdb"
        batch_size: 64
        backend: LMDB
      }
    }
    layer {
      name: "mnist"
      type: "Data"
      top: "data"
      top: "label"
      include {
        phase: TEST
      }
      transform_param {
        scale: 0.00390625
      }
      data_param {
        source: "examples/mnist/mnist_test_lmdb"
        batch_size: 100
        backend: LMDB
      }
    }
    layer {
      name: "conv1"
      type: "Convolution"
      bottom: "data"
      top: "conv1"
      param {
        lr_mult: 1
      }
      param {
        lr_mult: 2
      }
      convolution_param {
        num_output: 20
        kernel_size: 5
        stride: 1
        weight_filler {
          type: "xavier"
        }
        bias_filler {
          type: "constant"
        }
      }
    }
    layer {
      name: "pool1"
      type: "Pooling"
      bottom: "conv1"
      top: "pool1"
      pooling_param {
        pool: MAX
        kernel_size: 2
        stride: 2
      }
    }
    layer {
      name: "conv2"
      type: "Convolution"
      bottom: "pool1"
      top: "conv2"
      param {
        lr_mult: 1
      }
      param {
        lr_mult: 2
      }
      convolution_param {
        num_output: 50
        kernel_size: 5
        stride: 1
        weight_filler {
          type: "xavier"
        }
        bias_filler {
          type: "constant"
        }
      }
    }
    layer {
      name: "pool2"
      type: "Pooling"
      bottom: "conv2"
      top: "pool2"
      pooling_param {
        pool: MAX
        kernel_size: 2
        stride: 2
      }
    }
    layer {
      name: "ip1"
      type: "InnerProduct"
      bottom: "pool2"
      top: "ip1"
      param {
        lr_mult: 1
      }
      param {
        lr_mult: 2
      }
      inner_product_param {
        num_output: 500
        weight_filler {
          type: "xavier"
        }
        bias_filler {
          type: "constant"
        }
      }
    }
    layer {
      name: "relu1"
      type: "ReLU"
      bottom: "ip1"
      top: "ip1"
    }
    layer {
      name: "ip2"
      type: "InnerProduct"
      bottom: "ip1"
      top: "ip2"
      param {
        lr_mult: 1
      }
      param {
        lr_mult: 2
      }
      inner_product_param {
        num_output: 10
        weight_filler {
          type: "xavier"
        }
        bias_filler {
          type: "constant"
        }
      }
    }
    layer {
      name: "accuracy"
      type: "Accuracy"
      bottom: "ip2"
      bottom: "label"
      top: "accuracy"
      include {
        phase: TEST
      }
    }
    layer {
      name: "loss"
      type: "SoftmaxWithLoss"
      bottom: "ip2"
      bottom: "label"
      top: "loss"
    }

    参考资料:

    1.https://ujjwalkarn.me/2016/08/11/intuitive-explanation-convnets/

    展开全文
  • lenet阅读

    2018-11-13 17:13:14
    lenet 只有简单的八层,...第二层C1 是卷积层,每个图像用了 6 个shape=(5,5)的卷积核进行特征提取,方式是VALID(可能是提出时间早,SAME方式没有普及),形成feature map.shape = (28,28,6) 第三层S2 池化层,ou...

    lenet 只有简单的八层,结构简单,所以我们可以一层一层的进行分析。
    在这里插入图片描述
    第一层IN 是输入层(归一化),输入图像被resize成(32, 32),没有特殊的操作。

    第二层C1 是卷积层,每个图像用了 6 个shape=(5,5)的卷积核进行特征提取,方式是VALID(可能是提出时间早,SAME方式没有普及),形成feature map.shape = (28,28,6)

    第三层S2 池化层,output.shape = (14,14,6)

    第四层C3 卷积层,这一层的卷积为减小参数数量同时达到更好的泛化效果,用了16个卷积核和四种卷积方式:对池化层输出的六层map进行编码,每个卷积核作用的对象都不一样,C3的前6个特征图以S2中3个相邻的特征图子集为输入。接下来6个特征图以S2中4个相邻特征图子集为输入。然后的3个以不相邻的4个特征图子集为输入。最后一个将S2中所有特征图为输入。
    在这里插入图片描述
    生成了featuremap.shape = (10,10,16)

    第五层S4 和S2相似,outputmap = (5,5,16)

    第六层FC5 这一层把S4的output进行了全连接,输出shape = (84,),意在对应shape为(7,12)的ask i i码图
    在这里插入图片描述

    第七层FC6 对FC5的输出再一次进行全连接,输出shape = (10,)。这一层的意图就是实现one—cold的分类。

    第八层OUT 输出结果

    总结:lenet是cnn网络的开山之作
    卷积充分利用了不同尺度的特征图,同时减少了参数
    使用sigmoid进行整形

    展开全文
  • LeNet网络模型

    千次阅读 2017-09-06 22:14:20
      LeNet模型是一种用来识别手写数字的最经典的卷积神经网络,他是Yann LeCun在1998年设计并提出的。当年美国大多数银行就是用它来识别支票上面的手写数字的。它的识别准确性非常高。   LeNet的网络模型框架如下...

    一、LeNet模型简介
      LeNet模型是一种用来识别手写数字的最经典的卷积神经网络,他是Yann LeCun在1998年设计并提出的。当年美国大多数银行就是用它来识别支票上面的手写数字的。它的识别准确性非常高。
      LeNet的网络模型框架如下图所示:

    这里写图片描述

      下面对网络模型的每一层进行分析。

    二、LeNet模型网络层详解
      LeNet-5包含输入共有8层,每层都包含可训练参数(连接权重)。
      第一层:输入层。输入图像的尺寸为32*32。这要比Mnist数据库(caffe中的输入尺寸为28*28)中最大的字母还大。这样做的原因是希望潜在的明显特征,比如笔画断续、角点能够出现在最高层特征监测子感受野的中心。
      第二层:C1卷积层。它是第一个卷积层,它由6个特征图Feature Map构成,5*5大小的卷积核。而特征图中每个神经元与输入中5*5的邻域相连。特征图的大小为28*28(32-5+1=28),所以每个特征图上有28*28个神经元。C1有156个可训练参数(每个滤波器5*5=25个unit参数和一个bias参数,一共6个滤波器,共(5*5+1)*6=156个参数),共156(28*28)=122,304个连接。(最后顺便说一下为什么要进行卷积?卷积运算一个重要的特点就是,通过卷积运算,可以使原信号特征增强,并且降低噪音,同时不同的卷积层可以提取到图像中的不同特征,这层卷积我们就是用了6个卷积核)
      第三层:S2层是一个下采样层,有6个14*14的特征图。特征图中的每个单元与C1中相对应特征图的2*2邻域相连接。S2层每个单元的4个输入相加,乘以一个可训练参数,再加上一个可训练偏置,结果通过sigmoid函数计算而得。每个单元的2*2感受野并不重叠,因此S2中每个特征图的大小是C1中特征图大小的1/4(行和列各1/2),所以S2中每一个特征图都有14*14个神经元。S2层有12个可训练参数(2*6=12,2代表一个可训练参数和一个可训练偏置)和5880个连接,计算过程如下:(4+1)*(14*14)*6=5880。(说明下为什么要进行下采样?利用图像局部相关性的原理,对图像进行子抽样,可以减少数据处理量同时保留有用信息,从而降低了网络训练的参数和模型的过拟合程度)。
      一般神经网络常采用最大池化或平均池化。子采样具体过程如下:每邻域四个像素求和变为一个像素,然后通过标量Wx+1加权,再增加偏置bx+1,然后通过一个sigmoid激活函数,产生一个大概缩小四倍的特征映射图Sx+1。在整个网络中,S-层可看作是模糊滤波器,起到二次特征提取的作用。隐层与隐层之间空间分辨率递减,而每层所含的平面数递增,这样可用于检测更多的特征信息。
      第四层:C3层是第二个卷积层。它同样通过5x5的卷积核去卷积层S2,然后得到的特征map就只有10x10个神经元,但是它有16种不同的卷积核,所以就存在16个特征map了。这里需要注意的一点是:C3中的每个特征map是连接到S2中的所有6个或者几个特征map的,表示本层的特征map是上一层提取到的特征map的不同组合(这里是组合,就像人的视觉系统一样,底层的结构构成上层更抽象的结构,例如边缘构成形状或者目标的部分)。
      在Yann的论文中说明了C3中每个特征图与S2中哪些特征图相连,连接情况如下表所示:

    这里写图片描述

      由上表可以发现C3的前6个特征图以S2中3个相邻的特征图为输入。接下来6个特征图以S2中4个相邻特征图为输入,下面的3个特征图以不相邻的4个特征图为输入。最后一个特征图以S2中所有特征图为输入。这样C3层有1516个可训练参数((25*3+1)*6+(25*4+1)*9+(25*6+1)=1516)和151600(1516*10*10)个连接。
      那么为什么不把S2中的每个特征图连接到每个C3的特征图呢?原因有2点。第一,不完全的连接机制将连接的数量保持在合理的范围内。第二,也是最重要的,其破坏了网络的对称性。由于不同的特征图有不同的输入,所以迫使他们抽取不同的特征(希望是互补的)。
      第五层:S4层是一个下采样层,由16个5*5大小的特征图构成。特征图中的每个单元与C3中相应特征图的2*2邻域相连接,跟C1和S2之间的连接一样。S4层有32(2*16)个可训练参数(每个特征图1个因子和一个偏置)和2000个连接。
      第六层:C5层是一个卷积层,有120个特征图。每个单元与S4层的全部16个特征图的5*5领域相连。由于S4层特征图的大小也为5*5(同滤波器一样),故C5特征图的大小为1*1,这构成了S4和C5之间的全连接。之所以仍将C5标示为卷积层而非全连接层,是因为如果LeNet-5的输入变大,而其他的保持不变,那么此时特征图的维数就会比1*1大。C5层有48120个可训练连接((5*5*16+1)*120)。
      第七层:F6层有84个单元(之所以选这个数字的原因来自于输出层的设计),与C5层全相连。有10164个可训练参数((1*1*120+1)*84=10164)。如同经典神经网络,F6层计算输入向量和权重向量之间的点积,再加上一个偏置。然后将其传递给sigmoid函数产生单元i的一个状态。
    第八层:输出层由欧式径向基函数(Euclidean Radial Basis Function)单元组成,每类一个单元,每个有84个输入。换句话说,每个输出RBF单元计算输入向量和参数向量之间的欧式距离。输入离参数向量越远,RBF输出的越大。一个RBF输出可以被理解为衡量输入模式和与RBF相关联类的一个模型的匹配程度的惩罚项。用概率术语来说,RBF输出可以被理解为F6层配置空间的高斯分布的负log-likelihood。给定一个输入模式,损失函数应能使得F6的配置与RBF参数向量(即模式的期望分类)足够接近。这些单元的参数是人工选取并保持固定的(至少初始时候如此)。这些参数向量的成分被设为-1或1。虽然这些参数可以以-1和1等概率的方式任选,或者构成一个纠错码,但是被设计成一个相应字符类的7*12大小(即84)的格式化图片。这种表示对识别单独的数字不是很有用,但是对识别可打印ASCII集中的字符串很有用。
      使用这种分布编码而非更常用的“1 of N”编码用于产生输出的另一个原因是,当类别比较大的时候,非分布编码的效果比较差。原因是大多数时间非分布编码的输出必须为0。这使得用sigmoid单元很难实现。另一个原因是分类器不仅用于识别字母,也用于拒绝非字母。使用分布编码的RBF更适合该目标。因为与sigmoid不同,他们在输入空间的较好限制的区域内兴奋,而非典型模式更容易落到外边。
      RBF参数向量起着F6层目标向量的角色。需要指出这些向量的成分是+1或-1,这正好在F6 sigmoid的范围内,因此可以防止sigmoid函数饱和。实际上,+1和-1是sigmoid函数的最大弯曲的点处。这使得F6单元运行在最大非线性范围内。必须避免sigmoid函数的饱和,因为这将会导致损失函数较慢的收敛和病态问题。

    展开全文
  • CNN与LeNet

    2018-12-29 14:45:37
    LeNet论文翻译 2 用于字符识别的卷积神经网络 A 卷积网络 B LeNet-5 LeNet论文解读 神经元模型 从传统神经网络到CNN 连接数和参数个数的计算 特征图连接方式 结束语 相关资料 下面列出的论文都是我学习CNN...
  • LeNet由来及意义

    千次阅读 2019-11-06 11:05:52
    LeNet-5是Yann LeCun等人在多次研究后提出的最终卷积神经网络结构,一般LeNet即指代LeNet-5。 LeNet-5包含七层,不包括输入,每一层都包含可训练参数(权重),当时使用的输入数据是32*32像素的图像。下面逐层介绍...
  • MATLAB版本的Lenet理解

    2019-09-06 14:07:44
    最近看了各大博客关于lenet的讲解,最终发现还是下载MATLAB源码自己看理解最直观,花了3天时间捋清了lenet的训练方式,仅供参考。 MATLAB版本lenet下载链接 1. 简介 LeNet是Yan LeCun提出的一种用于识别手写体数字的...
  • 1.2 LeNet-5

    2019-08-18 16:41:48
    目录二、LeNet-51、CNN 的起源与发展2、LeNet-52.1 背景2.2 架构总体思想2.3、网络架构分解2.4、LeNet-5 改进 二、LeNet-5 1、CNN 的起源与发展 在上一章,通过对 NeoCognitron 的简单介绍,我们知道,S 细胞的主要...
  • 经典模型之Lenet

    2017-12-14 08:15:51
    经典模型之Lenet模型背景1985年,Rumelhart和Hinton等人提出了后向传播(BackPropagation,BP)算法[1](也有说1986年的,指的是他们另一篇paper:Learningrepresentations by back-propagating errors),使得神经...
  • lenet-5

    2019-04-09 10:55:00
    深度学习 CNN卷积神经网络 LeNet-5详解 2017年10月18日 16:04:35happyorg阅读数:28621 卷积神经网络( Convolutional Neural Network, CNN):是一种常见的...
  • 由于 LeNet-5 提出时间比较早,其网络中使用的一些技术在现在已经很少使用,因此现在我们所使用的 LeNet-5 与原始论文的有所不同。 LeNet-5 的结构图 CiC_iCi​:卷积层;SiS_iSi​:下采样层(池化层);FiF_iFi...
  • LeNet到AlexNet

    2016-10-19 21:20:35
    【卷积神经网络-进化史】从LeNet到AlexNet
  • LeNet-5[LeCun et al., 1998] 虽然提出时间比较早,但是是一个非常成功的神经网络模型。基于LeNet-5的手写数字识别系统在90年代被美国很多银行使用,用来识别支票上面的手写数字体。LeNet-5的网络结构图如图: ...
  • 卷积神经网络之LeNet

    2019-11-17 18:51:09
    目录 一、LeNet的贡献 二、LeNet网络结构 1、各层参数详解 (1)INPUT层-输入层 (2)C1层-卷积层 (3)、S2层-池化层(下采样层) ...三、LeNet论文 ...1、论文提出 2、但是将像素独自的输入到神经元...
  • LeNet是卷积神经网络的祖师爷LeCun在1998年提出,用于解决手写数字识别的视觉任务。自那时起,CNN的最基本的架构就定下来了:卷积层、池化层、全连接层。如今各大深度学习框架中所使用的LeNet都是简化改进过的LeNet-...
  • LeNet-5模型浅析

    千次阅读 2019-05-21 20:24:16
    写在前面的话:文章内容来源于但不限于网络、书籍、个人心得体会等,意在总结和方便各位同行快速参考,共同学习进步,记录自己的问题。...LeNet是LeCun在1989年提出的网络结构,是卷积神经网络(C...
  • Tensorflow2.0之LeNet-5实战

    千次阅读 2020-02-18 22:13:24
    1990 年代,Yann LeCun 等人提出了用于手写数字和机器打印字符图片识别的神经网络,被命名为LeNet-5 [4]。LeNet-5 的提出,使得卷积神经网络在当时能够成功被商用,广泛应用在邮政编码、支票号码识别等任务中。下图 ...
  • 本文建议阅读时间 10 min前言Lenet 是一系列网络的合称,包括 Lenet1 - Lenet5,由 Yann LeCun 等人在 1990 年《Handwritten Digit...
  • 学习笔记(1)LeNet-5

    2020-12-24 19:32:46
    学习笔记(1)LeNet-5 ...LeNet-5[LeCun et al.,1998]虽然提出时间比较早,但它是一个非常成功的神经网络模型。论文Gradient-Based Learning Applied to Document Recognition。基于LeNet-5的手写数字识别
  • 网络结构1——LeNet

    2021-01-18 19:38:18
    网络结构1——LeNet 参考文章:gradient- based learning applied to document recognition LeNet-5算法应用于手写数字识别问题 创新点 卷积神经网络专门设计用来处理二维形状变化,表现优于其他所有技术。利用...
  • lenet背景介绍lenet原理1.lenet基本结构2.主要操作流程 写在内容之前(很重要!!!) 为了读者能更好的了解本篇内容,提出以下诚恳建议。 本篇博文内容涉及到卷积神经网络的一些基础知识,卷积的知识,一些很...
  • LeNet-5详解

    千次阅读 2018-04-13 23:34:52
    在imagenet上的图像分类challenge上大神Alex提出的alexnet网络结构模型赢得了2012届的冠军,振奋人心,利用CNN实现了图片分类,别人用传统的机器学习算法调参跳到半死也就那样, Alex利用CNN精度远超传统的网络。 ...
  • 进入正文一、LeNet网络简介LeNet网络简介LeNet网络的背景1.1闪光点:定义了CNN的基本组件,是CNN的鼻祖。LeNet是卷积神经网络的祖师爷LeCun在19...
  • 深度学习(9): LeNet-5 网络模型小结

    千次阅读 2019-08-22 14:34:36
    文章目录1 MNIST手写字体数据集2 LeNet-5 网络模型3 实验4 小结参考资料 注:转载请标明原文出处链接:https://xiongyiming.blog.csdn.net/article/details/100013565 1989年,Yann Lecun在论文 Gradient-Based ...
  • DL之LeNet-5:LeNet-5算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略 目录 LeNet-5算法的简介(论文介绍) LeNet-5算法的架构详解 1、LeNet-5 结构分析 2、各层详细说明 3、以手写数字3为...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,306
精华内容 1,722
关键字:

lenet提出时间