前言

随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。来源于哔哩哔哩博主“霹雳吧啦Wz”,博主学习作为笔记记录,欢迎大家一起讨论学习交流。

一、搭建ResNeXt网络

用ResNeXt学习,没训练。

二、代码部分

1.module.py----定义ResNeXt的网络结构

代码如下(示例):

import torch.nn as nn
import torchclass BasicBlock(nn.Module):expansion = 1def __init__(self, in_channel, out_channel, stride=1, downsample=None, **kwargs):super(BasicBlock, self).__init__()self.conv1 = nn.Conv2d(in_channels=in_channel, out_channels=out_channel,kernel_size=3, stride=stride, padding=1, bias=False)self.bn1 = nn.BatchNorm2d(out_channel)self.relu = nn.ReLU()self.conv2 = nn.Conv2d(in_channels=out_channel, out_channels=out_channel,kernel_size=3, stride=1, padding=1, bias=False)self.bn2 = nn.BatchNorm2d(out_channel)self.downsample = downsampledef forward(self, x):identity = xif self.downsample is not None:identity = self.downsample(x)out = self.conv1(x)out = self.bn1(out)out = self.relu(out)out = self.conv2(out)out = self.bn2(out)out += identityout = self.relu(out)return outclass Bottleneck(nn.Module):"""注意:原论文中,在虚线残差结构的主分支上,第一个1x1卷积层的步距是2,第二个3x3卷积层步距是1。但在pytorch官方实现过程中是第一个1x1卷积层的步距是1,第二个3x3卷积层步距是2,这么做的好处是能够在top1上提升大概0.5%的准确率。可参考Resnet v1.5 https://ngc.nvidia.com/catalog/model-scripts/nvidia:resnet_50_v1_5_for_pytorch"""expansion = 4def __init__(self, in_channel, out_channel, stride=1, downsample=None,groups=1, width_per_group=64):super(Bottleneck, self).__init__()width = int(out_channel * (width_per_group / 64.)) * groupsself.conv1 = nn.Conv2d(in_channels=in_channel, out_channels=width,kernel_size=1, stride=1, bias=False)  # squeeze channelsself.bn1 = nn.BatchNorm2d(width)# -----------------------------------------self.conv2 = nn.Conv2d(in_channels=width, out_channels=width, groups=groups,kernel_size=3, stride=stride, bias=False, padding=1)self.bn2 = nn.BatchNorm2d(width)# -----------------------------------------self.conv3 = nn.Conv2d(in_channels=width, out_channels=out_channel*self.expansion,kernel_size=1, stride=1, bias=False)  # unsqueeze channelsself.bn3 = nn.BatchNorm2d(out_channel*self.expansion)self.relu = nn.ReLU(inplace=True)self.downsample = downsampledef forward(self, x):identity = xif self.downsample is not None:identity = self.downsample(x)out = self.conv1(x)out = self.bn1(out)out = self.relu(out)out = self.conv2(out)out = self.bn2(out)out = self.relu(out)out = self.conv3(out)out = self.bn3(out)out += identityout = self.relu(out)return outclass ResNet(nn.Module):def __init__(self,block,blocks_num,num_classes=1000,include_top=True,groups=1,width_per_group=64):super(ResNet, self).__init__()self.include_top = include_topself.in_channel = 64self.groups = groupsself.width_per_group = width_per_groupself.conv1 = nn.Conv2d(3, self.in_channel, kernel_size=7, stride=2,padding=3, bias=False)self.bn1 = nn.BatchNorm2d(self.in_channel)self.relu = nn.ReLU(inplace=True)self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)self.layer1 = self._make_layer(block, 64, blocks_num[0])self.layer2 = self._make_layer(block, 128, blocks_num[1], stride=2)self.layer3 = self._make_layer(block, 256, blocks_num[2], stride=2)self.layer4 = self._make_layer(block, 512, blocks_num[3], stride=2)if self.include_top:self.avgpool = nn.AdaptiveAvgPool2d((1, 1))  # output size = (1, 1)self.fc = nn.Linear(512 * block.expansion, num_classes)for m in self.modules():if isinstance(m, nn.Conv2d):nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')def _make_layer(self, block, channel, block_num, stride=1):downsample = Noneif stride != 1 or self.in_channel != channel * block.expansion:downsample = nn.Sequential(nn.Conv2d(self.in_channel, channel * block.expansion, kernel_size=1, stride=stride, bias=False),nn.BatchNorm2d(channel * block.expansion))layers = []layers.append(block(self.in_channel,channel,downsample=downsample,stride=stride,groups=self.groups,width_per_group=self.width_per_group))self.in_channel = channel * block.expansionfor _ in range(1, block_num):layers.append(block(self.in_channel,channel,groups=self.groups,width_per_group=self.width_per_group))return nn.Sequential(*layers)def forward(self, x):x = self.conv1(x)x = self.bn1(x)x = self.relu(x)x = self.maxpool(x)x = self.layer1(x)x = self.layer2(x)x = self.layer3(x)x = self.layer4(x)if self.include_top:x = self.avgpool(x)x = torch.flatten(x, 1)x = self.fc(x)return xdef resnet34(num_classes=1000, include_top=True):# https://download.pytorch.org/models/resnet34-333f7ec4.pthreturn ResNet(BasicBlock, [3, 4, 6, 3], num_classes=num_classes, include_top=include_top)def resnet50(num_classes=1000, include_top=True):# https://download.pytorch.org/models/resnet50-19c8e357.pthreturn ResNet(Bottleneck, [3, 4, 6, 3], num_classes=num_classes, include_top=include_top)def resnet101(num_classes=1000, include_top=True):# https://download.pytorch.org/models/resnet101-5d3b4d8f.pthreturn ResNet(Bottleneck, [3, 4, 23, 3], num_classes=num_classes, include_top=include_top)def resnext50_32x4d(num_classes=1000, include_top=True):# https://download.pytorch.org/models/resnext50_32x4d-7cdf4587.pthgroups = 32width_per_group = 4return ResNet(Bottleneck, [3, 4, 6, 3],num_classes=num_classes,include_top=include_top,groups=groups,width_per_group=width_per_group)def resnext101_32x8d(num_classes=1000, include_top=True):# https://download.pytorch.org/models/resnext101_32x8d-8ba56ff5.pthgroups = 32width_per_group = 8return ResNet(Bottleneck, [3, 4, 23, 3],num_classes=num_classes,include_top=include_top,groups=groups,width_per_group=width_per_group)

