自己动手实现一个深度学习算法——八、深度学习

news2024/11/28 10:32:55

深度学习是加深了层的深度神经网络。

1.加深网络

1)向更深的网络出发

创建一个如下图所示的网络结构的CNN
在这里插入图片描述

这个网络的层比之前实现的网络都更深。这里使用的卷积层全都是3×3 的小型滤波器,特点是随着层的加深,通道数变大(卷积层的通道数从前面的层开始按顺序以16、16、32、32、64、64的方式增加)。

这个网络有如下特点。
• 基于 3×3 的小型滤波器的卷积层。
• 激活函数是 ReLU。
• 全连接层的后面使用 Dropout 层。
• 基于 Adam 的最优化。
• 使用 He 初始值作为权重初始值。

网络类的实现,deep_convnet类

# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 为了导入父目录的文件而进行的设定
import pickle
import numpy as np
from collections import OrderedDict
from common.layers import *


class DeepConvNet:
    """识别率为99%以上的高精度的ConvNet

    网络结构如下所示
        conv - relu - conv- relu - pool -
        conv - relu - conv- relu - pool -
        conv - relu - conv- relu - pool -
        affine - relu - dropout - affine - dropout - softmax
    """
    def __init__(self, input_dim=(1, 28, 28),
                 conv_param_1 = {'filter_num':16, 'filter_size':3, 'pad':1, 'stride':1},
                 conv_param_2 = {'filter_num':16, 'filter_size':3, 'pad':1, 'stride':1},
                 conv_param_3 = {'filter_num':32, 'filter_size':3, 'pad':1, 'stride':1},
                 conv_param_4 = {'filter_num':32, 'filter_size':3, 'pad':2, 'stride':1},
                 conv_param_5 = {'filter_num':64, 'filter_size':3, 'pad':1, 'stride':1},
                 conv_param_6 = {'filter_num':64, 'filter_size':3, 'pad':1, 'stride':1},
                 hidden_size=50, output_size=10):
        # 初始化权重===========
        # 各层的神经元平均与前一层的几个神经元有连接(TODO:自动计算)
        pre_node_nums = np.array([1*3*3, 16*3*3, 16*3*3, 32*3*3, 32*3*3, 64*3*3, 64*4*4, hidden_size])
        wight_init_scales = np.sqrt(2.0 / pre_node_nums)  # 使用ReLU的情况下推荐的初始值
        
        self.params = {}
        pre_channel_num = input_dim[0]
        for idx, conv_param in enumerate([conv_param_1, conv_param_2, conv_param_3, conv_param_4, conv_param_5, conv_param_6]):
            self.params['W' + str(idx+1)] = wight_init_scales[idx] * np.random.randn(conv_param['filter_num'], pre_channel_num, conv_param['filter_size'], conv_param['filter_size'])
            self.params['b' + str(idx+1)] = np.zeros(conv_param['filter_num'])
            pre_channel_num = conv_param['filter_num']
        self.params['W7'] = wight_init_scales[6] * np.random.randn(64*4*4, hidden_size)
        self.params['b7'] = np.zeros(hidden_size)
        self.params['W8'] = wight_init_scales[7] * np.random.randn(hidden_size, output_size)
        self.params['b8'] = np.zeros(output_size)

        # 生成层===========
        self.layers = []
        self.layers.append(Convolution(self.params['W1'], self.params['b1'], 
                           conv_param_1['stride'], conv_param_1['pad']))
        self.layers.append(Relu())
        self.layers.append(Convolution(self.params['W2'], self.params['b2'], 
                           conv_param_2['stride'], conv_param_2['pad']))
        self.layers.append(Relu())
        self.layers.append(Pooling(pool_h=2, pool_w=2, stride=2))
        self.layers.append(Convolution(self.params['W3'], self.params['b3'], 
                           conv_param_3['stride'], conv_param_3['pad']))
        self.layers.append(Relu())
        self.layers.append(Convolution(self.params['W4'], self.params['b4'],
                           conv_param_4['stride'], conv_param_4['pad']))
        self.layers.append(Relu())
        self.layers.append(Pooling(pool_h=2, pool_w=2, stride=2))
        self.layers.append(Convolution(self.params['W5'], self.params['b5'],
                           conv_param_5['stride'], conv_param_5['pad']))
        self.layers.append(Relu())
        self.layers.append(Convolution(self.params['W6'], self.params['b6'],
                           conv_param_6['stride'], conv_param_6['pad']))
        self.layers.append(Relu())
        self.layers.append(Pooling(pool_h=2, pool_w=2, stride=2))
        self.layers.append(Affine(self.params['W7'], self.params['b7']))
        self.layers.append(Relu())
        self.layers.append(Dropout(0.5))
        self.layers.append(Affine(self.params['W8'], self.params['b8']))
        self.layers.append(Dropout(0.5))
        
        self.last_layer = SoftmaxWithLoss()

    def predict(self, x, train_flg=False):
        for layer in self.layers:
            if isinstance(layer, Dropout):
                x = layer.forward(x, train_flg)
            else:
                x = layer.forward(x)
        return x

    def loss(self, x, t):
        y = self.predict(x, train_flg=True)
        return self.last_layer.forward(y, t)

    def accuracy(self, x, t, batch_size=100):
        if t.ndim != 1 : t = np.argmax(t, axis=1)

        acc = 0.0

        for i in range(int(x.shape[0] / batch_size)):
            tx = x[i*batch_size:(i+1)*batch_size]
            tt = t[i*batch_size:(i+1)*batch_size]
            y = self.predict(tx, train_flg=False)
            y = np.argmax(y, axis=1)
            acc += np.sum(y == tt)

        return acc / x.shape[0]

    def gradient(self, x, t):
        # forward
        self.loss(x, t)

        # backward
        dout = 1
        dout = self.last_layer.backward(dout)

        tmp_layers = self.layers.copy()
        tmp_layers.reverse()
        for layer in tmp_layers:
            dout = layer.backward(dout)

        # 设定
        grads = {}
        for i, layer_idx in enumerate((0, 2, 5, 7, 10, 12, 15, 18)):
            grads['W' + str(i+1)] = self.layers[layer_idx].dW
            grads['b' + str(i+1)] = self.layers[layer_idx].db

        return grads

    def save_params(self, file_name="params.pkl"):
        params = {}
        for key, val in self.params.items():
            params[key] = val
        with open(file_name, 'wb') as f:
            pickle.dump(params, f)

    def load_params(self, file_name="params.pkl"):
        with open(file_name, 'rb') as f:
            params = pickle.load(f)
        for key, val in params.items():
            self.params[key] = val

        for i, layer_idx in enumerate((0, 2, 5, 7, 10, 12, 15, 18)):
            self.layers[layer_idx].W = self.params['W' + str(i+1)]
            self.layers[layer_idx].b = self.params['b' + str(i+1)]

