一、基本概念
CNN的三大特点:
1、局部感知
在传统神经网络中每个神经元都要与图片上每个像素相连接,这样的话就会造成权重(参数)的数量巨大,从而造成网络难以训练。而在含有卷积层的的神经网络中每个神经元的权重个数都是卷积核的大小,这样就相当于每个神经元只与对应图片部分的像素相连接,极大的减少了权重的数量。
2、权值共享
卷积核的权重通过学习得到且在卷积过程中卷积核的权重不会改变,这是权值共享的思想。
图像数据的特征具有空间一致性,即相邻像素的特性往往密切相关。权值共享可以捕捉到这种空间一致性,从而更好地提取图像特征。
3、多层级特征抽象
底层神经元学习到的是一些简单的局部特征,如边缘、纹理等。
中间层神经元则能够组合这些底层特征,学习到一些更抽象的中间级特征。
顶层神经元最终学习到了数据的高度抽象特征,如物体的语义信息等。
深度神经网络之所以能够从底层特征逐步学习到抽象的高层语义信息,是因为每一层的神经元都在基于前一层的输出提取新的信息,逐渐将简单的局部特征组合成更加复杂的特征。
池化的好处和坏处:
池化是卷积神经网络(CNN)中常用的一种操作,用于减少特征图的空间尺寸(即高度和宽度)
从而减小模型的计算量和参数数量,同时保持重要的特征信息。池化层的主要作用包括降维、防止过拟合、提高计算效率以及增强特征的平移不变性。
池化又被称作,子采样,降采样,汇聚。
常见的池化层类型
最大池化(Max Pooling):
在特征图的每个局部区域中选择最大的值作为该区域的输出。
常用的最大池化操作是使用 2x2 的池化窗口和步幅为2。
平均池化(Average Pooling):
在特征图的每个局部区域中计算平均值作为该区域的输出。
同样可以使用 2x2 的池化窗口和步幅为2。
池化操作会丢失一部分空间信息,特别是细节信息。这对于需要精确位置或细粒度信息的任务(如目标检测、图像分割等)可能不利,可能导致分辨率下降,影响模型性能。
全卷积网络
1、图像分割
图像分割(Image Segmentation)是一种计算机视觉领域Q的技术,旨在将图像分成若干个特定的、具有语义意义性质的区域。图像分割可以用于许多领域,包括目标检测、图像编辑、医学图像分析等。它是由图像处理到图像分析的关键步骤。
2、全卷积网络
参考链接:
全卷积网络是一种特殊类型的神经网络结构,通常用于图像分割、语义分割和其他像素级别的任务。与传统的卷积神经网络(CNN)相比,全卷积神经网络在最后几层使用了全局平均池化(global average pooling)或者转置卷积(transposed convolution)等操作,以便可以接受任意尺寸的输入并输出相应尺寸的输出。
传统的卷积神经网络(CNN)通常在前几层通过卷积和池化操作来提取特征,并在最后几层通过全连接层来输出固定大小的特征向量。这种结构适合用于对整个图像进行分类,但不适用于需要像素级别输出的任务,比如图像分割。
全卷积神经网络通过将全连接层替换为全局平均池化或转置卷积操作,使得网络可以接受任意尺寸的输入,并输出相应尺寸的特征图。这样一来,全卷积神经网络可以直接对输入图像的每个像素进行预测,从而适用于图像分割等像素级别的任务。
转置卷积
一些地方又被称作反卷积,上采样。
在深度学习中是卷积操作的逆向过程,可以根据卷积核的大小和输出的大小,恢复卷积前的图像尺寸,而不是恢复原始值。
参考链接:【机器学习】详解 转置卷积 (Transpose Convolution)-优快云博客
全局平均池化
低级特征、中级特征、高级特征
底层神经元学习到的是一些简单的局部特征,如边缘、纹理等。
中间层神经元则能够组合这些底层特征,学习到一些更抽象的中间级特征。
顶层神经元最终学习到了数据的高度抽象特征,如物体的语义信息等。
多通道:N输入和M输出是如何实现的?
实际上这个问题就是输入层和输出层的维度匹配问题
这里有几个概念
epoch、batch、batch size和iterations
epoch
在训练一个模型时所用到的全部数据;
备注:一般在训练时都要使用多于一个的epoch,因为在神经网络中传递完整的数据集仅仅一次是不够的,只有将完整的数据集在同样的神经网络中传递多次,才会得到比较优秀的训练效果,当然也不行,容易过拟合,所以要根据实验选择自己最合适的。
epochs:
epochs被定义为向前和向后传播中所有批次的单次训练迭代。这意味着一个周期是整个数据的单次向前和向后传递。简单说,epochs指的就是训练过程中数据将被“轮”多少次,就这样。
batch
Keras中参数更新是按批进行的,就是小批的梯度下降算法。如果准备跑模型的数据量太大,此时自己的电脑可能承受不住,所以可以适当的将数据分成几块,就是分成几个batch。每次的参数更新有两种方式:
第一种,遍历全部数据集算一次损失函数,然后算函数对各个参数的梯度,更新梯度。这种方法每更新一次参数都要把数据集里的所有样本都看一遍,计算量开销大,计算速度慢,不支持在线学习,这称为批梯度下降。
另一种,每看一次数据就算一下损失函数,然后求梯度更新参数,这个称为随机梯度下降,这个方法速度比较快,但是瘦脸性能不太好,可能在最优点附近晃来晃去,找不到最优点。两次参数的更新也有可能互相抵消掉,造成目标函数震荡的比较剧烈。
batch-size
一个batch中的数据量大小即为batch size,一般为2n,比如32,64,128等等。
iterations
iterations(迭代):每一次迭代都是一次权重更新,每一次权重更新需要batch_size个数据进行Forward运算得到损失函数,在BP算法更新参数。1个iteration等于使用batchsize个样本训练一次。
迭代,即batch size需要完成一次epoch的次数
举两个例子:
比如现在我们有一个2000大小的训练样本,然后我们将这2000个样本分成4个大小为500的小数据集样本,此时epoch=1(暂且就用这个样本训练1次)。 请问以下数值分别为多少:①batch;②batch size;③iterations;
-
batch:这是每次用于训练的一个小数据集。在这个例子中,您将 2000 个样本分成 4 个小数据集,每个数据集就是一个 batch。因此,batch 指的是每一小组数据,您总共有 4 个 batch。
-
batch size:这是每个 batch 中的样本数。在这个例子中,每个 batch 包含 500 个样本。因此,batch size = 500。
-
iterations:这是指在一个 epoch 中完成所有样本训练所需的批次数。因为您将 2000 个样本分成了 4 个 batch,所以 iterations = 4(即在一个 epoch 中完成训练需要 4 次迭代)。
Fashion Mnist数据集有70000个灰度图像,其中60000张图片作为训练数据,10000张图片作为测试数据。假设现在选择Batch Size=100对模型进行训练。迭代30000次。 每个Epoch要训练的图片数量:60000(训练集上的所有图像) 请问:①训练集具有的Batch个数;②每个Epoch需要完成的Batch个数;③每个Epoch具有的Iteration个数;④每个Epoch中发生模型权重更新的次数;⑤训练10个Epoch后,模型权重更新的次数;
1. 训练集具有的 Batch 个数
训练集中的样本总数为 60,000,每个 batch 有 100 个 样本:
Batch 数量=60000➗100=600
2. 每个 Epoch 需要完成的 Batch 个数
每个 Epoch 需要遍历整个训练集,因此需要完成的 Batch 个数和训练集的 Batch 个数相同:
每个 Epoch 的 Batch 个数=600
3. 每个 Epoch 具有的 Iteration 个数
在每个 Epoch 中,Iteration 数量与 Batch 个数相同,因此:
每个 Epoch 的 Iteration 个数=600
4. 每个 Epoch 中发生模型权重更新的次数
模型的权重在每个 Batch 训练后都会更新,因此每个 Epoch 中的权重更新次数等于 Batch 个数:
每个 Epoch 的权重更新次数=600
5. 训练 10 个 Epoch 后,模型权重更新的次数
在 10 个 Epoch 中,模型权重更新的总次数为每个 Epoch 的更新次数乘以 Epoch 数量:
训练 10 个 Epoch 的权重更新次数=600×10=6000
通道
卷积核的数量决定输出的通道数,比如说现在有一张像素为16*16的三通道图片(16*16*3),其实这张照片就由三个16*16的矩阵组成,如果这时我们有256个3*3*3的卷积核,其实就是每个卷积核由3个3*3的矩阵,有256个这样的卷积核。那么这张16*16*3的图片要和256个3*3*3的卷积核都进行点积并相加得出特征图,即得到的特征图有256个,即卷积核的个数,也是输出通道的个数。
为什么要增加通道? 要那么多通道有什么用?
在一张照片中可能有很多信息,比如人,动物....,我们人眼可以一下子就分辨出来,但是计算机不可以,他要进行特征提取,也是卷积的第一个操作。
我们增加通道数就代表着增加特征,而造成通道数增加的操作其实就是卷积核的增加,不同的卷积核可以提取到不同特征,比如说平滑卷积核,它可以让整个图像更加平滑清晰,还比如增加水平边界过滤器,垂直边界过滤器(本质都是卷积核),让图像的矩阵和卷积核进行点积相加,得到不同的矩阵,即不同的特征图,这些特征图越多,越利于计算机学习,这将教会计算机识别特征。
因为不同的卷积核可以分辨出不同的特征,所以增加卷积核的个数很必要,计算机通过利用这些特征图,来最终得到结论,分辨出图像的事物到底是什么。
深度学习的通道到底是什么?有什么用?(小白可看)_深度学习 通道-优快云博客
最后那么多的通道,是怎么缩小到自己想要的分类数量的?
靠的就是最后的全连接层
这里的全连接层就是前面的前馈神经网络
1×1的卷积核有什么用?
1×1卷积核主要功能是改变通道数目,致使减少计算量。在使用1×1卷积核的过程中,不改变原始图片的宽度和高度,它只是改变了通道数。它同时对原始图片的所有信道进行卷积,融合成一个值
为什么不直接相加呢?还卷积一下再相加
如果直接相加,那就超过256了,一般图像的位深度为8,所以要加权相加
二、基于CNN的XO识别
模型训练
import torch
from torchvision import transforms, datasets
import torch.nn as nn
from torch.utils.data import DataLoader
import torch.optim as optim
transforms = transforms.Compose([
transforms.ToTensor(), # 把图片进行归一化,并把数据转换成Tensor类型
transforms.Grayscale(1) # 把图片 转为灰度图
])
path = r'G:\大三上学期\深度学习\作业7\train_test'
path_test = r'G:\大三上学期\深度学习\作业7\test_data'
data_train = datasets.ImageFolder(path, transform=transforms)
data_test = datasets.ImageFolder(path_test, transform=transforms)
print("size of train_data:", len(data_train))
print("size of test_data:", len(data_test))
data_loader = DataLoader(data_train, batch_size=64, shuffle=True)
data_loader_test = DataLoader(data_test, batch_size=64, shuffle=True)
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 9, 3)
self.maxpool = 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.maxpool(self.relu(self.conv1(x)))
x = self.maxpool(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 = Net()
criterion = torch.nn.CrossEntropyLoss() # 损失函数 交叉熵损失函数
optimizer = optim.SGD(model.parameters(), lr=0.1) # 优化函数:随机梯度下降
epochs = 10
for epoch in range(epochs):
running_loss = 0.0
for i, data in enumerate(data_loader):
images, label = data
out = model(images)
loss = criterion(out, label)
optimizer.zero_grad()
loss.backward()
optimizer.step()
running_loss += loss.item()
if (i + 1) % 10 == 0:
print('[%d %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 100))
running_loss = 0.0
print('finished train')
# 保存模型
torch.save(model, 'model_name.pth') # 保存的是模型, 不止是w和b权重值
测试
import torch
import matplotlib.pyplot as plt
from torchvision import transforms, datasets
import torch.nn as nn
from torch.utils.data import DataLoader
transforms = transforms.Compose([
transforms.ToTensor(), # 把图片进行归一化,并把数据转换成Tensor类型
transforms.Grayscale(1) # 把图片 转为灰度图
])
path = r'G:\大三上学期\深度学习\作业7\train_test'
path_test = r'G:\大三上学期\深度学习\作业7\test_data'
data_train = datasets.ImageFolder(path, transform=transforms)
data_test = datasets.ImageFolder(path_test, transform=transforms)
print("size of train_data:", len(data_train))
print("size of test_data:", len(data_test))
data_loader = DataLoader(data_train, batch_size=64, shuffle=True)
data_loader_test = DataLoader(data_test, batch_size=64, shuffle=True)
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 9, 3)
self.m