2.train.py----加载数据集并进行训练,训练集计算loss,测试集计算accuracy,保存训练好的网络参数

代码如下(示例):

import os
import sys
import jsonimport torch
import torch.nn as nn
import torch.optim as optim
from torchvision import transforms, datasets
from tqdm import tqdmfrom model import resnet34def main():device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")print("using {} device.".format(device))data_transform = {"train": transforms.Compose([transforms.RandomResizedCrop(224),transforms.RandomHorizontalFlip(),transforms.ToTensor(),transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])]),"val": transforms.Compose([transforms.Resize(256),transforms.CenterCrop(224),transforms.ToTensor(),transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])}data_root = os.path.abspath(os.path.join(os.getcwd(), "../.."))  # get data root pathimage_path = os.path.join(data_root, "data_set", "flower_data")  # flower data set pathassert os.path.exists(image_path), "{} path does not exist.".format(image_path)train_dataset = datasets.ImageFolder(root=os.path.join(image_path, "train"),transform=data_transform["train"])train_num = len(train_dataset)# {'daisy':0, 'dandelion':1, 'roses':2, 'sunflower':3, 'tulips':4}flower_list = train_dataset.class_to_idxcla_dict = dict((val, key) for key, val in flower_list.items())# write dict into json filejson_str = json.dumps(cla_dict, indent=4)with open('class_indices.json', 'w') as json_file:json_file.write(json_str)batch_size = 16nw = min([os.cpu_count(), batch_size if batch_size > 1 else 0, 8])  # number of workersprint('Using {} dataloader workers every process'.format(nw))train_loader = torch.utils.data.DataLoader(train_dataset,batch_size=batch_size, shuffle=True,num_workers=nw)validate_dataset = datasets.ImageFolder(root=os.path.join(image_path, "val"),transform=data_transform["val"])val_num = len(validate_dataset)validate_loader = torch.utils.data.DataLoader(validate_dataset,batch_size=batch_size, shuffle=False,num_workers=nw)print("using {} images for training, {} images for validation.".format(train_num,val_num))net = resnet34()# load pretrain weights# download url: https://download.pytorch.org/models/resnet34-333f7ec4.pthmodel_weight_path = "./resnet34-pre.pth"assert os.path.exists(model_weight_path), "file {} does not exist.".format(model_weight_path)net.load_state_dict(torch.load(model_weight_path, map_location='cpu'))# for param in net.parameters():#     param.requires_grad = False# change fc layer structurein_channel = net.fc.in_featuresnet.fc = nn.Linear(in_channel, 5)net.to(device)# define loss functionloss_function = nn.CrossEntropyLoss()# construct an optimizerparams = [p for p in net.parameters() if p.requires_grad]optimizer = optim.Adam(params, lr=0.0001)epochs = 3best_acc = 0.0save_path = './resNet34.pth'train_steps = len(train_loader)for epoch in range(epochs):# trainnet.train()running_loss = 0.0train_bar = tqdm(train_loader, file=sys.stdout)for step, data in enumerate(train_bar):images, labels = dataoptimizer.zero_grad()logits = net(images.to(device))loss = loss_function(logits, labels.to(device))loss.backward()optimizer.step()# print statisticsrunning_loss += loss.item()train_bar.desc = "train epoch[{}/{}] loss:{:.3f}".format(epoch + 1,epochs,loss)# validatenet.eval()acc = 0.0  # accumulate accurate number / epochwith torch.no_grad():val_bar = tqdm(validate_loader, file=sys.stdout)for val_data in val_bar:val_images, val_labels = val_dataoutputs = net(val_images.to(device))# loss = loss_function(outputs, test_labels)predict_y = torch.max(outputs, dim=1)[1]acc += torch.eq(predict_y, val_labels.to(device)).sum().item()val_bar.desc = "valid epoch[{}/{}]".format(epoch + 1,epochs)val_accurate = acc / val_numprint('[epoch %d] train_loss: %.3f  val_accuracy: %.3f' %(epoch + 1, running_loss / train_steps, val_accurate))if val_accurate > best_acc:best_acc = val_accuratetorch.save(net.state_dict(), save_path)print('Finished Training')if __name__ == '__main__':main()

