深度学习---------------卷积层

news2024/9/22 19:41:56

目录

  • 从全连接到卷积
    • 分类猫和狗的图片
    • 重新考察全连接层
      • 原则1------平移不变性
      • 原则2------局部性
    • 总结
  • 卷积层
    • 二维交叉相关
    • 二维卷积层
    • 交叉相关 vs 卷积
    • 一维和三维交叉相关
    • 总结
  • 图像卷积
    • 二维互相关运算
    • 实现二维卷积层
    • 图像中目标的边缘检测
      • 该部分总代码
      • 该部分总代码
  • 问题

从全连接到卷积

分类猫和狗的图片

    使用一个还不错的相机采集图片(12M像素=120万像素)
RGB图片有36M元素(360万像素)
    使用100大小的单隐藏层MLP,模型有3.6B元素(3.6B是指的参数数量而不是像素数量,即3.6Billion=36亿像素)

    远多于世界上所有猫和狗的总数(900M狗,600M猫)

在这里插入图片描述

3,600,000,000 * 4字节 = 14,400,000,000字节 ≈ 14.4GB

在这里插入图片描述
在这里插入图片描述

①k、l表示图片的第k行、第l列个像素,它相当于全连接层的 x i x_i xi, x i x_i xi乘以一个权重值,得到全连接层中一层神经元中一个神经元的一条线的值。

②有一个四维的W,里面有很多个w,例如前图的全连接层有100个w。i,j表示此w的坐标,即遍历所有的i、j合为100。每个w又是一个矩阵,每个w连接所有像素,对应矩阵宽高为k和l。因此下图中的 h i , j h_{i,j} hi,j为全连接层中一个神经元的输出。

③原来的k,l是基于图片的绝对位置,ab是根据ij的相对位置,这里就省略绝对位置,只需要一个原点加相对原点的相对位置,就可以表示位置信息。




重新考察全连接层

将输入和输出变形为矩阵(宽度,高度)
将权重变形为4维张量(h,w)到(h’,w’)

在这里插入图片描述

原本权重为二维:输入输出为一维向量,可以理解为从输入和输出分别选一个节点。
现在权重为四维:输入输出为二维矩阵,可以理解成从输入和输出分别选一个包含高宽的节点。

i、j表示选的w的坐标(即许多个卷积核,或者说滤波器、检测器),k、l表示图片像素的位置。
(可以理解为:权重w是输入的第i行j列这个元素到输出的k行l列的变换系数,所以w是4维的才能把输入和输出的每一个元素都连接上。)

第i行第j列的卷积核中的第(k,l)个元素。
(可以理解为:有一个4维的W,里面有很多个w。i、j表示此w的坐标,每个w又是一个矩阵,矩阵宽高为k、l。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
重新对w进行索引,对w一些元素重新排列一下做到一个v上面。把原来的w写成变换后的w的话,那么需要对 对应的X进行变换。




原则1------平移不变性

在这里插入图片描述
这就是2维交叉相关。




原则2------局部性

在这里插入图片描述
意思是:在 X i , j X_{i,j} Xi,j附近区域,区域🔺很小。
在这里插入图片描述




总结

    对全连接层使用平移不变性局部性得到卷积层。

在这里插入图片描述




卷积层

在这里插入图片描述
① 卷积核遇到和自己相似的,会极度膨胀,遇到和自己不一样的,会极度缩小。

② 提取图像特征,卷积层越深,提取的是语义的特征。




二维交叉相关

在这里插入图片描述

在这里插入图片描述




二维卷积层

在这里插入图片描述
    输出大小略小于输入大小。这是因为卷积核的宽度和高度大于1,而卷积核只与图像中每个大小完全适合的位置进行互相关运算。所以,输出大小等于输入大小 n k n_k nk× n k n_k nk减去卷积核大小 k h k_h kh× k h k_h kh,即:

在这里插入图片描述


在这里插入图片描述




交叉相关 vs 卷积

在这里插入图片描述


一维和三维交叉相关

在这里插入图片描述


总结

    卷积层将输入核矩阵进行交叉相关,加上偏移后得到输出。

    核矩阵偏移是可学习的参数。

    核矩阵的大小是超参数。




图像卷积

二维互相关运算

在这里插入图片描述

import torch


# K是核矩阵
def corr2d(X, K):  # @save
    """计算二维互相关运算"""
    h, w = K.shape  # 获取卷积核的长&宽
    # 输入 X 的高度减去卷积核的高度加一,输入 X 的宽度减去卷积核的宽度加一
    Y = torch.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1))
    # 使用两层嵌套循环遍历输出Y的每一个位置(i, j)  
    for i in range(Y.shape[0]): # 外层循环遍历Y的行
        for j in range(Y.shape[1]): # 内层循环遍历Y的列
            # 这里的K相当于W 的一个子集
            # 通过切片操作 X[i:i + h, j:j + w] 从输入 X 中提取一个与卷积核 K 大小相同的子区域。
            # 将这个子区域与卷积核 K 进行逐元素相乘
            Y[i, j] = (X[i:i + h, j:j + w] * K).sum()
    return Y


