Pytorch深度学习实践(9)卷积神经网络(基础篇)

卷积神经网络(基础)

全连接神经网络

神经网络中全部是线性模型,是由线性模型串联起来的

全连接网络又叫全连接层

卷积神经网络

在全连接神经网络中,由于输入必须是一维向量,因此在处理图像时必须要对图像矩阵进行拉伸成一维的形式,这必然会导致损失一些空间信息

为了保证空间信息的完整性,因此我们需要使用卷积神经网络,直接出入图片,进行模型训练

基本步骤如下:

输入 -- 卷积 -- 下采样 -- 卷积 -- 下采样 -- 全连接层 -- 输出

其中,卷积和下采样工作称为特征提取 feature extraction,全连接层的工作叫做分类器 classification

图像

图像分为三个维度:

  • 通道(rgb

即表示为 C × H × W C×H×W C×H×W

卷积的运算

单通道卷积

在输入中,拿出和卷积核大小一致的矩阵,与卷积核进行数乘,让后放到输出的第一个单元格内

然后使用卷积核依次对输入进行遍历,最终填满所有的输出

多通道卷积

每一个通道都配有一个卷积核,对每个通道进行卷积操作,最后把所有通道的输出进行相加,得到最终的输出

原始图像几个通道,卷积核就要有几层

对于多通道图像,图像可以看作是立体 的,卷积核也可以看作是立体 的,经过卷积之后把各通道的输出相加,最终得到一个二维的张量

为了在训练过程中使得输出也具有多个通道,因此使用多个3维的卷积核

卷积层的设计

卷积核

三要素:

  • 输入的通道数
  • 输出的通道数
  • 卷积核尺寸的大小
python 复制代码
# 实例化卷积层
conv_layer = torch.nn.Conv2d(in_channels, out_channels, kernel_size = kernel_size)
# 设置卷积核权重 (batch_sie, channel, w, h) = (1, 1, 3, 3)
kernel = torch.Tensor([1, 2, 3, 4, 5, 6, 7, 8, 9]).view(1, 1, 3, 3)
conv_layer.weight.data = kernel.data

通过卷积核后输出的大小: m × n × k e r n e l _ s i z e w i d t h × k e r n e l _ s i z e h e i g h t m×n×kernel\size{width}×kernel\size{height} m×n×kernel_sizewidth×kernel_sizeheight

其中, m m m为批量 b a t c h batch batch大小, n n n为通道数

padding填充

通过设置padding,即对原始图像进行填充,进而控制输出的大小,填充的部分一般默认用0代替

一般来说,如果卷积核是 3 × 3 3×3 3×3,则padding一圈,如果卷积核是 5 × 5 5×5 5×5,则padding两圈

卷积核大小为 n × n,则padding n / 2 n / 2 n/2(整除)圈

python 复制代码
conv_layer = torch.nn.Conv2d(in_channels,  # 输入通道数
                             out_channels, # 输出通道数
                             kernel_size = kernel_size, # 卷积核大小
                             padding = 1,  # 填充层数
                             bias = False) # 不使用偏置

stride步长

每次遍历原始图像时的步长,可以有效地降低图像的宽度和高度

python 复制代码
conv_layer = torch.nn.Conv2d(1, 1,
                             kernel_size = 3, # 卷积核大小
                             padding = 1,  # 填充层数
                             stride=2,  #步长
                             bias = False) # 不使用偏置

下采样

一般使用最大池化层 ,即MaxPooling

最大池化层步长默认大小为 2 × 2 2×2 2×2

先将输入按照步长大小分割,形成多个部分,然后再在各个部分中取最大值,作为输出

python 复制代码
maxpooling_layer = torch.nn.MaxPool2d(kernel_size=2)

代码实战

使用卷积神经网络处理MNIST

构造卷积神经网络如下所示:

  • 卷积层不需要知道输入输出的大小
  • 但最后的全连接层(线性模型)需要定义输出输出的大小

不使用GPU版本

python 复制代码
import torch
import matplotlib.pyplot as plt
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F

########## 准备数据集 ##########
batch_size = 64
## 实例化转换器
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307,), (0.3081,))
])
train_dataset = datasets.MNIST(root='./dataset/mnist/',
                               train=True,
                               download=False,
                               transform=transform)
train_loader = DataLoader(train_dataset,
                          shuffle=True,
                          batch_size=batch_size)
test_dataset = datasets.MNIST(root='./dataset/mnist/',
                              train=False,
                              download=False,
                              transform=transform)
test_loader = DataLoader(test_dataset, 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) # 卷积层1
        self.conv2 = torch.nn.Conv2d(10, 20, kernel_size=5) # 卷积层2
        self.pooling = torch.nn.MaxPool2d(2)  # 池化层
        self.fc = torch.nn.Linear(320, 10)  # 全连接层

    def forward(self, x):
        batch_size = x.size(0)
        ## 先输入卷积层 在输入池话层 最后输入到relu中做非线性变换
        # 1
        x = F.relu(self.pooling(self.conv1(x)))
        # 2
        x = F.relu(self.pooling(self.conv2(x)))
        ## 全连接层
        # 先把输入平铺 flatten 操作
        x = x.view(batch_size, -1)
        x = self.fc(x)
        return x

model = Net()

########## 损失函数核优化器定义 ##########
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr = 0.01, momentum=0.5)

########## 模型训练 ##########
def train(epoch):
    running_loss = 0.0
    for batch_index, data in enumerate(train_loader, 0):
        inputs, target = data
        optimizer.zero_grad()

        # forward
        outputs = model(inputs)
        loss = criterion(outputs, target)
        # backward
        loss.backward()
        # update
        optimizer.step()

        running_loss += loss.item()
        if batch_index % 300 == 299:
            print('[%d %5d] loss: %.3f' % (epoch + 1, batch_index + 1, running_loss / 300))
            running_loss = 0.0