3.predict.py——得到训练好的网络参数后,用自己找的图像进行分类测试

import os
import jsonimport torch
from PIL import Image
from torchvision import transforms
import matplotlib.pyplot as pltfrom model import resnet34def main():device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")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])])# load imageimg_path = "../tulip.jpg"assert os.path.exists(img_path), "file: '{}' dose not exist.".format(img_path)img = Image.open(img_path)plt.imshow(img)# [N, C, H, W]img = data_transform(img)# expand batch dimensionimg = torch.unsqueeze(img, dim=0)# read class_indictjson_path = './class_indices.json'assert os.path.exists(json_path), "file: '{}' dose not exist.".format(json_path)with open(json_path, "r") as f:class_indict = json.load(f)# create modelmodel = resnet34(num_classes=5).to(device)# load model weightsweights_path = "./resNet34.pth"assert os.path.exists(weights_path), "file: '{}' dose not exist.".format(weights_path)model.load_state_dict(torch.load(weights_path, map_location=device))# predictionmodel.eval()with torch.no_grad():# predict classoutput = torch.squeeze(model(img.to(device))).cpu()predict = torch.softmax(output, dim=0)predict_cla = torch.argmax(predict).numpy()print_res = "class: {}   prob: {:.3}".format(class_indict[str(predict_cla)],predict[predict_cla].numpy())plt.title(print_res)for i in range(len(predict)):print("class: {:10}   prob: {:.3}".format(class_indict[str(i)],predict[i].numpy()))plt.show()if __name__ == '__main__':main()

4.batch_predict.py——批量图像预测脚本

