pytorch搭建CNN卷积神经网络详解

  • 个人觉得应该先写卷积操作的常见技术和公式操作,才能对卷积输入维度(结果),输出维度(结果)有更直观的了解吧。

  • 简单介绍一下卷积的常用trick:

    • Padding
    • Striding
  • 下方是输入输出公式(本人开始也很困惑,找到对应公式后,就十分明朗了):

    n:原始输入的维度 | f:卷积核的大小 | p:padding的大小| s:stride的大小

    • no padding: n - f + 1
    • padding: n +2p - f + 1
    • stride with padding : n + 2 p − f s + 1 \frac{n+2 p-f}{s} + 1 sn+2pf+1 (该公式包含了上述两种情况)

🌵 ​接下来以手写数字集为例,搭建一个CNN神经网络

1.导入需要使用的包并下载MNIST数据集

  • MNIST数据集:
    • 训练集:图片60000张,每张像素(28, 28), 灰度图所以没有通道数
    • 测试集:图片10000张,每张像素(28, 28)
import torch
import torch.nn as nn
import torch.utils.data as Data
import torchvision
import matplotlib.pyplot as plt

torch.manual_seed(1)   # 为了每次的实验结果一致
# 设置超参数
epoches = 2
batch_size = 50
learning_rate = 0.001

# 训练集
train_data = torchvision.datasets.MNIST(
    root="./mnist/",  # 训练数据保存路径
    train=True,       # True为下载训练数据集,False为下载测试数据集
    transform=torchvision.transforms.ToTensor(),  # 数据范围已从(0-255)压缩到(0,1)
    download=False,  # 是否需要下载
)
# 显示训练集中的第一张图片
print(train_data.train_data.size())   # [60000,28,28]
plt.imshow(train_data.train_data[0].numpy())
plt.show()

# 测试集
test_data = torchvision.datasets.MNIST(root="./mnist/", train=False)
print(test_data.test_data.size())    # [10000, 28, 28]
test_x = torch.unsqueeze(test_data.test_data, dim=1).type(torch.FloatTensor)/255
test_y = test_data.test_labels

# 将训练数据装入Loader中
train_loader = train_loader = Data.DataLoader(dataset=train_data, batch_size=batch_size, shuffle=True, num_workers=3)

2. 搭建CNN神经网络 重点!

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()   # 继承__init__功能
        ## 第一层卷积
        self.conv1 = nn.Sequential(
            # 输入[1,28,28]
            nn.Conv2d(
                in_channels=1,    # 输入图片的高度
                out_channels=16,  # 输出图片的高度
                kernel_size=5,    # 5x5的卷积核,相当于过滤器
                stride=1,         # 卷积核在图上滑动,每隔一个扫一次
                padding=2,        # 给图外边补上0
            ),
            # 经过卷积层 输出[16,28,28] 传入池化层
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2)   # 经过池化 输出[16,14,14] 传入下一个卷积
        )
        ## 第二层卷积
        self.conv2 = nn.Sequential(
            nn.Conv2d(
                in_channels=16,    # 同上
                out_channels=32,
                kernel_size=5,
                stride=1,
                padding=2
            ),
            # 经过卷积 输出[32, 14, 14] 传入池化层
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2)  # 经过池化 输出[32,7,7] 传入输出层
        )
        ## 输出层
        self.output = nn.Linear(in_features=32*7*7, out_features=10)

    def forward(self, x):
        x = self.conv1(x)
        x = self.conv2(x)           # [batch, 32,7,7]
        x = x.view(x.size(0), -1)   # 保留batch, 将后面的乘到一起 [batch, 32*7*7]
        output = self.output(x)     # 输出[50,10]
        return output

3. 实现CNN

