1.nn.linear(A,B)
作用:将矩阵从A维度转为B维度
例如:输入4个变量,回归任务,需要输出1个值,使用nn.linear(4,1),一个(16,4)的矩阵经过nn.linear(4,1)转为(16,1)
2.分类任务
回归:找一条拟合的线
分类:找一条线将两类区分
3.卷积神经网络
卷积核与原特征图相乘得到新特征图,通过新特征图来判断图像是否为寻找的图像
卷积核的大小称为神经元的感受野。
目标就是如何让卷积核成为有意义的特征图。
原特征图深度和卷积核必须相同。
4.练习
1,现有特征图4*4. 卷积核大小为2(表示是2*2), 卷出来的特征图多大。(3*3)卷积核的参数量多少?(2*2=4)
2,现有特征图4*4. 卷积核大小为3, 卷出来的特征图多大。(2*2)
3,现有特征图4*4. 卷积核大小为3,padding 1, 卷出来的特征图多大。(padding是一圈,特征图变成6*6,新特征图变成4*4)
4,现有特征图100*100. 卷积核大小为3, 卷出来的特征图多大。(98*98)
5,现有特征图100*100. 卷积核大小为3,padding1, 卷出来的特征图多大。(100*100)
6,特征图8*8. 卷积核 7, 问卷出来的特征图多大。这个卷积核的参数量多少?(94*94)
7,特征图3*4*4. padding1(3*6*6), 卷积核数量1,卷出来的特征图为1*4*4。这套卷积核多大, 卷积核的参数量多少?(3*3*3 27)
5.卷积尺寸计算公式
6.池化pooling
但在实战中, 常常卷积和池化一起使用。
7.LOSS与DROP OUT与归一化
而drop out可以缓解过拟合。
归一化大概是将数据化为统一可比较形式。
8.AlexNet
创新点:
relu、drop out、池化、归一化
代码:
import torch
import torch.nn as nn
class AlexNet(nn.Module):
def __init__(self, num_classes=1000):
super(AlexNet, self).__init__()
self.features = nn.Sequential(
# 输入:3通道227x227(或224x224)
nn.Conv2d(3, 96, kernel_size=11, stride=4), # 输出:96x55x55
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2), # 输出:96x27x27
nn.Conv2d(96, 256, kernel_size=5, padding=2), # 输出:256x27x27
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2), # 输出:256x13x13
nn.Conv2d(256, 384, kernel_size=3, padding=1), # 输出:384x13x13
nn.ReLU(inplace=True),
nn.Conv2d(384, 384, kernel_size=3, padding=1), # 输出:384x13x13
nn.ReLU(inplace=True),
nn.Conv2d(384, 256, kernel_size=3, padding=1), # 输出:256x13x13
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2) # 输出:256x6x6
)
self.classifier = nn.Sequential(
nn.Dropout(0.5),
nn.Linear(256 * 6 * 6, 4096),
nn.ReLU(inplace=True),
nn.Dropout(0.5),
nn.Linear(4096, 4096),
nn.ReLU(inplace=True),
nn.Linear(4096, num_classes)
)
def forward(self, x):
x = self.features(x)
x = torch.flatten(x, 1) # 展平为(batch_size, 256*6*6)
x = self.classifier(x)
return x
nn.Conv2d(3, 96, kernel_size=11, stride=4)
:- 输入通道3:RGB三通道图像。
- 输出通道96:使用96个11x11的卷积核。
- Stride=4:步幅4大幅降低输出尺寸,计算方式:输出尺寸=(227−11)/4+1=55输出尺寸,因此输出为96x55x55。
nn.ReLU(inplace=True)
:- 激活函数,引入非线性。
inplace=True
直接修改输入张量,减少内存占用。
nn.MaxPool2d(kernel_size=3, stride=2)
:- 最大池化窗口3x3,步幅2。
- 输出尺寸计算:(55−3)/2+1=27,输出为96x27x27。
- 第二层卷积(96→256通道):
padding=2
保持输出尺寸与输入一致(27x27)。- 池化后尺寸:27−3/2+1=13,输出256x13x13。
- 第三层卷积(256→384通道):
- 3x3卷积核,
padding=1
维持尺寸不变。
- 3x3卷积核,
- 第四层卷积(384→384通道):
- 与第三层结构相同,增加网络深度。
- 第五层卷积(384→256通道):
- 最终通道数减少,池化后得到256x6x6的特征图
nn.Dropout(0.5)
:- 在全连接层之间加入50%的Dropout,减少过拟合风险。
nn.Linear(256*6*6, 4096)
:- 将展平的256x6x6=9216维特征映射到4096维。
- 第一个全连接层参数量:9216 * 4096 ≈ 37.7M(占模型总参数量的主要部分)。
- 双全连接层设计:
- 通过两个4096维的全连接层增强非线性表达能力。
- 输出层:
- 最终映射到类别数(如ImageNet的1000类)。
self.features(x)
:执行所有卷积和池化操作。torch.flatten(x, 1)
:- 将四维张量(batch_size, 256, 6, 6)展平为二维(batch_size, 25666)。
1
表示从第1维(通道)开始展平。
self.classifier(x)
:通过全连接层输出分类结果。
9.VggNet
其在AlexNet的基础上, 运用了更小的卷积核,并且加深了网络, 达到了更好的效果。
import torch
import torch.nn as nn
class VGG(nn.Module):
def __init__(self, features, num_classes=1000, init_weights=True):
super(VGG, self).__init__()
# 特征提取网络(卷积层组)
self.features = features
# 分类网络(全连接层)
self.classifier = nn.Sequential(
nn.Dropout(p=0.5),
nn.Linear(512 * 7 * 7, 4096),
nn.ReLU(inplace=True),
nn.Dropout(p=0.5),
nn.Linear(4096, 4096),
nn.ReLU(inplace=True),
nn.Linear(4096, num_classes)
)
# 参数初始化
if init_weights:
self._initialize_weights()
def forward(self, x):
x = self.features(x) # 输入:N×3×224×224 → 输出:N×512×7×7
x = torch.flatten(x, start_dim=1) # 展平为N×(512×7×7)
x = self.classifier(x) # 分类输出
return x
def _initialize_weights(self):
for m in self.modules():
if isinstance(m, nn.Conv2d):
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
if m.bias is not None:
nn.init.constant_(m.bias, 0)
elif isinstance(m, nn.Linear):
nn.init.normal_(m.weight, 0, 0.01)
nn.init.constant_(m.bias, 0)
# 生成卷积层组的工具函数
def make_layers(cfg, batch_norm=False):
layers = []
in_channels = 3 # 初始输入为RGB三通道
for v in cfg:
if v == 'M':
layers += [nn.MaxPool2d(kernel_size=2, stride=2)] # 池化层
else:
conv2d = nn.Conv2d(in_channels, v, kernel_size=3, padding=1)
layers += [conv2d, nn.ReLU(inplace=True)]
in_channels = v # 更新输入通道数
return nn.Sequential(*layers)
# 不同VGG版本的配置(以VGG16为例)
cfgs = {
'vgg16': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M']
}
10.ResNet
传统深度网络随着层数增加,训练误差不降反升(非过拟合导致),即模型性能下降
模型 | 优势 | 局限性 | 适用场景 |
---|---|---|---|
AlexNet | 结构简单,易实现 | 参数冗余,计算效率低 | 教学、小规模分类任务 |
VGGNet | 特征提取能力强,结构统一 | 参数量大,实时性差 | 需要高精度特征表达的任务 |
ResNet | 支持超深层网络,训练稳定 | 深层模型计算资源消耗大 | 复杂视觉任务(检测、分割) |