IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> Pytorch深度学习实践(b站刘二大人)P10讲 (CNN卷积神经网络基础篇) -> 正文阅读

[人工智能]Pytorch深度学习实践(b站刘二大人)P10讲 (CNN卷积神经网络基础篇)

1.全连接网络

指的是网络里面用的都是线性层,如果一个网络全都由线性层串行连接起来,就叫做全连接网络在这里插入图片描述

在线性层里面输入和每一个输出值之间都存在权重,即每一个输入节点都要参与到下一层输出节点的计算上,这样的线性层也叫全连接层?Fully Connected

在这里插入图片描述

2.二维卷积神经网络工作方式

?卷积神经网络把图像按照原始的空间结构保存,能保留原始的空间信息(全连接过程中,把图像弄成了一串,会使原本图像中相邻的节点,距离较远)
经过一个卷积层把1*28*28的图像变成4*24*24

在这里插入图片描述
使用下采样(subsampling)时,通道数不会改变,图像的宽度和高度会改变,下采样的目的是减少数据的数据量,减少特征图(Feature map)的元素数量,目的是降低运算需求,因为是做分类,最终的目的是通过不断的卷积运算输出一个概率向量
现在输入的维度比较高,需要不断地进行维度(可以先升高后降低)和大小上的变化,最终把图像由1*28*28的张量变成概率向量

在这里插入图片描述
如上图,又经过了卷积和下采样,针对MNIST数据集,最注重输出的是图像对应所属10个分类的概率,所以最后要把8*4*4的三阶张量展开成一个一维的向量,可以用上一讲里面的view来实现,8个通道,每个通道有4*4个元素,按照某种顺序,把它展开成一维向量 ,如下图
展开之后就得到了线性的只有向量的输入,再用全连接层最终把这个向量映射到10维的输出,然后接上交叉熵损失利用softmax计算概率分布,解决分类问题

?在这里插入图片描述

神经网络里面,卷积和下采样叫做特征提取器,能通过卷积运算,找到某种特征

分类器:经过特征提取之后把它变成向量,然后把这个向量连接全连接网络做分类?

图像到底是什么?

一般是用RGB三个通道表示的,如下图,每一个图像可以划分成很多个格子,给每一个格子填上颜色值就构成一个图像,叫做栅格图像,基本上从自然界获取图像都是采用这样的方式
图像如果放大就是一个一个的格子

在这里插入图片描述

相机拍照时,是通过传感器获得像素值,有红绿蓝三种颜色的传感器,传感器上有光敏电阻,电阻值与RGB值有对应关系,最终获得图像?

?

用这个卷积块把图像遍历一遍,然后对每一个块做卷积运算,得到卷积输出结果,最后把输出结果拼到一起,这就是卷积

单通道图像卷积

?在这里插入图片描述

如上图,输入是1*5*5的图像,卷积核是3*3,步长为1,经过卷积核在输入矩阵上运算(计算方式如上图)得到了13*3的输出,以上是单通道的卷积运算方法

多通道卷积


? ? 比如输入图像是3个通道,到神经网络中间的时候输入通道不一定是3个,几百个通道都有可能,以3通道为例,每一个通道都要配一个核,输入通道的数量与核的数量是一样的
如下图,三个通道分别和卷积核做卷积,得到3个矩阵,然后相加
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

为什么输出的宽度和高度是3呢??

?我们看每一次卷积的中心

在这里插入图片描述

如果是3*3的卷积核,宽高是会减2的,上下左右各减一个 ;如果是5*5的卷积核,宽高减4在这里插入图片描述

如果想要输出是m个通道怎么办呢?


?那就准备m个卷积核,每一个卷积核对原始输入卷积完之后通道数都是1,然后把这些通道拼接起来
每一个卷积核通道数量要求和输入通道一样
卷积核的数量和输出通道数是一样的
卷积核的大小自己定,与图像大小无关
共享权重机制:对每一个图像块操作用的是相同的卷积核

在这里插入图片描述

?可以把m个卷积核拼成4维张量 m(卷积核个数)*n(输入通道数)width*?height,我们构建卷积层,它的权重就是这样的一个维度?

?所以定义一个卷积层,需要知道:输入通道数,输出通道数,卷积核大小

