深度学习入门-卷积神经网络(CNN)(下)

1-4、 深度学习入门-卷积神经网络(CNN)(上)-CSDN博客

5、 卷积神经网络(CNN)的实现

简单网络的构成是“Convolution - ReLU - Pooling - Affine - ReLU - Affine - Softmax”:

相关代码:

# 搭建进行手写数字识别的简单CNN网络
import sys, os
sys.path.append(os.pardir)
import pickle
import numpy as np
from collections import OrderedDict
from common.layers import *
from common.gradient import numerical_gradientclass SimpleConvNet:"""简单的ConvNetconv - relu - pool - affine - relu - affine - softmaxParameters----------input_size : 输入大小(MNIST的情况下为784)input_dim―输入数据的维度:(通道,高,长)conv_param―卷积层的超参数(字典)。字典的关键字如下:filter_num―滤波器的数量ilter_size―滤波器的大小stride―步幅pad―填充hidden_size―隐藏层(全连接)的神经元数量hidden_size_list : 隐藏层的神经元数量的列表(e.g. [100, 100, 100])output_size : 输出大小(MNIST的情况下为10)activation : 'relu' or 'sigmoid'weight_init_std : 初始化时权重的标准差(e.g. 0.01)指定'relu'或'he'的情况下设定“He的初始值”指定'sigmoid'或'xavier'的情况下设定“Xavier的初始值”"""# 初始化的最开始部分def __init__(self, input_dim=(1, 28, 28),# 卷积层的超参数通过名为conv_param的字典传入,# 以{'filter_num':30,'filter_size':5, 'pad':0, 'stride':1}保存必要的超参数值conv_param={'filter_num':30, 'filter_size':5, 'pad':0, 'stride':1},hidden_size=100, output_size=10, weight_init_std=0.01):# 将由初始化参数传入的卷积层的超参数从字典中取了出来(以方便后面使用)filter_num = conv_param['filter_num']filter_size = conv_param['filter_size']filter_pad = conv_param['pad']filter_stride = conv_param['stride']input_size = input_dim[1]# 计算卷积层的输出大小conv_output_size = (input_size - filter_size + 2*filter_pad) / filter_stride + 1pool_output_size = int(filter_num * (conv_output_size/2) * (conv_output_size/2))# 初始化权重参数# 将这些参数保存在实例变量的params字典中self.params = {}# 将第1层的卷积层的权重设为关键字W1,偏置设为关键字b1self.params['W1'] = weight_init_std * \np.random.randn(filter_num, input_dim[0], filter_size, filter_size)self.params['b1'] = np.zeros(filter_num)# 分别用关键字W2、b2和关键字W3、b3来保存第2个和第3个全连接层的权重和偏置self.params['W2'] = weight_init_std * \np.random.randn(pool_output_size, hidden_size)self.params['b2'] = np.zeros(hidden_size)self.params['W3'] = weight_init_std * \np.random.randn(hidden_size, output_size)self.params['b3'] = np.zeros(output_size)# 生成层self.layers = OrderedDict()# 从最前面开始按顺序向有序字典(OrderedDict)的layers中添加层self.layers['Conv1'] = Convolution(self.params['W1'], self.params['b1'],conv_param['stride'], conv_param['pad'])self.layers['Relu1'] = Relu()self.layers['Pool1'] = Pooling(pool_h=2, pool_w=2, stride=2)self.layers['Affine1'] = Affine(self.params['W2'], self.params['b2'])self.layers['Relu2'] = Relu()self.layers['Affine2'] = Affine(self.params['W3'], self.params['b3'])# SoftmaxWithLoss层被添加到另一个变量lastLayer中self.last_layer = SoftmaxWithLoss()def predict(self, x):for layer in self.layers.values():x = layer.forward(x)return xdef loss(self, x, t):"""求损失函数参数x是输入数据、t是正确标签"""# 用于推理的predict方法从头开始依次调用已添加的层,并将结果传递给下一层y = self.predict(x)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.0for 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)y = np.argmax(y, axis=1)acc += np.sum(y == tt) return acc / x.shape[0]def numerical_gradient(self, x, t):"""求梯度(数值微分)Parameters----------x : 输入数据t : 教师标签Returns-------具有各层的梯度的字典变量grads['W1']、grads['W2']、...是各层的权重grads['b1']、grads['b2']、...是各层的偏置"""loss_w = lambda w: self.loss(x, t)grads = {}for idx in (1, 2, 3):grads['W' + str(idx)] = numerical_gradient(loss_w, self.params['W' + str(idx)])grads['b' + str(idx)] = numerical_gradient(loss_w, self.params['b' + str(idx)])return gradsdef gradient(self, x, t):"""求梯度(误差反向传播法)Parameters----------x : 输入数据t : 教师标签Returns-------具有各层的梯度的字典变量grads['W1']、grads['W2']、...是各层的权重grads['b1']、grads['b2']、...是各层的偏置"""# forwardself.loss(x, t)# backwarddout = 1dout = self.last_layer.backward(dout)layers = list(self.layers.values())layers.reverse()for layer in layers:dout = layer.backward(dout)# 设定grads = {}grads['W1'], grads['b1'] = self.layers['Conv1'].dW, self.layers['Conv1'].dbgrads['W2'], grads['b2'] = self.layers['Affine1'].dW, self.layers['Affine1'].dbgrads['W3'], grads['b3'] = self.layers['Affine2'].dW, self.layers['Affine2'].dbreturn gradsdef save_params(self, file_name="params.pkl"):params = {}for key, val in self.params.items():params[key] = valwith 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] = valfor i, key in enumerate(['Conv1', 'Affine1', 'Affine2']):self.layers[key].W = self.params['W' + str(i+1)]self.layers[key].b = self.params['b' + str(i+1)]
# 学习
import sys, os
sys.path.append(os.pardir)
import numpy as np
import matplotlib.pyplot as plt
from dataset.mnist import load_mnist
from ch07.simple_convnet import SimpleConvNet
from common.trainer import Trainer# 读入数据
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=False)# 处理花费时间较长的情况下减少数据 
#x_train, t_train = x_train[:5000], t_train[:5000]
#x_test, t_test = x_test[:1000], t_test[:1000]max_epochs = 20network = SimpleConvNet(input_dim=(1,28,28), conv_param = {'filter_num': 30, 'filter_size': 5, 'pad': 0, 'stride': 1},hidden_size=100, output_size=10, weight_init_std=0.01)trainer = Trainer(network, x_train, t_train, x_test, t_test,epochs=max_epochs, mini_batch_size=100,optimizer='Adam', optimizer_param={'lr': 0.001},evaluate_sample_num_per_epoch=1000)
trainer.train()# 保存参数
network.save_params("params.pkl")
print("Saved Network Parameters!")# 绘制图形
markers = {'train': 'o', 'test': 's'}
x = np.arange(max_epochs)
plt.plot(x, trainer.train_acc_list, marker='o', label='train', markevery=2)
plt.plot(x, trainer.test_acc_list, marker='s', label='test', markevery=2)
plt.xlabel("epochs")
plt.ylabel("accuracy")
plt.ylim(0, 1.0)
plt.legend(loc='lower right')
plt.show()

