第三周 ResNet的学习

ResNet

一、数据集准备

	该数据集包含了train、test、val三部分,每一部分都包含了猫狗照片,train包含了20000张,猫狗各占一半;val包含了2000张照片,猫狗各占一半;首先将猫狗照片分为两个文件夹,方便为其数据加标签。
import os
import shutil
import numpy as np
import pandas as pd
path_img=r'./train'
myfolder= os.listdir(path_img)
lenl=len(myfolder)
print(lenl)
cat_direc=r'./train/cat'
dog_direc=r'./train/dog'
for folder in myfolder:
  if 'cat' in folder:
    path=path_img+'/'+folder
    newpath=cat_direc+'/'+folder
    if not os.path.exists(cat_direc):
        os.mkdir(cat_direc)
    os.rename(path,newpath)
    print('%s 存入成功'%(folder))
  if 'dog' in folder:
    path2=path_img+'/'+folder
    newpath2=dog_direc+'/'+folder
    if not os.path.exists(dog_direc):
        os.mkdir(dog_direc)
    os.rename(path2,newpath2)
    print('%s 存入成功'%(folder))

在这里插入图片描述

二、数据集处理

1、使用datasets.ImageFolder函数对每一个文件夹进行打标签,结果如下。
['cat', 'dog']
{'cat': 0, 'dog': 1}

在这里插入图片描述

2、读取数据,分别读取训练集和验证集,并对数据进行裁剪、归一化等处理,以下是实现代码以
及json文件的内容。
(1)transforms.Compose 是对数据的增强方式的组合,ResNet默认的输入图片尺寸为224*224;
并将图片转化为Tensor,归一化。 为了方便对训练集和数据集采用不同的增强方法,定义了一个
data_transforms字典,key分别是‘train’和‘validation’,对应的value分别是它们的增强方法。
(2)datasets.ImageFolder传入(1)中的增强方法,通过给定路径进行读取数据,并且会根据不
同文件夹进行贴标签。
(3)torch.utils.data.DataLoader把dataset读取到的照片,按照一定顺序排列,设置batch_size与
num_workers
data_transforms = {
    'train': transforms.Compose([
        transforms.Resize([224, 224]),
        transforms.CenterCrop(224),
        transforms.ToTensor(), # range [0, 255] -> [0.0,1.0]
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ]),
    'validation':transforms.Compose([
        transforms.Resize([224,224]),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ])
    }   
    data_dir = 'data'
    train_dataset = datasets.ImageFolder(root=os.path.join(data_dir, "train"),
                                          transform=data_transforms["train"])
    
    validate_dataset = datasets.ImageFolder(root=os.path.join(data_dir, "val"),
                                            transform=data_transforms["validation"])
    
    # imgs,labels=train_dataset[0]
    # print(imgs,labels)
    classeslist=train_dataset.class_to_idx
    cla_dict = dict((val, key) for key, val in classeslist.items())
    #json.dumps() 是把python对象转换成json对象的一个过程,生成的是字符串。
    json_str = json.dumps(cla_dict, indent=4)
    with open('class_indices.json', 'w') as json_file:
        json_file.write(json_str)

    batch_size = 128
    nw = min([os.cpu_count(), batch_size if batch_size > 1 else 0, 8])
    train_loader=torch.utils.data.DataLoader(train_dataset,
                                             batch_size=batch_size,
                                             shuffle=True,
                                             num_workers=nw)
    print(train_loader)
    validate_loader=torch.utils.data.DataLoader(validate_dataset,
                                                batch_size=batch_size,
                                                shuffle=True,
                                                num_workers=nw)
    

在这里插入图片描述

三、加载模型

1、载入ResNet模型,并且根据数据集进行修改,数据集只有两类,cat和dog,所以它
最后的FC层应该输出两类的结果概率,并决定图片的类型,我们需要修改ResNet的FC
层。
 net=resnet34()
 in_channel = net.fc.in_features
 net.fc = nn.Linear(in_channel, 2)
2、设置损失函数以及优化器。
(1)损失函数采用的是交叉熵损失
(2)Adam优化器,两个参数分别是要优化的参数,以及学习率
loss_function = nn.CrossEntropyLoss()
params = [p for p in net.parameters() if p.requires_grad] 
optimizer = optim.Adam(params, lr=0.0001)

四、训练模型

1、设置迭代次数以及权重文件保存路径。
epochs = 10
best_acc = 0.0
save_path = './resNet34.pth'
2、要主要训练与测试时net.train()与net.eval的区别,区别在于是否启用BN与Dropout。
3、tqdm的使用:
desc:进度条的描述信息,也称进度条的前缀
total:要监视的进度的总数
ascii:进度条显示的方式,bool ,为True时使用编码更新的方式展示
ncols(int):整个输出信息的宽度
nrows(int):进度条的高速
position(int):设置打印进度条的位置,可以设置多个bar
colour(str):进度条的颜色
for epoch in range(epochs):
        net.train()
        running_loss = 0.0
        #进度条
        train_bar = tqdm(train_loader, file=sys.stdout)
        for step, data in enumerate(train_bar):
            images, labels = data
            optimizer.zero_grad()
            logits = net(images.to(device))
            loss = loss_function(logits, labels.to(device))
            loss.backward()
            optimizer.step()

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

在这里插入图片描述

4、结果:验证集的准确率约为90%

五、测试模型

1、首先对数据进行同样的处理
    data_transform = transforms.Compose(
        [transforms.Resize(256),
         transforms.CenterCrop(224),
         transforms.ToTensor(),
         transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])
2、载入训练好的权重
 model = resnet34(num_classes=2).to(device)
 model.load_state_dict(torch.load(weights_path, map_location=device))
3、图片预测
img_path = './data/test/1.jpg'
plt.imshow(img)
model.eval()
with torch.no_grad():
    # predict class
   output = torch.squeeze(model(img.to(device))).cpu()
   predict = torch.softmax(output, dim=0)
   predict_cla = torch.argmax(predict).numpy()
   for i in range(len(predict)):
        print("class: {:10}   prob: {:.3}".format(class_indict[str(i)],
                                                  predict[i].numpy()))
    plt.show()

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

六、问题总结

1、Residual learning 的基本原理?
以下是残差模块的一个基本网络结构。

在这里插入图片描述
在这里插入图片描述

	our formulation always learns residual functions; our identity shortcuts are never closed, and all information is always passed 
through, with additional residual functions to be learned.

2、Batch Normailization 的原理,思考 BN、LN、IN 的主要区别。
(1)BN的原理

在这里插入图片描述

	首先是计算数据B的均值→然后计算数据B的方差→对数据B进行标准化处理→进行平移和缩放处理,引入γ和β两个参数,通过这两
个参数,让我们的网络可以学习恢复到原始网络的特征分布。
(2)区别
a)	BN:是对不同样本的同一特征通道进行归一化。
b)	LN:	是对同一样本的所有特征通道进行归一化。
c)	IN:是对每一个样本的每一个通道进行归一化。
3、为什么分组卷积可以提升准确率?即然分组卷积可以提升准确率,同时还能降低计算量,分数数量尽量多不行吗?
	分组卷积将输入特征图按C分为g组,每一组进行常规卷积。分组卷积也叫过滤器组,由于过滤器关系是稀疏的,根据稀疏关系,有
些过滤器之间的关系是不需要学习的,这样就可以减少参数量,也可以更准确、更有效的训练网络。
分组数量尽量多的话,可能会使得有些关系学习不到。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值