NNDL 作业7 基于CNN的XO识别

一、概念解释

        1.局部感知:相较于全连接神经网络,卷积神经网络中相邻两层神经元之间的神经元只是部分连接,只感知局部,而不像全连接神经网络那样获取所有神经元之间的信息。也就是说,卷积神经网络中只是感知了局部,而不是整幅图像。卷积神经网络中局部感知的实现是通过卷积核“互相关”操作实现的。

        2.权值共享:在卷积神经网络中,对输入的图片进行卷积时,对于同一个特征的提取,卷积核的参数是共享的,即卷积核中的参数是相同的。

         3.池化带来哪些好处和坏处?

           好处:

                1.减少计算复杂度:池化可以起到降维的作用,减少参数量。

                2.防止过拟合:通过减少模型的参数量,限制模型对训练数据的过拟合。

                3. 特征提取,从输入的数据中提取出重要特征。

        坏处:

                会造成细节的信息丢失,池化操作会丢弃一部分特征激活,这可能导致位置信息的丢失。

            4.全卷积网络

                FCN对图像进行像素级的分类。与经典的CNN在卷积层之后使用全连接层得到固定长度的特征 向 量进行分类(全联接层+softmax输出)不同,FCN可以接受任意尺寸的输入图像,采用反卷积层对最后一个卷积层的feature map进行上采样, 使它恢复到输入图像相同的尺寸,从而可以对每个像素都产生了一个预测, 同时保留了原始输入图像中的空间信息, 最后在上采样的特征图上进行逐像素分类。最后逐个像素计算softmax分类的损失, 相当于每一个像素对应一个训练样本。

简单的来说,FCN与CNN的区域在把于CNN最后的全连接层换成卷积层。

                4.低级特征、中级特征、高级特征

                低级特征、中级特征和高级特征是特征提取的三个层次,分别对应于神经网络的底层、         中间层和较深层次。

                低级特征主要包含图像的底层信息,如颜色、纹理等。这些特征是图像中最基本的、最          直观的特征,通常用于描述图像的表面信息。

                中级特征往往包括对象信息,以及形状和空间信息等。它们通常是在网络的中间层次进         行提取的特征,具有比低级特征更高层次的抽象和语义含义。中级特征可以将低级特征组合           起 来,形成更具有代表性和抽象性的特征表示。

                高级特征往往包含对象内在的语义信息。这些特征是在神经网络的较深层次中提取的抽         象和语义丰富的特征表示。它们通过对中级特征的进一步组合和整合,能够对整体图像的语           义 信息和高层次结构进行建模。

                这三个层次的特征分别对应于神经网络的不同层次,从低级到高级,从局部到整体,从         表面信息到语义信息,逐渐提升对图像的理解和抽象表示。

                5.多通道。N输入,M输出是如何实现的?

                对于N个输入通道,每个通道都有自己的输入数据,这些数据通过独立的卷积层进行特            征提取。然后,这些特征图会被拼接(concatenation)或者融合(fusion)起来,形成更具            有代表性的特征表示。这个过程可以在网络的不同层次中进行多次,以逐步提取和整合更               高级的特征信息。

                6.1x1的卷积核有什么作用

                  降维;增加非线性(接一个非线性激活函数)。

二、使用CNN进行XO识别 

        1、已有的网络模型复现:

import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torchvision import transforms, datasets

transforms = transforms.Compose([
    transforms.ToTensor(),  # 把图片进行归一化,并把数据转换成Tensor类型
    transforms.Grayscale(1)  # 把图片 转为灰度图
])

data_train = datasets.ImageFolder(r"D:\BaiduNetdiskDownload\training_data_sm\train_data", transforms)
data_test = datasets.ImageFolder(r"D:\BaiduNetdiskDownload\training_data_sm\test_data", transforms)

train_loader = DataLoader(data_train, batch_size=64, shuffle=True)
test_loader = DataLoader(data_test, batch_size=64, shuffle=True)
for i, data in enumerate(train_loader):
    images, labels = data
    print(images.shape)
    print(labels.shape)
    break

for i, data in enumerate(test_loader):
    images, labels = data
    print(images.shape)
    print(labels.shape)
    break
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 9, 3)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(9, 5, 3)
        self.relu = nn.ReLU()
        self.fc1 = nn.Linear(27*27*5, 1200)
        self.fc2 = nn.Linear(1200, 64)
        self.fc3 = nn.Linear(64, 2)

    def forward(self, x):
        x = self.pool(self.relu(self.conv1(x)))
        x = self.pool(self.relu(self.conv2(x)))
        x = x.view(-1,27*27*5)
        x = self.relu(self.fc1(x))
        x = self.relu(self.fc2(x))
        x = self.fc3(x)
        return x
model = CNN()

loss = nn.CrossEntropyLoss()
opti = torch.optim.SGD(model.parameters(), lr=0.1)