训练类train_deepnet的实现

# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 为了导入父目录而进行的设定
import numpy as np
import matplotlib.pyplot as plt
from dataset.mnist import load_mnist
from deep_convnet import DeepConvNet
from common.trainer import Trainer

(x_train, t_train), (x_test, t_test) = load_mnist(flatten=False)

network = DeepConvNet()  
trainer = Trainer(network, x_train, t_train, x_test, t_test,
                  epochs=20, mini_batch_size=100,
                  optimizer='Adam', optimizer_param={'lr':0.001},
                  evaluate_sample_num_per_epoch=1000)
trainer.train()

# 保存参数
network.save_params("deep_convnet_params.pkl")
print("Saved Network Parameters!")

权重参数保存在deep_conv_net_params.pkl

2)进一步提高识别精度

集成学习、学习率衰减、Data Augmentation(数据扩充)等都有助于提高识别精度。

Data Augmentation 基于算法“人为地”扩充输入图像(训练图像)。对于输入图像,通过施加旋转、垂直或水平方向上的移动等微小变化,增加图像的数量。这在数据集的图像数量有限时尤其有效。

3)加深层的动机

关于加深层的重要性,现状是理论研究还不够透彻。

层越深,识别性能也越高。

加深层一个好处就是可以减少网络的参数数量。加深层的另一个好处就是使学习更加高效。

通过加深层,可以将各层要学习的问题分解成容易解决的简单问题,从而可以进行高效的学习。

2.深度学习的小历史

现在深度学习之所以受到大量关注,其契机是2012年举办的大规模图像识别大赛ILSVRC(ImageNet Large Scale Visual Recognition Challenge)。在那年的比赛中,基于深度学习的方法(通称 AlexNet)以压倒性的优势胜出,彻底颠覆了以往的图像识别方法。

1)ImageNet

是拥有超过100万张图像的数据集。它包含了各种各样的图像,并且每张图像都被关联了标签(类别名)。每年都会举办使用这个巨大数据集的ILSVRC图像识别大赛。

2)VGG