运行结果:

如上运行结果:

如果使用MNIST数据集训练SimpleConvNet,则训练数据的识别率为99.82%,测试数据的识别率为98.91%(会有一些误差)。测试数据的识别率大约为99%,就小型网络来说,这是一个非常高的识别率。

6、 卷积神经网络(CNN)的可视化

6.1、第1层(卷积层)权重的可视化

将卷积层(第1层)的滤波器显示为图像,然后来比较一下学习前和学习后的权重:

代码:

# 卷积层权重的可视化
import numpy as np
import matplotlib.pyplot as plt
from ch07.simple_convnet import SimpleConvNetdef filter_show(filters, nx=8, margin=3, scale=10):"""c.f. https://gist.github.com/aidiary/07d530d5e08011832b12#file-draw_weight-py"""FN, C, FH, FW = filters.shapeny = int(np.ceil(FN / nx))fig = plt.figure()fig.subplots_adjust(left=0, right=1, bottom=0, top=1, hspace=0.05, wspace=0.05)for i in range(FN):ax = fig.add_subplot(ny, nx, i+1, xticks=[], yticks=[])ax.imshow(filters[i, 0], cmap=plt.cm.gray_r, interpolation='nearest')plt.show()network = SimpleConvNet()
# 随机进行初始化后的权重
filter_show(network.params['W1'])# 学习后的权重
network.load_params("params.pkl")
filter_show(network.params['W1'])