def main():
    # cnn 实例化
    cnn = CNN()
    print(cnn)

    # 定义优化器和损失函数
    optimizer = torch.optim.Adam(cnn.parameters(), lr=learning_rate)
    loss_function = nn.CrossEntropyLoss()

    # 开始训练
    for epoch in range(epoches):
        print("进行第{}个epoch".format(epoch))
        for step, (batch_x, batch_y) in enumerate(train_loader):
            output = cnn(batch_x)  # batch_x=[50,1,28,28]
            loss = loss_function(output, batch_y)
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
			# 为了实时显示准确率
            if step % 50 == 0:
                test_output = cnn(test_x)
                pred_y = torch.max(test_output, 1)[1].data.numpy()
                accuracy = ((pred_y == test_y.data.numpy()).astype(int).sum()) / float(test_y.size(0))
                print('Epoch: ', epoch, '| train loss: %.4f' % loss.data.numpy(), '| test accuracy: %.2f' % accuracy)


    test_output = cnn(test_x[:10])
    pred_y = torch.max(test_output, 1)[1].data.numpy().squeeze()
    print(pred_y)
    print(test_y[:10])

if __name__ == "__main__":
    main()
  • 实时结果

在这里插入图片描述

  • 跑完后结果(准确率很高)

在这里插入图片描述

完整代码:

"""
    作者:Troublemaker
    功能:
    版本:
    日期:2020/4/5 19:57
    脚本:cnn.py
"""
import torch
import torch.nn as nn
import torch.utils.data as Data
import torchvision
import matplotlib.pyplot as plt

torch.manual_seed(1)
# 设置超参数
epoches = 2
batch_size = 50
learning_rate = 0.001

# 搭建CNN
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()   # 继承__init__功能
        ## 第一层卷积
        self.conv1 = nn.Sequential(
            # 输入[1,28,28]
            nn.Conv2d(
                in_channels=1,    # 输入图片的高度
                out_channels=16,  # 输出图片的高度
                kernel_size=5,    # 5x5的卷积核,相当于过滤器
                stride=1,         # 卷积核在图上滑动,每隔一个扫一次
                padding=2,        # 给图外边补上0
            ),
            # 经过卷积层 输出[16,28,28] 传入池化层
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2)   # 经过池化 输出[16,14,14] 传入下一个卷积
        )
        ## 第二层卷积
        self.conv2 = nn.Sequential(
            nn.Conv2d(
                in_channels=16,    # 同上
                out_channels=32,
                kernel_size=5,
                stride=1,
                padding=2
            ),
            # 经过卷积 输出[32, 14, 14] 传入池化层
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2)  # 经过池化 输出[32,7,7] 传入输出层
        )
        ## 输出层
        self.output = nn.Linear(in_features=32*7*7, out_features=10)

    def forward(self, x):
        x = self.conv1(x)
        x = self.conv2(x)           # [batch, 32,7,7]
        x = x.view(x.size(0), -1)   # 保留batch, 将后面的乘到一起 [batch, 32*7*7]
        output = self.output(x)     # 输出[50,10]
        return output


# 下载MNist数据集
train_data = torchvision.datasets.MNIST(
    root="./mnist/",  # 训练数据保存路径
    train=True,
    transform=torchvision.transforms.ToTensor(),  # 数据范围已从(0-255)压缩到(0,1)
    download=False,  # 是否需要下载
)
# print(train_data.train_data.size())   # [60000,28,28]
# print(train_data.train_labels.size())  # [60000]
# plt.imshow(train_data.train_data[0].numpy())
# plt.show()

test_data = torchvision.datasets.MNIST(root="./mnist/", train=False)
print(test_data.test_data.size())    # [10000, 28, 28]
# print(test_data.test_labels.size())  # [10000, 28, 28]
test_x = torch.unsqueeze(test_data.test_data, dim=1).type(torch.FloatTensor)[:2000]/255
test_y = test_data.test_labels[:2000]

# 装入Loader中
train_loader = Data.DataLoader(dataset=train_data, batch_size=batch_size, shuffle=True, num_workers=3)