VGG 是由卷积层和池化层构成的基础的 CNN。它的特点在于将有权重的层(卷积层或者全连接层)叠加至16层(或者19层),具备了深度(根据层的深度,有时也称为“VGG16”或“VGG19”)。

3)GoogLeNet

GoogLeNet的特征是,网络不仅在纵向上有深度,在横向上也有深度(广度)。

GoogLeNet 在横向上有“宽度”,这称为“Inception 结构”,Inception结构使用了多个大小不同的滤波器(和池化),最后再合并它们的结果。

4)ResNet

它的特征在于具有比以前的网络更深的结构。我们已经知道加深层对于提升性能很重要。但是,在深度学习中,过度加深层的话,很多情况下学习将不能顺利进行,导致最终性能不佳。

3.深度学习的高速化

大多数深度学习的框架都支持GPU(Graphics Processing Unit),可以高速地处理大量的运算。

最近的框架也开始支持多个GPU或多台机器上的分布式学习。

1)需要努力解决的问题

AlexNex中,大多数时间都被耗费在卷积层上。如何高速、高效地进行卷积层中的运算是深度学习的一大课题。

2)基于GPU的高速化

GPU 原本是作为图像专用的显卡使用的,但最近不仅用于图像处理,也用于通用的数值计算。

由于GPU 可以高速地进行并行数值计算,因此GPU 计算的目标就是将这种压倒性的计算能力用于各种用途。所谓 GPU 计算,是指基于GPU进行通用的数值计算的操作。

深度学习中需要进行大量的乘积累加运算(或者大型矩阵的乘积运算)。这种大量的并行运算正是GPU所擅长的(反过来说,CPU比较擅长连续的、复杂的计算)。因此,与使用单个CPU相比,使用GPU进行深度学习的运算可以达到惊人的高速化。

3)分布式学习

为了进一步提高深度学习所需的计算的速度,可以考虑在多个GPU或者多台机器上进行分布式计算。现在的深度学习框架中,出现了好几个支持多GPU或者多机器的分布式学习的框架。

其中,Google的TensorFlow、微软的CNTK(Computational Network Toolki)在开发过程中高度重视分布式学习。以大型数据中心的低延迟·高吞吐网络作为支撑,基于这些框架的分布式学习呈现出惊人的效果。

“如何进行分布式计算”是一个非常难的课题。它包含了机器间的通信、数据的同步等多个无法轻易解决的问题。

4)运算精度的位数缩减

在深度学习的高速化中,除了计算量之外,内存容量、总线带宽等也有可能成为瓶颈。关于内存容量,需要考虑将大量的权重参数或中间数据放在内存中。关于总线带宽,当流经GPU(或者CPU)总线的数据超过某个限制时,就会成为瓶颈。考虑到这些情况,我们希望尽可能减少流经网络的数据的位数。

4.深度学习的应用案例

深度学习并不局限于物体识别,还可以应用于各种各样的问题。此外,在图像、语音、自然语言等各个不同的领域,深度学习都展现了优异的性能。

1)物体检测

物体检测是从图像中确定物体的位置,并进行分类的问题。

物体检测是比物体识别更难的问题。之前介绍的物体识别是以整个图像为对象的,但是物体检测需要从图像中确定类别的位置,而且还有可能存在多个物体。

对于这样的物体检测问题,人们提出了多个基于CNN的方法。这些方法展示了非常优异的性能,并且证明了在物体检测的问题上,深度学习是非常有效的。

在使用CNN进行物体检测的方法中,有一个叫作R-CNN的有名的方法。首先(以某种方法)找出形似物体的区域,然后对提取出的区域应用CNN进行分类。R-CNN 中会将图像变形为正方形,或者在分类时使用 SVM(支持向量机),实际的处理流会稍微复杂一些,不过从宏观上看,也是由刚才的两个处理(候选区域的提取和CNN特征的计算)构成的。

2)图像分割

图像分割是指在像素水平上对图像进行分类。使用以像素为单位对各个对象分别着色的监督数据进行学习。然后,在推理时,对输入图像的所有像素进行分类。

要基于神经网络进行图像分割,最简单的方法是以所有像素为对象,对每个像素执行推理处理。比如,准备一个对某个矩形区域中心的像素进行分类的网络,以所有像素为对象执行推理处理。正如大家能想到的,这样的方法需要按照像素数量进行相应次forward处理,因而需要耗费大量的时间(正确地说,卷积运算中会发生重复计算很多区域的无意义的计算)。为了解决这个无意义的计算问题,有人提出了一个名为FCN的方法。该方法通过一次forward处理,对所有像素进行分类