运行结果:

学习前:

学习后:

观察运行结果发现,学习后的滤波器在有规律地观察边缘(颜色变化的分界线)和斑块(局部的块状区域)等。

如下图显示了选择两个学习完的滤波器对输入图像进行卷积处理时的结果。我们发现“滤波器1”对垂直方向上的边缘有响应,“滤波器2”对水平方向上的边缘有响应。

6.2、基于分层结构的信息提取

上述结果是针对第1层的卷积层得出的。第1层的卷积层中提取了边缘或斑块等“低级”信息。

在堆叠了多层的CNN中,则随着层次加深,提取的信息也愈加复杂、抽象。

最开始的层对简单的边缘有响应,接下来的层对纹理有响应,再后面的层对更加复杂的物体部件有响应。也就是说,随着层次加深,神经元从简单的形状向“高级”信息变化。

如下图,CNN的卷积层中提取的信息。第1层的神经元对边缘或斑块有响应,第3层对纹理有响应,第5层对物体部件有响应,最后的全连接层对物体的类别(狗或车)有响应。

7、 具有代表性的 CNN:LeNet、AlexNet

7.1、LeNet

LeNet是进行手写数字识别的网络。如下图,它有连续的卷积层和池化层(只“抽选元素”的子采样层),最后经全连接层输出结果。

特点:

激活函数为sigmoid函数

使用子采样(subsampling)缩小中间数据的大小

7.2、AlexNet

AlexNet叠有多个卷积层和池化层,最后经由全连接层输出结果。

特点:

激活函数为ReLU函数

使用Max池化缩小中间数据的大小

使用进行局部正规化的LRN(Local Response Normalization)层

使用Dropout

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

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

相关文章

Java 大视界 -- Java 大数据在智能交通智能公交站台乘客流量预测与服务优化中的应用(349)

Java 大视界 -- Java 大数据在智能交通智能公交站台乘客流量预测与服务优化中的应用(349)引言:正文:一、Java 全场景韧性调度系统(新增极端天气 车型适配)1.1 极端天气:暴雪 / 台风的分钟级响应…

数论内容主要包括哪些

数论(Number Theory)是数学中研究整数的性质及其相互关系的一个分支,被誉为“数学中的皇后”。它历史悠久,内容丰富,既包含许多初等、直观的问题,也涉及高深、抽象的理论。数论的主要内容包括以下几个方面&…

springboot打包二次压缩Excel导致损坏

springboot打包二次压缩Excel导致损坏开发时,将Excel文件放到resources下,通过类加载器流读取,返回api用于下载该Excel文件。我发现这样下载的Excel被损坏了,无法打开,推测是springboot打包插件默认对resources下的所有…

huggingface笔记

1. huggingface的下载目录 ~/.cache/huggingface 2. 如何修改hugging face的模型默认下载地址 huggingface的默认下载路径在~/.cache/huggingface/hub/,但模型数据占用空间往往很大,可以用以下方法修改默认下载路径。 方法一:在linux中指定环…

Redis3:Redis数据结构与命令全解析

目录 1、redis数据结构介绍 1.1命令学习方式 1.1.1命令行查询 2、redis的通用命令 2.1查找常见的通用命令 2.2常见的通用命令: 3、String类型 3.1String类型的常见命令 3.2Key的层级格式 3.2.1Key的结构 4、Hash类型 4.1Hash类型 4.2Hash类型常见命令 …

WebSocket 重连与心跳机制:打造坚如磐石的实时连接

在现代 Web 应用中,WebSocket 是实现实时通信的核心技术。但网络环境复杂多变,如何确保连接稳定成为关键挑战。本文将深入剖析 WebSocket 的重连与心跳机制,提供一套经过生产环境验证的解决方案。 一、WebSocket 基础封装 首先我们实现一个具…

【代码】Matlab鸟瞰图函数

用matlab把图像转化为鸟瞰图 代码 clc clear close all I imread(road.png); figure(1) imshow(I) bevSensor load(birdsEyeConfig); birdsEyeImage transformImage(bevSensor.birdsEyeConfig,I); figure(2) imshow(birdsEyeImage)效果

网络编程-java