epochs = 10

for epoch in range(epochs):
    total_loss = 0
    for i, data in enumerate(train_loader):
        images, labels = data
        out = model(images)
        one_loss = loss(out, labels)
        opti.zero_grad()
        one_loss.backward()
        opti.step()
        total_loss += one_loss
        if (i + 1) % 10 == 0:
            print('[%d  %5d]   loss: %.3f' % (epoch + 1, i + 1, total_loss / 100))
            total_loss = 0.0

print('finished train')

# 保存模型
torch.save(model, 'model.pth')
import matplotlib.pyplot as plt

# 读取模型
model_load = torch.load('model.pth')
# 读取一张图片 images[0],测试
print("labels[0] truth:\t", labels[0])
x = images[0].unsqueeze(0)
predicted = torch.max(model_load(x), 1)
print("labels[0] predict:\t", predicted.indices)

img = images[0].data.squeeze().numpy()
plt.imshow(img, cmap='gray')
plt.show()

model_load = torch.load('model.pth')

correct = 0
total = 0
with torch.no_grad():
    for data in test_loader:
        images, labels = data
        outputs = model_load(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()
print('Accuracy of the network on the  test images: %f %%' % (100. * correct / total))

训练过程:

[1     10]   loss: 0.069
[1     20]   loss: 0.068
[2     10]   loss: 0.055
[2     20]   loss: 0.038
[3     10]   loss: 0.039
[3     20]   loss: 0.015
[4     10]   loss: 0.005
[4     20]   loss: 0.004
[5     10]   loss: 0.004
[5     20]   loss: 0.002
[6     10]   loss: 0.001
[6     20]   loss: 0.003
[7     10]   loss: 0.001
[7     20]   loss: 0.001
[8     10]   loss: 0.001
[8     20]   loss: 0.001
[9     10]   loss: 0.001
[9     20]   loss: 0.001
[10     10]   loss: 0.000
[10     20]   loss: 0.000
finished train

Loss变化: 

 

测试集上的准确率:

Accuracy of the network on the  test images: 100.000000 %

2.更改网络模型:增加一个卷积层

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 9, 3)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(9, 5, 3)
        self.conv3=nn.Conv2d(5,2,3)
        self.relu = nn.ReLU()
        self.fc1 = nn.Linear(12*12*2, 1200)
        self.fc2 = nn.Linear(1200, 64)
        self.fc3 = nn.Linear(64, 2)

    def forward(self, x):
        x = self.pool(self.relu(self.conv1(x)))
        x = self.pool(self.relu(self.conv2(x)))
        x=self.pool(self.relu(self.conv3(x)))
        x = x.view(-1,12*12*2)
        x = self.relu(self.fc1(x))
        x = self.relu(self.fc2(x))
        x = self.fc3(x)
        return x

训练结果:

[1     10]   loss: 0.069
[1     20]   loss: 0.069
[2     10]   loss: 0.068
[2     20]   loss: 0.067
[3     10]   loss: 0.050
[3     20]   loss: 0.035
[4     10]   loss: 0.007
[4     20]   loss: 0.009
[5     10]   loss: 0.004
[5     20]   loss: 0.003
[6     10]   loss: 0.001
[6     20]   loss: 0.002
[7     10]   loss: 0.001
[7     20]   loss: 0.001
[8     10]   loss: 0.000
[8     20]   loss: 0.000
[9     10]   loss: 0.000
[9     20]   loss: 0.000
[10     10]   loss: 0.000
[10     20]   loss: 0.000
finished train
labels[0] truth:	 tensor(0)
labels[0] predict:	 tensor([0])
Accuracy of the network on the  test images: 100.000000 %

Loss变化:

 

        从以上两个损失值变化曲线来看,后者的损失值下降会更快一些,模型的收敛速度更快。

        3.去掉池化层

        准确率只有百分之五十了。

        Loss:

        去掉池化层之后,模型训练的速度变得非常慢,还导致损失值相对比较高。由此可见,汇聚层对加快模型收敛速度和降低参数量都有着非常重要的作用。 

        4、修改通道数等超参数

        适当减少或者增加通道数,模型的损失值下降速度变化不大,准确率基本上都维持在了100%。学习率调大的话,很容易导致模型不收敛。

卷积后的特征图

激活之后的特征图 

 

池化之后的特征图 

 

        部分卷积核:

 

                根据实际测试,本实验中的模型不同层得到的特征区别并不大。


总结:

        首先,这次实验让我对DataLoader这个函数有了更深的了解,知道这个批量加载的整个过程。批量加载完所有数据之后才是一轮。其次就是对卷积神经网络的整个流程更加熟悉,能熟练计算第一个全连接层的第一个参数量。

参考链接: 

【2021-2022 春学期】人工智能-作业6:CNN实现XO识别

  NNDL 作业6:基于CNN的XO识别

 

 

 

                      

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值