FCN 的字面意思是 “全部由卷积层构成的网络”。相对于一般的 CNN 包含全连接层,FCN将全连接层替换成发挥相同作用的卷积层。

FCN的特征在于最后导入了扩大空间大小的处理。

3)图像标题的生成

一个基于深度学习生成图像标题的代表性方法是被称为 NIC(Neural Image Caption)的模型。

RNN是呈递归式连接的网络,经常被用于自然语言、时间序列数据等连续性的数据上。

我们将组合图像和自然语言等多种信息进行的处理称为多模态处理。多模态处理是近年来备受关注的一个领域。

5.深度学习的未来

1)图像风格变换

两个输入图像中,一个称为“内容图像”,另一个称为“风格图像”。

2)图像的生成

现在有一种研究是生成新的图像时不需要任何图像(虽然需要事先使用大量的图像进行学习,但在“画”新图像时不需要任何图像)。

3)自动驾驶
4)Deep Q-Network(强化学习)

就像人类通过摸索试验来学习一样(比如骑自行车),让计算机也在摸索试验的过程中自主学习,这称为强化学习(reinforcement learning)。强化学习和有“教师”在身边教的“监督学习”有所不同。

强化学习的基本框架是,代理(Agent)根据环境选择行动,然后通过这个行动改变环境。根据环境的变化,代理获得某种报酬。强化学习的目的是决定代理的行动方针,以获得更好的报酬

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1259256.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Centos 如何判断分区是mbr还是gpt格式

1 介绍 MBR 自20世纪80年代初以来的标准分区表格式每个驱动器最多支持四个主分区最多可以划分2TB的磁盘 GPT GPT是MBR分区表格式的后续每个驱动器最多支持128个分区可以将一个磁盘分区到最大到18艾字节 对小于2TB的磁盘使用MBR对大于2TB的磁盘使用GTP 2 查询方式 2.1 fdis…

Windows11安装后跳过联网登录

Windows11安装后跳过联网登录 实验设备: VMware17Pro虚拟机中使用Windows11镜像安装Windows11操作系统,并且在虚拟机中测试跳过联网登录。 步骤 说明:物理卸载网卡(在虚拟机上禁用网卡)没用 思路: sh…

鸿蒙应用开发-初见:ArkTS

作者:HarderCoder ArkTS ArkTS围绕应用开发在 TypeScript (简称TS)生态基础上做了进一步扩展,继承了TS的所有特性,是TS的超集 ArkTS在TS的基础上扩展了struct和很多的装饰器以达到描述UI和状态管理的目的 基本语法 …

【云备份】配置加载文件模块

文章目录 配置信息设计配置文件加载cloud.conf配置文件单例模式的使用ReadConfigFile —— 读取配置文件GetInstance —— 创建对象其他函数的实现 具体实现cloud.confconfig.hpp 配置信息设计 使用文件配置加载一些程序运行的关键信息 可以让程序的运行更加灵活 配置信息&am…

kafka集群环境部署

文章目录 1 Kafka集群2 搭建两台服务器2.1 zookeeper部署2.2 启动1号机器的broker2.3 启动2号机器的broker2.4 查看kafka集群2.5 测试集群 1 Kafka集群 2 搭建两台服务器 2.1 zookeeper部署 zookeeper先只部署一台,在1号机器(192.168.11.59)…

浅谈智能照明控制系统在建筑电气工程中的应用

贾丽丽 安科瑞电气股份有限公司 上海嘉定 201801 摘要:建筑电气工程是项目工程中的重要组成部分,其对技术、电气设备及系统的要求较高。在信息化技术不断深入推广的新时期,建筑电气工程中的照明系统获得新的发展契机,为了满足现…

【RTP】4: 实例解析:一个SRTP的wireshark抓包:带padding、带扩展

抓取的是视频包。固定的pt是127从头部找到序号,快速找到这个包包大小因为是包括了SRTP的,所以318 个字节,实际RTP包是286个字节。SRTP 包 UDP总共 294个字节,payload部分286 RTP协议 RTP部分: B0 代表有padding、有扩展 从B0开始

每天一道算法题:51. N 皇后

难度 困难 题目 按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上,并且使皇后彼此之间不能相互攻击。 给你一个整数 n ,返回所有不同的 n_ _皇后问题 的…

FLASK博客系列9——你想成为我的新用户吗?