import os
import jsonimport torch
from PIL import Image
from torchvision import transformsfrom model import resnet34def main():device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")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])])# load image# 指向需要遍历预测的图像文件夹imgs_root = "/data/imgs"assert os.path.exists(imgs_root), f"file: '{imgs_root}' dose not exist."# 读取指定文件夹下所有jpg图像路径img_path_list = [os.path.join(imgs_root, i) for i in os.listdir(imgs_root) if i.endswith(".jpg")]# read class_indictjson_path = './class_indices.json'assert os.path.exists(json_path), f"file: '{json_path}' dose not exist."json_file = open(json_path, "r")class_indict = json.load(json_file)# create modelmodel = resnet34(num_classes=5).to(device)# load model weightsweights_path = "./resNet34.pth"assert os.path.exists(weights_path), f"file: '{weights_path}' dose not exist."model.load_state_dict(torch.load(weights_path, map_location=device))# predictionmodel.eval()batch_size = 8  # 每次预测时将多少张图片打包成一个batchwith torch.no_grad():for ids in range(0, len(img_path_list) // batch_size):img_list = []for img_path in img_path_list[ids * batch_size: (ids + 1) * batch_size]:assert os.path.exists(img_path), f"file: '{img_path}' dose not exist."img = Image.open(img_path)img = data_transform(img)img_list.append(img)# batch img# 将img_list列表中的所有图像打包成一个batchbatch_img = torch.stack(img_list, dim=0)# predict classoutput = model(batch_img.to(device)).cpu()predict = torch.softmax(output, dim=1)probs, classes = torch.max(predict, dim=1)for idx, (pro, cla) in enumerate(zip(probs, classes)):print("image: {}  class: {}  prob: {:.3}".format(img_path_list[ids * batch_size + idx],class_indict[str(cla.numpy())],pro.numpy()))if __name__ == '__main__':main()

三、额外部分





1.通过计算发现分组卷积的参数会减少,与正常相比,理论上减少了分组数g倍(假设卷积核尺寸是kxk,输入图像的深度是Cin,输出卷积核的深度通道数是n,分组卷积的组数是g)。2.当组卷积的分组数g=输入特征矩阵的深度Cin,比如这里输入是四个通道,g=4意味着分成四组,每一组就是分配了一个chanel为1的卷积,并且输出特征矩阵深度n=输入特征矩阵深度Cin,是组卷积就变成了DW卷积。

上图三个部分是等价的,最右边先是通过1x1卷积将深度从256降为128,然后通过3x3,分组为32的组卷积,最后通过1x1卷积将深度从128升为256。中间是通过将分成32组,每组深度是右图深度除以分组32得到的深度,再进行concatenate.左边是先通过1x1卷积再进行相加,与中间先进行concatenate,再进行1x1卷积一样。



32是分组数group,对应conv2,conv3,conv4,conv5对应的group数都是32,C=32;4d是conv2等一系列卷积所对应的block中组卷积当中每一组所采用的卷积的个数。比如conv2,组卷积是32,C=32.每一组的卷积核个数是4,所以输出是32x4=128.即3x3,128,C=32。

不同分组数C和d的效果,错误率较低。

对于浅层网络,比如Resnet 28,34直接通过两层3x3B=的block结构进行堆叠,论文说只有block层数大于3效果会比较好,所以对于两层网络对他进行拆分,效果可能并不好,甚至增加计算量。


ResNeXt在ResNet基础上变化了组卷积模块,其他类似,所以更改代码部分在ResNet基础上,增加组数;其次,在指定网址上下载预训练权重,在train.py文件导入from model import resnext50_32x4d.预训练权重设置成resnext50_32x4d.pth.保存路径也改为resnext50.pth.预测时候在predict.py文件导入from model import resnext50_32x4d.model=resnext50_32x4d,预训练权重设置成resnext50_32x4d.pth.

