神经网络:卷积层

发布于:2025-07-21 ⋅ 阅读:(15) ⋅ 点赞:(0)
  1. 神经网络 卷积操作

    例子:

    输入:二维图像

    [1,2,0,3,1]

    [0,1,2,3,1]

    [1,2,1,0,0]

    [5,2,3,1,1]

    [2,1,0,1,1]

    卷积核:

    [1,2,1]

    [0,1,0]

    [2,1,0]

    然后需要将输入图像和卷积核转化为4维张量

    为什么转为4维张量?因为卷积操作需要输入图像和卷积核的维度相同,所以需要将其转化为相同的维度。

    (插入 channel:彩色图像就是rgb为3 灰度图像就是1)

    下面进行二维卷积操作:

    1. 步长为1 就是每次移动一步

      stride = 1

    2. 步长为2 就是每次移动两步

    3. 填充为1

      padding = 1

      达到填充后的输出和输入的大小相同 都是5x5

      为了充分学习边缘信息 提取边缘特征

    4. 上述输出

      在这里插入图片描述

    code:

    import torch
    import torch.nn.functional as F
    
    #原始输入图像
    input = torch.tensor([[1,2,0,3,1],
                          [0,1,2,3,1],
                          [1,2,1,0,0],
                          [5,2,3,1,1],
                          [2,1,0,1,1]])
    #卷积核
    kernel = torch.tensor([[1,2,1],
                           [0,1,0],
                           [2,1,0]])
    #将输入图像和卷积核转化为4维张量 reshape(batch_size, channel, height, width)
    #为什么转为4维张量?因为卷积操作需要输入图像和卷积核的维度相同,所以需要将其转化为相同的维度
    input = torch.reshape(input,(1,1,5,5))
    kernel = torch.reshape(kernel,(1,1,3,3))
    
    #二维卷积
    #stride=1 表示步长为1
    output = F.conv2d(input,kernel,stride=1)
    print(output)
    
    #步长为2
    output = F.conv2d(input,kernel,stride=2)
    print(output)
    
    #填充为1
    #填充后输出的大小和输入相同
    #就是卷积的时候在原输入的周围补0 上下左右补0
    #padding 也是为了充分利用边缘信息 提取边缘特征
    output = F.conv2d(input,kernel,stride=1,padding=1)
    print(output)
    
  2. 神经网络 卷积层

    作用:提取特征

    流程:

    1. 选取数据集

      这里我用的是自定义的数据集 还是放一下目录结构

      数据集在images下 注意DataLoader加载数据集需要的目录结构是datasets/classes 需要注意下

      在这里插入图片描述

    2. 数据预处理

      主要是使用transforms工具箱

      这里我先统一大小

      转成Tensor格式

      标准化

      #数据预处理
      transform = transforms.Compose([
          transforms.Resize((224,224)),
          transforms.ToTensor(),
          transforms.Normalize(
              mean = [0.5,0.5,0.5],
              std = [0.5,0.5,0.5]
          )
      ])
      
    3. 加载数据集

      ImageFloder()的时候应用transform

      batch_size是指一次取出多少图片来处理(2的倍数)

      folder_path = '../images'
      dataset = ImageFolder(folder_path,transform=transform)
      dataloader = DataLoader(dataset,batch_size=1)
      
    4. 构建卷积层

      这里的in_channels为3(彩色图片)out_channels为6(说明应该是应用了两个卷积核去卷积操作 会产生两个输出 所以最后的output的数量是input的两倍)kernel_size=3 卷积核设置的3x3的

      然后前向传播 输出结果

      class convNet(nn.Module):
          def __init__(self):
              #调用父类nn.Module的构造函数
              super(convNet,self).__init__()
              self.conv1 = Conv2d(in_channels=3,out_channels=6,kernel_size=3,stride=1,padding=0)
      
          def forward(self,x):
              x = self.conv1(x)
              return x
      
      convnet = convNet()
      
    5. 使用tensorboard观察结果

      日志存在logs文件夹下

      writer = SummaryWriter('../logs')
      ...
      ...
      ...
      writer.close()
      
       writer.add_images('input',img,cnt)
       writer.add_images('output',output,cnt)
      
    6. 开始遍历处理加载的图片(见后面完整代码中)

      output = torch.reshape(output,(-1,3,222,222))
      

      这一个操作是因为output的通道数是6 运行会报错 这里就给他强制性转换一下shape

      输入通道数变成几不知道 就填写-1

      (222,222)这个是怎么得到的?

      print(output.shape)得到的

    7. tensorboard结果:

      tensorboard --logdir=../logs
      

      (我数据集中就放了一张图片哈哈哈哈哈 大家能够认出是谁吗)

      在这里插入图片描述

      (笑死我了 这里是变形的小苏苏)

    8. 完整代码

      code:

      import torch
      import torchvision
      from torch import nn
      from torch.nn import Conv2d
      from torch.utils.data import DataLoader
      from torch.utils.tensorboard import SummaryWriter
      from torchvision.datasets import ImageFolder
      from torchvision import transforms
      
      #数据预处理
      transform = transforms.Compose([
          transforms.Resize((224,224)),
          transforms.ToTensor(),
          transforms.Normalize(
              mean = [0.5,0.5,0.5],
              std = [0.5,0.5,0.5]
          )
      ])
      
      #加载数据集
      folder_path = '../images'
      dataset = ImageFolder(folder_path,transform=transform)
      dataloader = DataLoader(dataset,batch_size=1)
      
      class convNet(nn.Module):
          def __init__(self):
              #调用父类nn.Module的构造函数
              super(convNet,self).__init__()
              self.conv1 = Conv2d(in_channels=3,out_channels=6,kernel_size=3,stride=1,padding=0)
      
          def forward(self,x):
              x = self.conv1(x)
              return x
      
      convnet = convNet()
      
      writer = SummaryWriter('../logs')
      
      cnt = 0
      for data in dataloader:
          img,label = data
          print(img.shape)
          output = convnet(img)
          print(output.shape)
          writer.add_images('input',img,cnt)
          output = torch.reshape(output,(-1,3,222,222))
          writer.add_images('output',output,cnt)
          cnt = cnt + 1
      
      writer.close()