距离上次发文好久好久了。 先说声抱歉,拖更的毛病我会改掉的。 上次我们教大家如何用后台去管理用户和新增文章,但始终都是单机操作,怎么让你的朋友也来加入你的小站呢?今天我们来为我们的网站增添一个新功能,实现用户…

js 获取数组的最大值与最小值

let arr [1, 2, 5, 8, 10, 100, -1] 1. 使用Math的静态方法max/min Math.max()函数返回给定的一组数中的最大值。 它的语法:Math.max(value1[, value2, ...]) 使用此方法,需要注意,如果没有参数的话,则返回-Infinity。如果有任一…

海外服务器的韧性有多重要?带你了解亚马逊云科技的前世今生

在“第四次工业革命”的浪潮中,云计算已经成为众多互联网企业发展业务灵活性和创新性的核心引擎。然而,随之而来的是各个行业对云服务器,尤其是海外服务器的韧性和可靠性的需求不断提升。在这个充满挑战和竞争的行业环境下,亚马逊…

Vatee万腾的数字创新征途:vatee科技力量的独特奇点

在数字化的时代浪潮中,Vatee万腾如一颗耀眼的明星,以其独特的科技奇点引领着数字创新的征途。无论是在人工智能、大数据、云计算,还是智能化领域,Vatee万腾都展现出了与众不同的创新力量,为科技征途描绘了独一无二的奇…

linux下的工具---gdb

一、gdb简介 GDB,是The GNU Project Debugger 的缩写,是 Linux 下功能全面的调试工具。 GDB支持断点、单步执行、打印变量、观察变量、查看寄存器、查看堆栈等调试手段。 程序的发布方式有两种,debug模式和release模式 Linux gcc/g出来的二进制程序&am…

神经网络的分类

神经网络可以分为三种主要类型:前馈神经网络、反馈神经网络 和 图神经网络。 一、前馈神经⽹络 前馈神经⽹络(feedforward neural network)是⼀种简单的神经⽹络,也被称为多层感知机(multi-layer perceptron&#xff…

亚马逊云科技实现了奇瑞捷豹路虎SAP系统的上云目标并保持成本优化

11月23日,“2023第八届IDC中国数字化转型年度盛典”正式开启并揭晓“2023 IDC中国未来企业大奖-卓越奖”获奖企业,奇瑞捷豹路虎汽车有限公司(以下简称“奇瑞捷豹路虎”)凭借“基于云原生的智慧化运营平台”项目,继获得…

2024年最安全的10个Linux桌面发行版

选择合适的 Linux 发行版很重要。 Linux 发行版是一切计算的基石,也是诸君管理硬件组件及交互的重要工具。如果没有强大的安全措施,你的系统很容易受到攻击。值得庆幸的是,Linux 生态系统提供了一系列选项,允许用户根据自己的特定…

Single Patterns : 就一个单例模式调得我蛋疼,1. 单例类的继承树即扩展 2. 系统中单例类的注册及查询,属实有意思!

Intent Ensure a class only has one instance, and provide a global point of access to it. // DesignPatterns.cpp: 定义应用程序的入口点。 //#include "DesignPatterns.h"#include <list> #include <utility> using namespace std;class Single…

计算机视觉面试题-03

1、简单介绍一下sigmoid&#xff0c;relu&#xff0c;softplus&#xff0c;tanh&#xff0c;RBF及其应用场景 这里简单介绍几个激活函数及其应用场景&#xff1a; Sigmoid 函数&#xff08;Logistic 函数&#xff09;&#xff1a; 公式&#xff1a; s i g m a ( x ) 1 1 e …

2.7V 到 5.5V、 12Bit 单通道数模转换器MS5221/5221M

产品简述 MS5221/5221M 是一款 12bit 单通道输出的电压型 DAC &#xff0c;接口 采用三线串口模式&#xff0c;可以兼容 TMS320 、 SPI 、 QSPI 和 Microwire 串 口。 MS5221/5221M 数据有 16bit &#xff0c;包括控制字节&#xff0c;和 12bitDAC 数 据。 MS5221/5221M 电…

CloudCompare 二次开发1

一、在源码中添加插件文件 修改cmakelist 二、插件文件内容 MyPlugin 1、修改程序名称 2、 修改cMakeList 3、 修改cpp和.h 4、修改qc 5、修改json 三、重新编译 cmake 插件 如果不打√那个生成的程序里面没有这个插件显示 generate 然后生成 结果 四、结果显示 dll …