Socket 套接字 Socket套接字,是由系统提供用于网络通信的技术,是基于 TCP/IP 协议的网络通信的基本单元。基于 Socket 套接字的网络程序开发就是网络编程。 应用层会调用操作系统提供的一组 api ,这组 api 就是 socket api(传输层…

CPU架构、三级缓存以及内存优化屏障

目录 一、三级缓存和内存布局 二、CPU架构 (1)SMP对称对处理器架构 (2)NUMA非统一内存架构 三、RCU机制在内核中的体现 四、内存优化屏障 (1)编译器、CPU优化 (2)优化的问题…

HarmonyOS从入门到精通:动画设计与实现之九 - 实用动画案例详解(下)

HarmonyOS动画开发实战(九):实用动画案例详解(下) 在上篇中,我们围绕加载动画、点赞反馈、下拉刷新等核心交互场景,探讨了如何通过动画提升用户体验。本篇将聚焦界面元素动效与特殊场景动画&…

Node.js 聊天内容加密解密实战教程(含缓存密钥优化)

一、技术方案说明 本方案采用以下技术组合: 加密算法:AES-256-GCM(认证加密,防止篡改)密钥派生:PBKDF2(10万次迭代)缓存机制:内存缓存 定期轮换安全特性:随机…

信息安全基础专业面试知识点(上:密码学与软件安全)

密码学DES加密流程56比特长度的密钥K, 分组长度64比特,密文64比特初始置换 (IP):将输入的64位明文块进行置换,打乱其顺序。分成左右两半: 将置换后的64位数据分成左右两部分,每部分32位。16轮迭代加密: 这是DES的核心&#xff0c…

Windows Server 2025 黄金dMSA攻击漏洞:跨域攻击与持久化访问风险分析

网络安全研究人员近日披露了Windows Server 2025中委托管理服务账户(dMSA,Delegated Managed Service Accounts)存在的"关键设计缺陷"。据Semperis公司向The Hacker News提供的报告显示:"该漏洞可能导致高危害攻击…

解锁数据分析:从基础概念到核心指标的全面指南

在数字化时代,数据已成为驱动业务决策的核心力量。无论是运营一款 APP、管理一家便利店,还是优化在线教育课程,理解数据的本质与关键指标都至关重要。本文将从数据的基本概念出发,拆解运营全流程中的核心指标,并分享数…

DiffPy-CMI详细安装教程

本章教程,主要记录安装DiffPy-CMI的具体安装步骤。 DiffPy-CMI 是一个复杂建模框架,是高度灵活的 Python 模块库,专为晶体、纳米材料及非晶态材料的纳米结构建模而设计。 注意:DiffPy-CMI只支持在Linux和Mac上安装,Windows上是不支持的。 一、准备工作 需要准备一台Linux或…

中国各省市县坡度数据(Tif/Excel)

数据简介 昨天我们分享了中国120m精度的DEM数据(见前文),今天我们根据该数据计算中国的坡度数据,并根据中国省市县行政区划数据将其统计各省市县坡度的最大、最小以及平均值,方便大家研究使用。 基于中国120米精度DEM生成的坡度数据&#xff…

09-three.js Materials

Three.js Journey — Learn WebGL with Three.jsThe ultimate Three.js course whether you are a beginner or a more advanced developerhttps://threejs-journey.com/?cp3 MeshBasicMaterial 添加3个网格体: /*** Object*/ // MashBasicMaterial const mater…

Netty介绍和基本代码演示

什么是Netty?Netty是一个基于Java NIO的异步事件驱动的网络应用框架,主要用于快速开发高性能、高可靠性的网络服务器和客户端程序。它简化了网络编程的复杂性,提供了丰富的协议支持,被广泛应用于各种高性能网络应用中。为什么选择…

[BrowserOS] Nxtscape浏览器核心 | 浏览器状态管理 | 浏览器交互层

第三章:Nxtscape浏览器核心 欢迎回来! 在前两章中,我们了解了名为专用AI代理的专家团队及其管理者AI代理协调器,它们协同解析需求并规划执行步骤。 但这些代理与协调器实际运行的平台是什么?答案正是本章的核心——…

时序数据库处理的时序数据独特特性解析

时序数据(Time-Series Data)作为大数据时代增长最快的数据类型之一,正在物联网、金融科技、工业监控等领域产生爆炸式增长。与传统数据相比,时序数据具有一系列独特特性,这些特性直接影响了时序数据库(Time…