X = torch.tensor([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]])
K = torch.tensor([[0.0, 1.0], [2.0, 3.0]])
print(corr2d(X, K))

输出:
在这里插入图片描述



实现二维卷积层

    卷积层对输入卷积核权重进行互相关运算,并在添加标量偏置之后产生输出。所以,卷积层中的两个被训练的参数卷积核权重标量偏置。就像我们之前随机初始化全连接层一样,在训练基于卷积层的模型时,我们也随机初始化卷积核权重。

    corr2d函数实现二维卷积层。在__init__构造函数中,将weight和bias声明为两个模型参数。前向传播函数调用corr2d函数并添加偏置。

    高度和宽度分别为 h 和 w 的卷积核可以被称为 h × w 卷积或 h × w 卷积核。 我们也将带有 h × w 卷积核的卷积层称为 h × w 卷积层

class Conv2D(nn.Module):
    def __init__(self, kernel_size):
        super().__init__()
        self.weight = nn.Parameter(torch.rand(kernel_size))
        self.bias = nn.Parameter(torch.zeros(1))
 
    def forward(self, x):
        return corr2d(x, self.weight) + self.bias



练习:

import torch
from torch import nn
from d2l import torch as d2l


class Conv2D(nn.Module):
    def __init__(self, kernel_size):
        super().__init__()
        self.weight = nn.Parameter(torch.rand(kernel_size))
        self.bias = nn.Parameter(torch.zeros(1))

    def forward(self, x):
        return corr2d(x, self.weight) + self.bias


# K是核矩阵
def corr2d(X, K):  # @save
    """计算二维互相关运算"""
    h, w = K.shape  # 获取卷积核的长&宽
    Y = torch.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1))
    for i in range(Y.shape[0]):
        for j in range(Y.shape[1]):
            # 这里的K相当于W
            Y[i, j] = (X[i:i + h, j:j + w] * K).sum()
    return Y


X = torch.tensor([[0, 1, 2, 3],
                  [4, 5, 6, 7],
                  [8, 9, 10, 11],
                  [12, 13, 14, 15]], dtype=torch.float32)

# 创建 Conv2D 实例
conv = Conv2D(kernel_size=(2, 2))
# 进行卷积操作
Y = conv(X)
print(Y)

输出:
在这里插入图片描述


图像中目标的边缘检测

卷积层的一个简单应用:检测图像中不同颜色的边缘。

import torch

X = torch.ones((6, 8))
X[:, 2:6] = 0
print(X)

输出:

在这里插入图片描述


    构造一个高度为1、宽度为2的卷积核K。当进行互相关运算时,如果水平相邻的两元素相同,则输出为零,否则输出为非零。

在这里插入图片描述

K = torch.tensor([[1.0, -1.0]])



输出Y中的1代表从白色到黑色的边缘,-1代表从黑色到白色的边缘。 其他情况的输出为0。

Y = corr2d(X, K)
print(Y)

输出:
在这里插入图片描述


该部分总代码

import torch


# K是核矩阵
def corr2d(X, K):  # @save
    """计算二维互相关运算"""
    h, w = K.shape  # 获取卷积核的长&宽
    Y = torch.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1))
    for i in range(Y.shape[0]):
        for j in range(Y.shape[1]):
            # 这里的K相当于W
            Y[i, j] = (X[i:i + h, j:j + w] * K).sum()
    return Y


X = torch.ones((6, 8))
X[:, 2:6] = 0
K = torch.tensor([[1.0, -1.0]])
Y = corr2d(X, K)
print(Y)



    现在我们将输入的二维图像转置,再进行如上的互相关运算。 其输出如下,之前检测到的垂直边缘消失了。不出所料,这个卷积核K只可以检测垂直边缘,无法检测水平边缘。

corr2d(X.t(), K)

输出:
在这里插入图片描述
为什么全零?因为x转置后的结果如下图:

在这里插入图片描述

答:水平相邻的两元素相同,则输出为零

那么如何解决呢?
答:将K也转置

在这里插入图片描述
效果展示:
在这里插入图片描述



该部分总代码

import torch


# K是核矩阵
def corr2d(X, K):  # @save
    """计算二维互相关运算"""
    h, w = K.shape  # 获取卷积核的长&宽
    Y = torch.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1))
    for i in range(Y.shape[0]):
        for j in range(Y.shape[1]):
            # 这里的K相当于W
            Y[i, j] = (X[i:i + h, j:j + w] * K).sum()
    return Y


X = torch.ones((6, 8))
X[:, 2:6] = 0
K = torch.tensor([[1.0, -1.0]])
Y = corr2d(X.t(), K)
print(Y)



    如果我们只需寻找黑白边缘,那么以上[1, -1]的边缘检测器足以。然而,当有了更复杂数值的卷积核,或者连续的卷积层时,我们不可能手动设计滤波器。那么我们是否可以学习由X生成Y的卷积核呢?

    仅查看“输入-输出”对 来学习由X生成Y的卷积核。先构造一个卷积层,并将其卷积核初始化为随机张量。接下来,在每次迭代中,我们比较Y卷积层输出平方误差,然后计算梯度来更新卷积核。为了简单起见,我们在此使用内置的二维卷积层,并忽略偏置

# 构造一个二维卷积层,它具有1个输出通道和形状为(1,2)的卷积核
# 第一个参数:输入通道数为1,第二个参数:输出通道数为1
conv2d = nn.Conv2d(1,1, kernel_size=(1, 2), bias=False)
 
# 这个二维卷积层使用四维输入和输出格式(批量大小、通道、高度、宽度),
# 其中批量大小和通道数都为1
X = X.reshape((1, 1, 6, 8))
Y = Y.reshape((1, 1, 6, 7))
lr = 3e-2  # 学习率
# 通过一个循环来迭代更新权重
for i in range(10):
	# 进行前向传播,通过卷积层得到预测值Y_hat
    Y_hat = conv2d(X)
    l = (Y_hat - Y) ** 2
    conv2d.zero_grad()
    l.sum().backward()
    # 迭代卷积核,使用权重数据的data属性进行原地更新,学习率与梯度相乘得到了权重应该更新的方向和大小。
    conv2d.weight.data[:] -= lr * conv2d.weight.grad
    if (i + 1) % 2 == 0:
        print(f'epoch {i+1}, loss {l.sum():.3f}')



该部分总代码

import torch
from torch import nn


# K是核矩阵
def corr2d(X, K):  # @save
    """计算二维互相关运算"""
    h, w = K.shape  # 获取卷积核的长&宽
    Y = torch.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1))
    for i in range(Y.shape[0]):
        for j in range(Y.shape[1]):
            # 这里的K相当于W
            Y[i, j] = (X[i:i + h, j:j + w] * K).sum()
    return Y


X = torch.ones((6, 8))
X[:, 2:6] = 0
K = torch.tensor([[1.0, -1.0]])
Y = corr2d(X, K)
# 构造一个二维卷积层,它具有1个输出通道和形状为(1,2)的卷积核
# 第一个参数:输入通道数为1,第二个参数:输出通道数为1
conv2d = nn.Conv2d(1, 1, kernel_size=(1, 2), bias=False)

# 这个二维卷积层使用四维输入和输出格式(批量大小、通道、高度、宽度),
# 其中批量大小和通道数都为1
X = X.reshape((1, 1, 6, 8))
Y = Y.reshape((1, 1, 6, 7))
lr = 3e-2  # 学习率
# 通过一个循环来迭代更新权重
for i in range(10):
    # 进行前向传播,通过卷积层得到预测值Y_hat
    Y_hat = conv2d(X)
    l = (Y_hat - Y) ** 2
    conv2d.zero_grad()
    l.sum().backward()
    # 迭代卷积核,使用权重数据的data属性进行原地更新,学习率与梯度相乘得到了权重应该更新的方向和大小。
    conv2d.weight.data[:] -= lr * conv2d.weight.grad
    if (i + 1) % 2 == 0:
        print(f'epoch {i + 1}, loss {l.sum():.3f}')


输出:
在这里插入图片描述



所学的卷积核的权重张量

conv2d.weight.data.reshape((1, 2))

输出:
在这里插入图片描述




问题