第六课:ResNeXt学习相关推荐

  1. 《迅雷链精品课》第六课:主流区块链数据存储分析(一)

    上一节课我们学习了区块链中的账户与账本,了解区块链账户的特点和本质.今天我们将系统地学习区块链数据存储,在课程学习前,大家可以先思考下列问题:区块链的数据是如何存储的?区块链如何在没有中心信任节点的情 ...

  2. 投资学习网课笔记(part6)--基金第六课

    学习笔记,仅供参考 文章目录 基金第六课 基金的两种交易渠道 场内渠道 场外渠道 场外基金交易规则 场内基金的交易规则 如何分辨场内和场外基金 基金定投 基金第六课 基金的两种交易渠道 场内渠道 使用 ...

  3. Python学习第六课-列表

    Python学习第六课-列表 一.序列 1.1 概念 1.2分类 二.列表 2.1 概念 2.2 练习 三.切片 3.1 可切片对象的索引方式 3.2切片操作 3.3 练习 四.通用操作 4.1 序列 ...

  4. 第六课 大数据技术之Fink1.13的实战学习-Table Api和SQL

    第六课 大数据技术之Fink1.13的实战学习-Table Api和SQL 文章目录 第六课 大数据技术之Fink1.13的实战学习-Table Api和SQL 第一节 Fink SQL快速上手 1. ...

  5. 斯坦福大学iOS应用开发教程学习笔记(第六课)故事版 StoryBoard

    第六课 主要内容:多个MVC的程序和故事版.UINavigationController. Segues 1.多个MVC 前面的程序都是一个MVC,多个View时,怎么办,那就需要多个Controll ...

  6. 2011斯坦福大学iOS应用开发教程学习笔记(第六课)故事版

    第六课 主要内容:多个MVC的程序和故事版.UINavigationController. Segues 1.多个MVC 前面的程序都是一个MVC,多个View时,怎么办,那就需要多个Controll ...

  7. 第六课.NLP文本分类任务

    第六课目录 NLP文本分类简介 IMDB数据集准备 设置随机种子 下载IMDB并划分数据集 构建词汇表 使用torchtext生成batch WordAveraging 模型定义 加载由glove.6 ...

  8. 【C语言探索之旅】 第一部分第六课:条件表达式

    内容简介 1.课程大纲 2.第一部分第六课:条件表达式 3.第一部分第七课预告:循环语句 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言编写三个游戏. ...

  9. Coursera公开课笔记: 斯坦福大学机器学习第六课“逻辑回归(Logistic Regression)”

    Coursera公开课笔记: 斯坦福大学机器学习第六课"逻辑回归(Logistic Regression)" 斯坦福大学机器学习第六课"逻辑回归"学习笔记,本次 ...

最新文章

  1. 使用appium做自动化测试时,send_keyss只能输入字母数字,无法输入中文
  2. 剑指offer:表示数值的字符串
  3. 做网络推广时网站结构要如何进行优化呢?
  4. Spring Boot配置IDEA无法创建Spring Initializr项目
  5. Dubbo:Dubbo入门---搭建一个最简单的Demo框架
  6. log file sync
  7. CAP 2.6 版本发布通告
  8. 面试题,如何改进一款产品
  9. 表情包+外卖+壁纸小程序源码
  10. POJ1321 Bailian1321 棋盘问题【DFS】
  11. 一个有助于理解事件冒泡和事件捕获的例子
  12. 如何从 ArcView 3.3 版本的工程迁移到 ArcGIS Desktop 10 ?
  13. 简单通用的Makefile编写例子
  14. Vue 自定义项目的创建以及配置
  15. matlab gui的callback,matlab GUI callback 函数实现
  16. 【TypeScript系列教程13】String 字符串对象的基本使用
  17. RocketMQ手动创建Topic
  18. 数据库视图view简介
  19. SAP系统PP模块常用事务代码
  20. php实现爬虫抓取法定节假日放假和补班安排数据

热门文章

  1. 9006 - ProxySQL Error: connection is locked to hostgroup 2 but trying to reach hostgroup 1
  2. 读书笔记--《软技能-代码之外的生存指南》
  3. 测试工程师需要掌握哪些软技能?
  4. 也发个过VS3.0的MapHack
  5. WIN7 ftp网线直连传东西怎么设置
  6. Python安装Numpy模块
  7. java分布式服务框架Dubbo的介绍与使用
  8. FL Studio教程之Wasp XT合成器功能介绍
  9. 关于MPO光纤连接器你知道哪些?
  10. 做计算机实验报告的总结,制作网线实验报告与总结