def main():
    # cnn 实例化
    cnn = CNN()
    print(cnn)

    # 定义优化器和损失函数
    optimizer = torch.optim.Adam(cnn.parameters(), lr=learning_rate)
    loss_function = nn.CrossEntropyLoss()

    # 开始训练
    for epoch in range(epoches):
        print("进行第{}个epoch".format(epoch))
        for step, (batch_x, batch_y) in enumerate(train_loader):
            output = cnn(batch_x)  # batch_x=[50,1,28,28]
            # output = output[0]
            loss = loss_function(output, batch_y)
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

            if step % 50 == 0:
                test_output = cnn(test_x)  # [10000 ,10]
                pred_y = torch.max(test_output, 1)[1].data.numpy()
                # accuracy = sum(pred_y==test_y)/test_y.size(0)
                accuracy = ((pred_y == test_y.data.numpy()).astype(int).sum()) / float(test_y.size(0))
                print('Epoch: ', epoch, '| train loss: %.4f' % loss.data.numpy(), '| test accuracy: %.2f' % accuracy)


    test_output = cnn(test_x[:10])
    pred_y = torch.max(test_output, 1)[1].data.numpy().squeeze()
    print(pred_y)
    print(test_y[:10])

if __name__ == "__main__":
    main()
  • 36
    点赞
  • 195
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
PyTorch是现代的深度学习框架,为研究人员和开发人员提供了很好的工具和支持。在PyTorch中,我们可以轻松地搭建3D卷积神经网络。 首先,我们需要导入必要的包。PyTorch包含了torch.nn模块,它提供我们搭建神经网络所需的各种工具和模块。我们还需要一个包,就是torchvision.models模块,里面包含已经搭好的模型,我们可以使用它们。 接着,我们要定义我们的3D卷积神经网络。定义方法如下: ```python import torch.nn as nn class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv3d(1, 64, kernel_size=3, padding=1) self.bn1 = nn.BatchNorm3d(64) self.relu1 = nn.ReLU(inplace=True) self.conv2 = nn.Conv3d(64, 128, kernel_size=3, padding=1) self.bn2 = nn.BatchNorm3d(128) self.relu2 = nn.ReLU(inplace=True) self.conv3 = nn.Conv3d(128, 256, kernel_size=3, padding=1) self.bn3 = nn.BatchNorm3d(256) self.relu3 = nn.ReLU(inplace=True) self.pool = nn.MaxPool3d((2, 2, 2)) self.fc1 = nn.Linear(256 * 8 * 8 * 8, 1024) self.fc2 = nn.Linear(1024, 10) def forward(self, x): x = self.conv1(x) x = self.bn1(x) x = self.relu1(x) x = self.conv2(x) x = self.bn2(x) x = self.relu2(x) x = self.conv3(x) x = self.bn3(x) x = self.relu3(x) x = self.pool(x) x = x.view(-1, 256 * 8 * 8 * 8) x = self.fc1(x) x = self.fc2(x) return x ``` 这里我们定义了一个名为Net的类。在__init__函数中,我们定义了三层卷积层,每一层后面跟着一个BatchNormalization层和ReLU激活层。之后我们定义一个池化层,最后是两层全连接层,其中第二层的输出是类别数目。 在forward函数中,我们把输入x通过卷积层、池化层、全连接层的顺序处理,最后输出。 接着,我们就可以对我们的三维数据进行训练了,使用PyTorch内置的optim包进行优化器的定义,再使用loss进行计算。 其中,数据需要先引入PyTorch,再进行一些简单的预处理,然后导入DataLoader中,以便进行网络训练。 ```python import torch.optim as optim net = Net() criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(net.parameters(), lr=0.001) trainloader = DataLoader(train_dataset, batch_size=16, shuffle=True, num_workers=4) ``` 最后,我们就可以进行训练了。在训练过程中,我们一般选择mini-batch的方式进行,即把数据集分成若干个小批次进行训练,并在每个小批次训练完后更新网络权重。 ```python for epoch in range(10): running_loss = 0.0 for i, data in enumerate(trainloader, 0): inputs, labels = data optimizer.zero_grad() outputs = net(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() running_loss += loss.item() if i % 100 == 99: print('[%d, %5d] loss: %.3f' % (epoch+1, i+1, running_loss/100)) running_loss = 0.0 print('Finished Training') ``` 随着迭代次数的增加,我们的网络会逐渐提高准确性。在训练完整个数据集后,我们可以对网络进行评估并进行可视化分析。 以上是使用PyTorch搭建3D卷积神经网络的过程。我们可以通过PyTorch提供的工具和模块,轻松地建立自己的卷积神经网络,并进行训练、评估。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值