🎬个人简介:一个全栈工程师的升级之路!
📋个人专栏:pytorch深度学习
🎀CSDN主页 发狂的小花
🌄人生秘诀:学习的本质就是极致重复!
《PyTorch深度学习实践》完结合集_哔哩哔哩_bilibili
目录
1 卷积神经网络
2 拆解卷积
3 特征提取+分类
1 卷积神经网络
CNN,用于特征提取,但是计算量大,卷积算子是一个计算密集型算子,工业界优化卷积算子是一个重大的任务。有LeNet、AlexNet、VGG系列、ResNet、很多深度学习框架都提供了丰富的CNN模型实现个训练的接口。
- ResNet深度残差网络:
Resnet50(深度残差网络),图像分类网络,2015年何凯明提出。残差是在正常的神经网络中加了一个short cut 分支结构,也称为高速公路。这样网络就不是单纯卷积的输出F(x),而是卷积的输出和前面输入的叠加F(x)+X,可以很好的解决训练过程中的梯度消失问题。被证明具有很强的图像特征提取能力,一般作为一种特征提取器来使用。常用来作为back bone,即骨干网络。也被用来测试AI芯片的性能指标。
- 为什么重要?
(1)常被用来做back bone,例如 YoLo-v3 ,被用来作为特征提取器,特斯拉的占用网络
(2)性能标杆
- ResNet包含的算法:
(1)卷积算法
卷积是CNN网络的核心,对图片或者特征图进行进一步的特征提取,从而实现在不同尺度下的特征提取或者特征融合。
(2)激活(relu)
卷积是乘加运算,属于线性运算,使用激活函数是为了引入非线性因素,提高泛化能力,将一部分神经元激活,而将另一部分神经元关闭。
(3)池化
池化层主要是为了降维,减少运算量,同时可以保证输出特征图中的关键特征
(4)加法
残差结构,解决梯度消失问题
(5)全连接
全连接层,称为Linear层或者FC层,将所有学习到的特征进一步融合,并映射到样本空间的特征上,输出与样本对应。全连接层之后会加一个Softmax,完成多分类。
2 拆解卷积
- 卷积为什么重要
(1)通过卷积核局部感知图像,感受野(有点像人眼盯着某一个地方看)
(2)滑动以获取全局特征(有点像人眼左看右看物体)
(3)权重矩阵(记忆)
- 特征图(Feature Map)
卷积操作从输入图像提取的特征图,即卷积算法的输出结果,包含了输入图像的抽象特征。
- 感受野
卷积核在输入图像上的滑动扫描过程,表示一个输出像素“看到”的输入图像中区域的大小,注意是从输出来看。如果将卷积比作窗户,那么感受野就是一个输出像素透过这个窗户可以看到的输入图片的范围。
感受野影响神经网络对于图像的理解和图像特征的提取。大的感受野可以使得神经网络理解图像的全局信息,从而提取全局特征。小的感受野只能捕捉图像的局部特征。
- 2个3x3卷积替代5x5卷积的意义?
首先可以替代是因为从输出元素看,2个3x3卷积和1个5x5卷积,具有相同的感受野。
优势:
(1)2个3x3卷积的卷积核参数量为3x3+3x3=18,而1个5x5=25
(2)一个卷积变成两个卷积,加深了神经网络的层数,从而在卷积后面引入更多的非线性层,增加了非线性能力。
- 卷积公式
输出通道就是卷积核的个数
- Padding参数
指的是在输入图像的周围添加的额外的像素值,用来扩大输入图像的尺寸,这些额外填充的像素值通常设置为0,卷积在这个填充后的图像上进行。
Padding主要是为了防止边缘信息的损失,保持输出大小与输入大小一致。
需要填充的场景:
(1)相同卷积(输入和输出尺寸一致)
(2)处理小物体,边缘像素卷积运算较少,多次卷积容易丢失在边缘的小物体,Padding可以提高
(3)网络设计灵活
- Stride 参数
卷积核在活动过程中每次跳过的像素的数量,可以减少计算量、控制Feature Map输出的大小,一定程度上防止过拟合,这是通过降低模型的复杂度来实现的。
Dilation 参数和空洞卷积
dilation指的是卷积核元素之间的间距,决定卷积核在输入数据上的覆盖范围。增大dilation,增大感受野,由此引入了空洞卷积。
空洞卷积扩大了卷积核的感受野,但却不增加卷积核的尺寸,减少运算量;可以解决大尺寸输入图像的问题;可以处理遥远像素之间的关系。
- 卷积长、宽推导
除了以上的三个tensor,还有计算卷积的三个参数,Padding、stride、dilation,这样才构成一个完整的卷积运算。
无参数推导:
加padding推导:
加上stride推导:
加上dilation推导:
3 特征提取+分类
输入->卷积->输出
一个简单的神经网络:
一些代码说明:
代码说明:
1、torch.nn.Conv2d(1,10,kernel_size=3,stride=2,bias=False)
1是指输入的Channel,灰色图像是1维的;10是指输出的Channel,也可以说第一个卷积层需要10个卷积核;kernel_size=3,卷积核大小是3x3;stride=2进行卷积运算时的步长,默认为1;bias=False卷积运算是否需要偏置bias,默认为False。padding = 0,卷积操作是否补0。
2、self.fc = torch.nn.Linear(320, 10),这个320获取的方式,可以通过x = x.view(batch_size, -1) # print(x.shape)可得到(64,320),64指的是batch,320就是指要进行全连接操作时,输入的特征维度。
CPU代码:
import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch.optim as optim
# prepare dataset
batch_size = 64
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
train_dataset = datasets.MNIST(root='../dataset/mnist/', train=True, download=True, transform=transform)
train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)
test_dataset = datasets.MNIST(root='../dataset/mnist/', train=False, download=True, transform=transform)
test_loader = DataLoader(test_dataset, shuffle=False, batch_size=batch_size)
# design model using class
class Net(torch.nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = torch.nn.Conv2d(1, 10, kernel_size=5)
self.conv2 = torch.nn.Conv2d(10, 20, kernel_size=5)
self.pooling = torch.nn.MaxPool2d(2)
self.fc = torch.nn.Linear(320, 10)
def forward(self, x):
# flatten data from (n,1,28,28) to (n, 784)
batch_size = x.size(0)
x = F.relu(self.pooling(self.conv1(x)))
x = F.relu(self.pooling(self.conv2(x)))
x = x.view(batch_size, -1) # -1 此处自动算出的是320
x = self.fc(x)
return x
model = Net()
# construct loss and optimizer
criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
# training cycle forward, backward, update
def train(epoch):
running_loss = 0.0
for batch_idx, data in enumerate(train_loader, 0):
inputs, target = data
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, target)
loss.backward()
optimizer.step()
running_loss += loss.item()
if batch_idx % 300 == 299:
print('[%d, %5d] loss: %.3f' % (epoch+1, batch_idx+1, running_loss/300))
running_loss = 0.0
def test():
correct = 0
total = 0
with torch.no_grad():
for data in test_loader:
images, labels = data
outputs = model(images)
_, predicted = torch.max(outputs.data, dim=1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('accuracy on test set: %d %% ' % (100*correct/total))
if __name__ == '__main__':
for epoch in range(10):
train(epoch)
test()
GPU代码:
import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch.optim as optim
import matplotlib.pyplot as plt
# prepare dataset
batch_size = 64
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
train_dataset = datasets.MNIST(root='./dataset/mnist/', train=True, download=True, transform=transform)
train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)
test_dataset = datasets.MNIST(root='./dataset/mnist/', train=False, download=True, transform=transform)
test_loader = DataLoader(test_dataset, shuffle=False, batch_size=batch_size)
# design model using class
class Net(torch.nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = torch.nn.Conv2d(1, 10, kernel_size=5)
self.conv2 = torch.nn.Conv2d(10, 20, kernel_size=5)
self.pooling = torch.nn.MaxPool2d(2)
self.fc = torch.nn.Linear(320, 10)
def forward(self, x):
# flatten data from (n,1,28,28) to (n, 784)
batch_size = x.size(0)
x = F.relu(self.pooling(self.conv1(x)))
x = F.relu(self.pooling(self.conv2(x)))
x = x.view(batch_size, -1) # -1 此处自动算出的是320
# print("x.shape",x.shape)
x = self.fc(x)
return x
model = Net()
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
# construct loss and optimizer
criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
# training cycle forward, backward, update
def train(epoch):
running_loss = 0.0
for batch_idx, data in enumerate(train_loader, 0):
inputs, target = data
inputs, target = inputs.to(device), target.to(device)
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, target)
loss.backward()
optimizer.step()
running_loss += loss.item()
if batch_idx % 300 == 299:
print('[%d, %5d] loss: %.3f' % (epoch+1, batch_idx+1, running_loss/300))
running_loss = 0.0
def test():
correct = 0
total = 0
with torch.no_grad():
for data in test_loader:
images, labels = data
images, labels = images.to(device), labels.to(device)
outputs = model(images)
_, predicted = torch.max(outputs.data, dim=1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('accuracy on test set: %d %% ' % (100*correct/total))
return correct/total
if __name__ == '__main__':
epoch_list = []
acc_list = []
for epoch in range(10):
train(epoch)
acc = test()
epoch_list.append(epoch)
acc_list.append(acc)
plt.plot(epoch_list,acc_list)
plt.ylabel('accuracy')
plt.xlabel('epoch')
# plt.show()
plt.savefig('./data/pytorch9.png')
🌈我的分享也就到此结束啦🌈
如果我的分享也能对你有帮助,那就太好了!
若有不足,还请大家多多指正,我们一起学习交流!
📢未来的富豪们:点赞👍→收藏⭐→关注🔍,如果能评论下就太惊喜了!
感谢大家的观看和支持!最后,☺祝愿大家每天有钱赚!!!欢迎关注、关注!