①为什么要权重变形?为什么要重新索引?
解释全连接层和卷积层之间的关系,即怎么样对全连接层做变换、做限制能得到卷积层。

②为什么不应该看那么远?感受野不是越大越好吗?
类似于全连接层为什么隐藏层不是越大越好。(可以做一个很浅的很宽的全连接层,但没一个深一点短一点的全连接层好。)卷积神经网络是一样的。对一个卷积层比较少的(一层或者两层的)但是每个盒比较大的不如把每一层盒变小一点、做深一点。通常小一点的主要用3×3,5×5(即:2D卷积核一般shape = (3,3),最多(5,5)。大shape的卷积核不如更深层的小shape的卷积核)。

③二维卷积层,有没有可能同时使用两个不同尺寸的Kernel进行计算,然后再计算出一个更合适的Kernel,从而提升特征提取的性能。
有的

④为什么100的MLP太大放不下,100的全连接层能放下?
全连接层最大的问题:权重w的高取决于输入的宽。当输入一个1200万像素的图片,输入的维度就变成1200万的维度,所以炸掉了。100的全连接层是不大的,假设给定一个很大的图片那么全连接层就不行了,而卷积没有这个问题,因为盒是固定的。

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

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

相关文章

安装MySQL数据库【后端 8】

安装MySQL数据库 MySQL是世界上最流行的开源关系型数据库管理系统(RDBMS)之一,广泛应用于Web应用程序开发中。无论你是初学者还是有一定经验的开发者,掌握MySQL的安装都是必不可少的技能。本文将指导你如何在不同的操作系统上安装…

在 SOCKS 和 HTTP 代理之间如何选择?

在 SOCKS 和 HTTP 代理之间进行选择需要彻底了解每种代理的工作原理以及它们传达的配置。只有这样,您才能轻松地在不同类型的代理之间进行选择。 本文概述了 HTTP 和 SOCKS 代理是什么、它们如何运作以及它们各自带来的好处。此外,我们将比较这两种代理类…

1、Unity【基础】3D数学

3D数学 文章目录 3D数学1、数学计算公共类Mathf1、Mathf和Math2、区别3、Mathf中的常用方法(一般计算一次)4、Mathf中的常用方法(一般不停计算)练习 A物体跟随B物体移动 2、三角函数1、角度和弧度2、三角函数3、反三角函数练习 物…

三、虚拟机安装CentOS 7

编写目的: 1.做个记录,防止参考的博客被删 2.做个基础的虚拟机镜像,无应用,固定ip,能联网即可。后面直接克隆一个镜像,安装Jenkins等 目录 一、下载CentOS镜像 二、vmware配置CentOS虚拟机 1.打开vmw…

MSF经典attack示范

免责声明:本文仅做分享... 目录 Nessus官网 指定攻击 自动在线攻击 nmap扫 查看扫到的服务 查看主机 离线攻击 Msfvenom 本地快速传递文件的方法-->py 哈希传递攻击 提权 后渗透阶段 1-收集操作系统和版本信息 2-主机名称&环境变量 3-用户账户信息 4-远…

Stable Diffusion绘画 | ControlNet应用-NormalMap(法线贴图)

NormalMap(法线贴图),指的是一张只有红绿蓝RGB颜色的图片,通过指定的发法线算法,用RGB颜色相互混合搭配来表示物体的凹凸情况,常用于3D贴图模型使用。 整体配置如下: ControlNet 的法线控制可以把任何的图片转化为法线…

Java Web —— 第四天(HTTP协议,Tomcat)

HTTP-概述 概念:Hyper Text Transfer Protocol,超文本传输协议,规定了浏览器和服务器之间数据传输的规则 特点: 1. 基于TCP协议:面向连接,安全 2.基于请求-响应模型的:一次请求对应一次响应 3. HTTP协议是无状态的协议: 对于事务处理没有…

书生浦语大模型全链路开源开放体系学习

书生浦语大模型的开源体系经过一年努力,已实现从数据收集到模型部署的全链路打通。课程介绍了书生浦语的最新进展,包括7B和20B模型的开源及其性能提升。新版本模型在推理能力和上下文处理上表现优异,支持超长上下文和复杂任务解决。开源工具涵…

Java并发类API--Executor与ThreadPoolExecutor

