02 VGG(2014)

文章介绍了深度学习中的网络原理,包括使用多个3x3卷积核替代大尺度卷积核以减少参数,解释了感受野的概念,以及网络架构中的卷积和池化步骤。在代码复现部分,涵盖了迁移学习、分类网络准确率计算和常用的Tensor操作。同时,文章提到了Adam优化器和模型参数加载的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、 网络原理

1 堆叠多个3x3的卷积核

2 感受野

3 网络架构

二、 代码复现

1 迁移学习

2 分类网络准确率计算

3 常用tensor变换等操作函数


仅是个人笔记,代码学习资源来源B站博主霹雳吧啦Wz的个人空间_哔哩哔哩_bilibili

一、 网络原理

1 堆叠多个3x3的卷积核

堆叠多个3x3的卷积核来替代大尺度卷积核 (减少所需参数)

两个3x3的卷积核替代5x5的卷积核,三个3x3的 卷积核替代7x7的卷积核

参数: 2*3*3 =18 ---------  5*5=25               3*3*3=27------------7*7=49

为何能替代?————相同的感受野

2 感受野

感受野(详见超链接)

3 网络架构

  • conv的stride为1,padding为1
  • maxpool的size为2,stride为2

卷积未改变特征图大小,ke_size=3,pad=1

每次是通过池化改变的;步距为2

特征提取(全连接之前):

224——112——56——28——14——7    通过5个池化

接入全连接: 512*7*7

二、 代码复现

绝大部分代码同01alexnet

optimizer = optim.Adam(net.parameters(), lr=0.0001)
  • tqdm进度条使用——tqdm(详见超链接)
        train_bar = tqdm(train_loader, file=sys.stdout)


        for step, data in enumerate(train_bar):
            images, labels = data
            optimizer.zero_grad()
            outputs = net(images.to(device))
            loss = loss_function(outputs, labels.to(device))
            loss.backward()
            optimizer.step()
            running_loss += loss.item()


            train_bar.desc = "train epoch[{}/{}] loss:{:.3f}".format(epoch + 1,
                                                                     epochs,
                                                                     loss)

1 迁移学习

  • 参数加载         注意:使用别人预训练模型参数时,要注意别人的预处理方式)
  1.  torch官方参数加载——使用weights参数(详见超链接)
    net = vgg16(weights = torchvision.models.VGG16_Weights)
  2.  自己下载的/训练的,参数完全匹配                                                          model.load_state_dict方法(详见超链接)                                                                               torch.load方法(详见超链接)                                                                                                          参数完全匹配 ————就是字典的key必须完全一样名字val形状相同
    model = vgg(model_name="vgg16", num_classes=5).to(device)
    weights_path = "./vgg16Net.pth"
    model.load_state_dict(torch.load(weights_path, map_location=device))
    
  3. 参数不完全匹配

     两种方法都行,哪个方便用哪个

使用下面的套路加载---本质都一样

用下面这个!!!!!!!!!!!!!!!!!!!!!!!!!

# 设备加载
device = torch.device(args.device if torch.cuda.is_available() else "cpu")
# 建立model
model = u2net_full()
# 查看model的初始化参数值
old_dic = model.state_dict()
# 加载.pth参数文件
weight_path = 'F:/.../u2net_full.pth'
pre_dic = torch.load(weight_path, map_location=device)
# 将.pth参数加载到model中,只会将字典名称完全一样以及shape相同的加载进去
# 返回model中未加载成功的参数   以及   .pth中多余的参数(与model不匹配)------strict=False
missing_keys, unexpected_keys = model.load_state_dict(pre_dic, strict=False)
print(missing_keys, unexpected_keys)
# 再次查看model的参数值,检查是否已经更换成功
new_dic = model.state_dict()
model.to(device)

  •  模型修改

    根据名称修改,修改前后特征图要满足输入输出要求

  • 参数获取、冻结

      参数、模型查看(详见超链接)

for m, n in net.named_parameters():  # m就是层的名称,n就是它的参数
    # m的形式   eg: features.0.weight 、 features.0.bias 、 classifier.6.weight等等
    # 卷积,全连接,才有weight、bias     池化、激活没有参数
    if m ==  'classifier.3.bias':     # m是字符串格式,打印某一层的参数
        print(m, n.shape)
    if m == 'features.6.weight':
        print(m, n.shape)

 参数冻结

# 冻结net全部参数
 for name, parameter in net.named_parameters():
     parameter.requires_grad = False

# 冻结net部分参数
 for name, parameter in net.named_parameters():
     if 'key' in name:
         parameter.requires_grad = False

2 分类网络准确率计算

for val_data in val_bar:
    val_images, val_labels = val_data
    outputs = net(val_images.to(device))
    # (batch,类别数)  一个样本是一行,每一行是属于各个类别的概率
     predict_y = torch.max(outputs, dim=1)[1]
    # (batch)  predict_y==(outputs每一行最大值的)索引
    acc += torch.eq(predict_y, val_labels.to(device)).sum().item()  
    # 判断相等的个数

val_accurate = acc / val_num   #一轮的准确率: 正确的样本数/总样本数

3 常用tensor变换等操作函数

维度变换:

torch.nn.flatten 开始展的默认维度值为1,torch.flatten默认是从0开始展。

.reshape   .view()类似。方法会先展平再按照维度排列,不同于转置!!!

转置操作使用下面两个:

tensor.transpose(),只交换指定的两个维度的内容

tensor.permute()则可以一次性交换多个维度

输入网络,BCHW

测试一张图片时是CHW,所以添加一个维度升维

torch.squeeze()

x = torch.randn(size=(2, 1, 2, 1, 2))  
#shape(2, 1, 2, 1, 2)

# 1 把x中维度大小为1的所有维都删除
y = torch.squeeze(x)
#shape(2,2,2)

# 2 删除某一维
y = torch.squeeze(x,0) #第一维大小为2,不为1,因此结果删除不掉
#shape(2, 1, 2, 1, 2)
y = torch.squeeze(x,1) #x第二维大小是1,可以删掉
#shape(2, 2, 1, 2)

torch.unsqueeze()

y = torch.unsqueeze(x, 0)  #在第0维扩展,第0维大小为1
 
y = torch.unsqueeze(x, -1)  #在最后一维扩展,最后一维大小为1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值