########## 模型测试 ##########
def test():
    correct = 0
    total = 0
    with torch.no_grad():
        for data in test_loader:
            inputs, target = data
            outputs = model(inputs)
            _, predicted = torch.max(outputs.data, dim=1)
            total += target.size(0)
            correct += (predicted == target).sum().item()
    print('Accuracy on test set: %d %%' % (100 * correct / total))
    return 100 * correct / total

######### main ##########
if __name__ == '__main__':
    accuracy_history = []
    epoch_history = []
    for epoch in range(50):
        train(epoch)
        accuracy = test()
        accuracy_history.append(accuracy)
        epoch_history.append(epoch)
    plt.plot(epoch_history, accuracy_history)
    plt.xlabel('epoch')
    plt.ylabel('accuracy(%)')
    plt.show()

使用GPU版本

  • 设置模型训练设备

    python 复制代码
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
  • 把模型放入GPU

    python 复制代码
    model.to(device)
  • 把数据放入GPU

    python 复制代码
    inputs, target = inputs.to(device), target.to(device)
python 复制代码
import torch
import matplotlib.pyplot as plt
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F

########## 准备数据集 ##########
batch_size = 64
## 实例化转换器
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307,), (0.3081,))
])
train_dataset = datasets.MNIST(root='./dataset/mnist/',
                               train=True,
                               download=False,
                               transform=transform)
train_loader = DataLoader(train_dataset,
                          shuffle=True,
                          batch_size=batch_size)
test_dataset = datasets.MNIST(root='./dataset/mnist/',
                              train=False,
                              download=False,
                              transform=transform)
test_loader = DataLoader(test_dataset, 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) # 卷积层1
        self.conv2 = torch.nn.Conv2d(10, 20, kernel_size=5) # 卷积层2
        self.pooling = torch.nn.MaxPool2d(2)  # 池化层
        self.fc = torch.nn.Linear(320, 10)  # 全连接层

    def forward(self, x):
        batch_size = x.size(0)
        ## 先输入卷积层 在输入池话层 最后输入到relu中做非线性变换
        # 1
        x = F.relu(self.pooling(self.conv1(x)))
        # 2
        x = F.relu(self.pooling(self.conv2(x)))
        ## 全连接层
        # 先把输入平铺 flatten 操作
        x = x.view(batch_size, -1)
        x = self.fc(x)
        return x

model = Net()
## 使用gpu
if torch.cuda.is_available():
    print("使用gpu训练")
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
## 将模型放入设备
model.to(device)
########## 损失函数核优化器定义 ##########
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr = 0.01, momentum=0.5)

########## 模型训练 ##########
def train(epoch):
    running_loss = 0.0
    for batch_index, data in enumerate(train_loader, 0):
        inputs, target = data
        ## 将数据放入设备
        inputs, target = inputs.to(device), target.to(device)
        optimizer.zero_grad()

        # forward
        outputs = model(inputs)
        loss = criterion(outputs, target)
        # backward
        loss.backward()
        # update
        optimizer.step()

        running_loss += loss.item()
        if batch_index % 300 == 299:
            print('[%d %5d] loss: %.3f' % (epoch + 1, batch_index + 1, running_loss / 300))
            running_loss = 0.0

########## 模型测试 ##########
def test():
    correct = 0
    total = 0
    with torch.no_grad():
        for data in test_loader:
            inputs, target = data
            ## 将数据放入设备
            inputs, target = inputs.to(device), target.to(device)
            outputs = model(inputs)
            _, predicted = torch.max(outputs.data, dim=1)
            total += target.size(0)
            correct += (predicted == target).sum().item()
    print('Accuracy on test set: %d %%' % (100 * correct / total))
    return 100 * correct / total

######### main ##########
if __name__ == '__main__':
    accuracy_history = []
    epoch_history = []
    for epoch in range(50):
        train(epoch)
        accuracy = test()
        accuracy_history.append(accuracy)
        epoch_history.append(epoch)
    plt.plot(epoch_history, accuracy_history)
    plt.xlabel('epoch')
    plt.ylabel('accuracy(%)')
    plt.show()
相关推荐
海棠AI实验室12 分钟前
AI的进阶之路:从机器学习到深度学习的演变(三)
人工智能·深度学习·机器学习
AIGC大时代41 分钟前
如何使用ChatGPT辅助文献综述,以及如何进行优化?一篇说清楚
人工智能·深度学习·chatgpt·prompt·aigc
人机与认知实验室3 小时前
人、机、环境中各有其神经网络系统
人工智能·深度学习·神经网络·机器学习
靴子学长8 小时前
基于字节大模型的论文翻译(含免费源码)
人工智能·深度学习·nlp
海棠AI实验室9 小时前
AI的进阶之路:从机器学习到深度学习的演变(一)
人工智能·深度学习·机器学习
四口鲸鱼爱吃盐10 小时前
Pytorch | 从零构建GoogleNet对CIFAR10进行分类
人工智能·pytorch·分类
leaf_leaves_leaf11 小时前
win11用一条命令给anaconda环境安装GPU版本pytorch,并检查是否为GPU版本
人工智能·pytorch·python
夜雨飘零111 小时前
基于Pytorch实现的说话人日志(说话人分离)
人工智能·pytorch·python·声纹识别·说话人分离·说话人日志
四口鲸鱼爱吃盐11 小时前
Pytorch | 从零构建MobileNet对CIFAR10进行分类
人工智能·pytorch·分类
苏言の狗11 小时前
Pytorch中关于Tensor的操作
人工智能·pytorch·python·深度学习·机器学习