在 Java 中,Executor 和 ThreadPoolExecutor 是用于管理线程和执行任务的工具,帮助开发者更好地控制多线程环境。下面是它们的使用和区别。 1.Executor 简介 Executor 是一个接口,用来创建线程池,它定义了一个 execute(Runnable c…

05 内部类API异常

1.内部类 1.1形参和返回值 1. 类名作为形参和返回值 方法的形参是类名,需要该类的对象 方法的返回值为类名,则返回该类的对象 2.抽象类名作为形参和返回值 方法的形参是抽象类名,需要该类的子类对象 方法的返回值是抽象类名,需要返回是该类的子类对象 3.接口名作为形参和返回值…

打印机维护好帮手 | 闪克打印机修复助手 v2.23.0.0

闪克打印机修复助手是一款专业的打印机修复软件,专为解决打印机相关问题而设计,能够帮助用户轻松识别和处理打印机设备的问题,从而提升工作效率。闪克打印机修复助手集成了错误修复、打印机驱动安装和综合修复三大功能。 它能够安全、快速、高…

C盘磁盘空间不足:VirtualBox的锅

文章目录 一,数据迁移二,修改默认配置三,在VirtualBox上删除原来的虚拟机四,在新的虚拟机目录下五,删除C盘上的虚拟机文件虚拟机消耗磁盘分析 开始在自己的windows电脑上使用Vitualbox虚拟机之后,发现C盘常…

【走迷宫】

题目 DFS代码 #include<bits/stdc.h> using namespace std; const int N 110; int matrix[N][N]; int n, m; int dx[4] {-1, 0, 1, 0}, dy[4] {0, 1, 0, -1}; int dis[N][N]; void dfs(int x, int y, int cnt) {if(cnt > dis[n-1][m-1]) return;if(x n-1 &&a…

Vue2.0 项目实战篇\部署篇

Vue2.0 项目实战篇\部署篇&#x1f4dc; 本篇文章学习记录于&#xff1a; bilibili-黑马程序♞ 104-139集 》》&#x1f3af;目标&#xff1a;冲击前后端全栈&#x1f525;&#xff0c;分享一下学过程&#xff1a; Java.慈祥的博客——个人前端技术栈blog记录&#xff1a;、感…

list使用及底层模拟实现

目录 一.list的使用 排序sort 去重unique remove按值删除 remove_if splice merge合并 二.模拟实现 1.成员变量及节点的实现 2.普通迭代器 成员变量 解引用operator* operator-> 前置和前置-- 后置和后置-- 等于与不等于重载 begin()迭代器 end()迭代器 3.co…

【论文阅读】YOLOv10: Real-Time End-to-End Object Detection

题目&#xff1a;YOLOv10: Real-Time End-to-End Object Detection 作者&#xff1a;Ao Wang Hui Chen∗ Lihao Liu Kai Chen Zijia Lin Jungong Han Guiguang Ding∗ 清华大学的 motivation: 作者觉得YOLO系列的NMS和某些结构非常的耗时&#xff0c;提出NMS-free和一些列高效…

AI大模型赋能游戏:更智能、更个性化的NPC

参考论文&#xff1a;https://arxiv.org/abs/2403.10249 在传统游戏中&#xff0c;NPC&#xff08;非玩家角色&#xff09;的行为往往是预先设定好的&#xff0c;缺乏灵活性和变化性。然而&#xff0c;基于大模型的NPC可以利用其强大的推理和学习能力&#xff0c;实时生成对话…

使用 JUnit 5 进行 Java 单元测试:最佳实践和技术说明

掌握 Java 单元测试&#xff1a;深入了解工具、最佳实践和技术&#xff0c;以确保代码的稳健性。增强软件可靠性并完美交付&#xff01; 想要提升 Java 开发工作量&#xff1f;本指南探索 Java 测试领域&#xff0c;涵盖基础概念和高级技术。您将了解测试驱动开发 (TDD) 的重要…

Wireshark分析工具

简单用例 首先打开软件,左上角点文件,选中要分析的文件列表。 导入用tcpdump抓的包后进行分析,这里要输入过滤条件,对网络包进行一定的过滤处理。(这里172网段是阿里云的地址,用自己写的python2脚本对阿里云进行压测。) 这里输入过滤条件 tcp.port == 80 ,语法含义是…

快速把文件名统计到excel表的方法

文件名统计到EXCEL表&#xff0c;这似乎很多人都没听说过&#xff0c;因为它与EXCEL表格不沾边&#xff0c;那么这个需求如何实现&#xff0c;用到什么方法&#xff0c;今天给大家介绍一个比较实用的方法&#xff0c;它可以把文件名或文件夹的名快速提取并统计到EXCEL表格上去。…