#卷积层并不在于输入的张量的宽度和高度,因为我们是复用的权重,只是把图像遍历一遍,图像大输出就大,图像小,输出就小
#所以卷积层对输入图像的宽度和高度没有要求,只对输入通道数有要求

import torch
in_channels,out_channels=5,10#n,m
width,height=100,100#图像的大小
kernel_size=3#卷积核的大小3*3
batch_size=1#pytorch里面所有输入的数据必须是小批量的数据
input=torch.randn(batch_size,
                  in_channels,
                  width,
                  height)#batch_size表示小批量的第几个
#torch.randn 生成输入数据的时候取的随机数,服从正态分布采样的随机数
conv_layer=torch.nn.Conv2d(in_channels,
                           out_channels,
                           kernel_size=kernel_size)
#Conv2d,卷积核也可以用长方形的,kernel_size=(5,3)
output=conv_layer(input)#把输入传进卷积层,得到输出
print(input.shape)#[1,5,100,100]
print(output.shape)#[1,10,98,98]
print(conv_layer.weight.shape)#卷积层权重的形状[10,5,3,3],10是输出通道的数量,5是输入通道的数量,3,3是卷积核的大小
#定义一个卷积层,需要确定输入通道,输出通道,卷积核的大小

?输出结果:

torch.Size([1, 5, 100, 100])
torch.Size([1, 10, 98, 98])
torch.Size([10, 5, 3, 3])

怎么保证卷积之后图像宽高不变?

在这里插入图片描述

这是有规律可循的
如果卷积核是3*3,3/2=1----->在原矩阵外补1圈0 padding=1
如果卷积核是5*
5,5/2=2----->在原矩阵外补2圈0 padding=2

import torch
input=[3,4,6,5,7,
       2,4,6,8,2,
       1,6,7,8,4,
       9,7,4,6,2,
       3,7,5,4,1]
input=torch.Tensor(input).view(1,1,5,5)#把输入变成(batch_size,channel,width,height)
conv_layer=torch.nn.Conv2d(1,1,kernel_size=3,padding=1,bias=False)
#构建卷积层,输入是1个通道,输出是一个通道,卷积核3*3,如果bias=True,卷积完之后会给每一个通道加上一个偏置量
#不需要加偏置量就bias=False,padding=1是当卷积核为3*3时,保证输出还是5*5
kernel=torch.Tensor([1,2,3,4,5,6,7,8,9]).view(1,1,3,3)#构建卷积核(输出通道数,输入通道数,宽度,高度)
conv_layer.weight.data=kernel.data#把做出来的kernel张量的data赋值给卷积层的权重.data,把卷积层的权重初始化
output=conv_layer(input)
print(output)

结果

tensor([[[[ 91., 168., 224., 215., 127.],
          [114., 211., 295., 262., 149.],
          [192., 259., 282., 214., 122.],
          [194., 251., 253., 169.,  86.],
          [ 96., 112., 110.,  68.,  31.]]]],

当步长stride=2?:

?在这里插入图片描述

?下采样


下采样用的比较多的是MaxPooling(最大池化层)
最大池化层是没有权重的
22的maxpooling默认stride=2
就是把图像分成22的一个组,在每个组里面找最大值
所以做maxpooling的时候只能把一个通道拿出来做maxpooling,通道之间不会去找最大值,所以在做最大池化(maxpooling)的时候,通道数量不会发生改变,但是如果用2*2的maxpooling,图像大小会缩成原来的一半
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200902170558863.png?x-oss-process=image/watermark,type_ZmFuZ3poZW

import torch
input=[3,4,5,6,
       2,4,6,8,
       1,6,7,8,
       9,7,4,6]
input=torch.Tensor(input).view(1,1,4,4)
maxpooling_layer=torch.nn.MaxPool2d(kernel_size=2)
#当kernel_size=2,maxpooling默认的步长也会是2
output=maxpooling_layer(input)
print(output)

?结果:

tensor([[[[4., 8.],
          [9., 8.]]]])

卷积神经网络实现MNIST

在这里插入图片描述

第一个最大池化做一个就行了,因为它没有权重,跟sigmoid和relu一样,是没有权重的,但是有权重的必须每一个层单独做一个实例?

参考代码:

import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F  # 用Relu函数
import torch.optim as optim  # 优化器优化

batch_size = 64
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
# transform:把图像转化成图像张量
train_dataset = datasets.MNIST(root='../dataset/mnist',
                               train=True,
                               download=True,
                               transform=transform)  # 训练数据集
train_loader = DataLoader(train_dataset,
                          shuffle=True,
                          batch_size=batch_size)
test_dataset = datasets.MNIST(root='../dataset/mnist',
                              train=False,
                              download=True,
                              transform=transform)
test_loader = DataLoader(test_dataset,
                         shuffle=False,
                         batch_size=batch_size)


class Net(torch.nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = torch.nn.Conv2d(1,10,kernel_size=5)
        self.conv2 = torch.nn.Conv2d(10,20,kernel_size=5)
        self.pooling = torch.nn.MaxPool2d(2)
        self.fc = torch.nn.Linear(320,10)

    def forward(self, x):
        batch_size = x.size(0)
        x = F.relu(self.pooling(self.conv1(x)))
        x = F.relu(self.pooling(self.conv2(x)))
        # Flatten data from (n,1,28,28) to (n,784) Flatten层用来将输入“压平”,即把多维的输入一维化,常用在从卷积层到全连接层的过渡。
        x = x.view(batch_size,-1)
        x = self.fc(x)  #x应用全连接网络
        return x

model = Net()
criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)


# 因为网络模型已经有点大了,所以梯度下降里面要用更好的优化算法,比如用带冲量的(momentum),来优化训练过程


# 把一轮循环封装到函数里面
def train(epoch):
    running_loss = 0.0
    for batch_idx, data in enumerate(train_loader, 0):
        inputs, target = data
        optimizer.zero_grad()  # 优化器,输入之前清零
        # forward + backward + updat
        outputs = model(inputs)
        loss = criterion(outputs, target)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()
        if batch_idx % 300 == 299:  # 每300轮输出一次
            print('[%d,%5d] loss:%.3f' % (epoch + 1, batch_idx + 1, running_loss / 300))
            running_loss = 0.0


def test():
    correct = 0  # 正确多少
    total = 0  # 总数多少
    with torch.no_grad():  # 测试不用算梯度
        for data in test_loader:  # 从test_loader拿数据
            images, labels = data
            outputs = model(images)  # 拿完数据做预测
            _, predicted = torch.max(outputs.data, dim=1)  # 沿着第一个维度找最大值的下标,返回值有两个,因为是10列嘛,返回值
            # 返回值一个是每一行的最大值,另一个是最大值的下标(每一个样本就是一行,每一行有10个量)(行是第0个维度,列是第1个维度)
            total += labels.size(0)  # 取size元组的第0个元素(N,1),
            correct += (predicted == labels).sum().item()  # 推测出来的分类与label是否相等,真就是1,假就是0,求完和之后把标量拿出来
    print('Accuracy on test set:%d %%' % (100 * correct / total))


# 训练
if __name__ == '__main__':
    for epoch in range(10):
        train(epoch)
        test() #训练一轮,测试一轮


如果有GPU,怎么用显卡来计算

①把模型迁移到GPU

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 
model.to(device)

如果装的是支持cuda版本的pyTorch,available就是True,默认是cuda 0,只有cpu就是false
如果有多个显卡,不同的任务可以使用不同的显卡
model.to(device)把整个模型的参数,缓存,所有的模块都放到cuda里面,转成cuda tensor

在这里插入图片描述?

?计算的时候要把用来计算的张量也迁移到GPU,主要是输入和对应的输出,把inputs和target都迁移到device上,注意迁移的device和模型的device要在同一块显卡上,比如把模型放在第0块显卡,数据放在第一块显卡,是没法工作的

inputs, target = inputs.to(device), target.to(device)?
在这里插入图片描述

测试也把输入输出放到显卡上

在这里插入图片描述?

?

view()函数
参考文章:https://blog.csdn.net/ningmengshuxiawo/article/details/108356453

补充知识:CNN基础知识——卷积(Convolution)、填充(Padding)、步长(Stride) - 知乎

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-01-11 23:59:55  更:2022-01-12 00:01:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 4:39:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码