本周观看了李沐老师的《动手学深度学习》和李宏毅老师的课程,李沐老师很注重代码的编写,但是对概念的讲解并不是特别多,所以还要去结合一些其他的资料去进行了解;李宏毅老师讲解的理论知识真的很好,两者可以相互借鉴,互相补充学习,下面是本周的所看的课程总结。
狗的品种识别(ImageNet Dogs)
与上周的CIFAR10的识别相似,进行分类,只不过这次利用的模型为resnet34,是微调后的模型,只设置除输出层的权重参数梯度,并最终没有只对图片进行一个品种的预测,是利用softmax进行每个类别的预测概率的输出。
1、加载相关模块
import os
import torch
import torchvision
from torch import nn
from torch.utils.data import DataLoader
from d2l import torch as d2l
import collections
import shutil
import math
2、加载ImageNet Dog的tiny数据集,这个数据集小一些,方便下载和训练,其中训练集有1000张图片,测试集有10张图片,另外还有labels.csv文件,里面包括图片的id和breed品种数据
d2l.DATA_HUB['dog_tiny'] = (d2l.DATA_URL+'kaggle_dog_tiny.zip','0cb91d09b814ecdc07b50f31f8dcad3e81d6a86d')
## 如果使用Kaggle比赛的完整数据集,请将下面的变量更改为False
demo = True
if demo:
data_dir = d2l.download_extract('dog_tiny')
else:
data_dir = '../data/dog-breed-identification'
3、定义函数,读取id和breed标签的labels.csv文件,将每个id和breed生成一个字典
def read_csv_data(fname):
with open(fname,'r') as f:
lines = f.readlines()[1:]
tokens = [line.rstrip().split(',') for line in lines]
return dict(tokens)
labels = read_csv_data(os.path.join(data_dir,'labels.csv'))
labels
'''
{'0097c6242c6f3071762d9f85c3ef1b2f': 'bedlington_terrier',
'00a338a92e4e7bf543340dc849230e75': 'dingo',
'00b7d114bc5166a629a3cc03d9329120': 'irish_water_spaniel',
'00f34ac0a16ef43e6fd1de49a26081ce': 'walker_hound',
'010e87fdf252645a827e37470e65e842': 'groenendael',
'014c2b0cd8e3b517e649cecf8543b8fe': 'african_hunting_dog',
'0206c12e8984e3c8a166cc272de25d6f': 'chihuahua',
'021b5a49189665c0442c19b5b33e8cf1': 'entlebucher',
'023e4e28415506e0deddcbd8f8bdab29': 'pug',
'02508e76981e1ba059d785704b4c480c': 'pug',
}
'''
4、计算训练的样本个数以及类别数目
print('samples num',len(labels))
print('classes num',len(set(labels.values())))
'''
samples num 1000
classes num 120
'''
5、定义copy_file函数,创建文件夹,并将源图片地址复制指定文件夹下
def copy_file(fname,target_dir):
# 创建文件夹,若存在,就不在重复创建
os.makedirs(name=target_dir,exist_ok=True)
# 将源图片复制到指定文件夹下
shutil.copy(fname,target_dir)
6、定义split_copy_train_valid函数,从训练集拆分一部分做验证集,然后复制在指定文件夹下,每个训练集和测试集文件夹下都是每个类的文件夹
def split_copy_trian_valid(data_dir,labels,split_to_valid_ratio):
"""
从训练集拆分一部分做验证集,然后复制在指定文件夹下
"""
split_num = collections.Counter(labels.values()).most_common()[-1][1] # 对类别数目计数,从大到小排列,获取最少的类目 85
num_valid_per_label = max(1,math.floor(split_num*split_to_valid_ratio)) # 获取从训练集中每一类需要选出多少个样本作为验证集 floor向下取整 8
valid_label_count = {}
for train_file in os.listdir(os.path.join(data_dir,'train')):
# 获取当前图片的label
label = labels[train_file.split('.')[0]] # eg dog
# 当前图片的路径
train_file_path = os.path.join(data_dir,'train',train_file) # eg /train/1.png
absolute_path = os.path.join(data_dir,'train_valid_test') # /train_valid_test
# 复制训练集的图片到trian_valid文件夹下
copy_file(train_file_path,os.path.join(absolute_path,'train_valid',label)) # /train_valid_test/train_valid/dog
if label not in valid_label_count or valid_label_count[label]<num_valid_per_label:
# 复制训练集的图片到valid文件夹下
copy_file(train_file_path,os.path.join(absolute_path,'valid',label)) # /train_valid_test/valid/dog
valid_label_count[label] = valid_label_count.get(label,0)+1 # 统计分类数据中每个类别的出现次数
else:
# 复制训练集的图片到train文件夹下
copy_file(train_file_path,os.path.join(absolute_path,'train',label)) # /train_valid_test/train/dog
return num_valid_per_label
train_valid为原始数据集为120个类,1000张图片,train文件夹为训练集,valid文件夹为验证集,以split_to_valid_ratio比率分配数据。
7、定义copy_test函数,复制测试集图片到指定文件夹,而测试集不知道label,所以test文件夹下的类别为unknown
def copy_test(data_dir):
"""
复制测试集图片到指定文件夹
"""
for test_file in os.listdir(os.path.join(data_dir,'test')): # 复制测试集图片到test文件夹下
copy_file(os.path.join(data_dir,'test',test_file),os.path.join(data_dir,'train_valid_test','test','unknown')) # /train_valid_test/test/unknown
8、定义copy_ImageNetDogs_data函数,调用之前的函数
def copy_ImageNetDogs_data(data_dir,split_to_valid_ratio):
labels = read_csv_data(os.path.join(data_dir,'labels.csv'))
split_copy_train_valid(data_dir,labels,split_to_valid_ratio)
copy_test(data_dir)
9、定义batch_size,split_to_valid_ratio,并调用copy_ImageNetDogs_data函数
batch_size = 32 if demo else 128
split_to_valid_ratio = 0.1
copy_ImageNetDogs_data(data_dir,split_to_valid_ratio)
10、图像增广
train_augs = torchvision.transforms.Compose([
torchvision.transforms.RandomResizedCrop(224,scale=(0.08,1.0),ratio=(3.0/4.0,4.0/3.0)),
torchvision.transforms.RandomHorizontalFlip(),
torchvision.transforms.ColorJitter(brightness=0.4,contrast=0.4,saturation=0.4,hue=0.4),
torchvision.transforms.ToTensor(),
torchvision.transforms.Normalize([0.485,0.456,0.406],[0.229,0.224,0.225])
])
test_augs = torchvision.transforms.Compose([
torchvision.transforms.Resize(256),
torchvision.transforms.CenterCrop(224),
torchvision.transforms.ToTensor(),
torchvision.transforms.Normalize([0.485,0.456,0.406],[0.229,0.224,0.225])
])
11、加载数据集
train_datasets,train_valid_datasets = [torchvision.datasets.ImageFolder(
root=os.path.join(data_dir,'train_valid_test',folder),transform=train_augs
) for folder in ['train','train_valid']]
test_datasets,valid_datasets = [torchvision.datasets.ImageFolder(
root=os.path.join(data_dir,'train_valid_test',folder),transform=test_augs
) for folder in ['test','valid']]
12、总训练集个数1000个样本,从训练集分割出来的训练集880个样本,验证集120个样本,测试集10个样本
len(train_datasets),len(train_valid_datasets),len(test_datasets),len(valid_datasets)
'''
(880, 1000, 10, 120)
'''
13、创建数据迭代器
train_iter,train_valid_iter = [DataLoader(dataset=ds,batch_size=batch_size,shuffle=True,drop_last=True) for ds in [train_datasets,train_valid_datasets]]
test_iter = DataLoader(dataset=test_datasets,batch_size=batch_size,shuffle=False,drop_last=False)
valid_iter = DataLoader(dataset=valid_datasets,batch_size=batch_size,shuffle=False,drop_last=True)
14、定义get_net函数,定义resnet34模型,并设置除输出层以外的其它层的权重参数梯度为False
def get_net(devices):
finetunning_net = nn.Sequential()
finetunning_net.features = torchvision.models.resnet34(pretrained=True)
# 定义一个新的输出网络,共有120个输出类别
finetunning_net.output_layer = nn.Sequential(nn.Linear(in_features=1000,out_features=256),nn.ReLU(),nn.Linear(in_features=256,out_features=120))
finetunning_net = finetunning_net.to(devices[0])
# 设置除输出层以外的其它层的权重参数梯度为False
for param in finetunning_net.features.parameters():
param.requires_grad = False
return finetunning_net
15、定义损失函数
loss = nn.CrossEntropyLoss(reduction='none') # 每个样本的损失值而不是整体的平均损失
16、定义evaluate_loss函数,计算整体数据集上的平均损失
def evaluate_loss(data_iter,net,device):
"""
整体数据集上的平均损失
"""
loss_sum,num = 0.0,0
for X,y in data_iter:
X = X.to(device)
y = y.to(device)
y_hat = net(X)
loss_sum += loss(y_hat,y).sum() # 每批所有样本的总损失
num += y.numel() # 当前批次的样本个数
return (loss_sum/num).to('cpu')
17、定义train函数,进行训练
def train(net,train_iter,valid_iter,num_epochs,lr,weight_decay,lr_period,lr_decay,devices):
# 只迭代输出网络的参数
optimizer = torch.optim.SGD((param for param in net.parameters() if param.requires_grad),lr=lr,momentum=0.9,weight_decay=weight_decay)
lr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer=optimizer,step_size=lr_period,gamma=lr_decay)
timer,num_batches = d2l.Timer(),len(train_iter)
legend = ['train loss']
if valid_iter is not None:
legend.append('valid loss')
animator = d2l.Animator(xlabel='epoch',xlim=[1,num_epochs],legend=legend)
net = nn.DataParallel(module=net,device_ids=devices).to(devices[0])
for epoch in range(num_epochs):
metric = d2l.Accumulator(2)
net.train()
for i,(X,y) in enumerate(train_iter):
timer.start()
optimizer.zero_grad()
X,y = X.to(devices[0]),y.to(devices[0])
y_hat = net(X)
l_sum = loss(y_hat,y).sum()
l_sum.backward()
optimizer.step()
metric.add(l_sum,y.shape[0])
timer.stop()
if i%(num_batches//5)==0 or i == num_batches-1:
animator.add(epoch+(i+1)/num_batches,(metric[0]/metric[1],None))
net.eval()
messages = f'train loss {metric[0]/metric[1]}'
if valid_iter is not None:
valid_loss = evaluate_loss(valid_iter,net,devices[0])
animator.add(epoch+1,(None,valid_loss.detach().cpu()))
messages += f'valid loss {valid_loss:.3f}'
lr_scheduler.step()
print(messages+f'\n{num_epochs*metric[1]/timer.sum():.1f} example/sec,on{str(devices[0])}')
17、调整学习率等参数,进行训练
lr,weight_decay,epochs = 1e-4,1e-4,10
lr_decay,lr_period,devices = 0.9,2,d2l.try_all_gpus()
net = get_net(devices)
train(net,train_iter,valid_iter,epochs,lr,weight_decay,lr_period,lr_decay,devices)
18、在测试集上进行分类
注:此时输出并不是概率最大的类,而是将每个类别的预测概率输出
net = get_net(devices)
train(net,train_valid_iter,None,epochs,lr,weight_decay,lr_period,lr_decay,devices)
preds = []
for X,_ in test_iter:
X = X.to(devices[0])
output = torch.nn.functional.softmax(net(X),dim=-1)
preds.extend(output.cpu().detach().numpy())
indexs = sorted(os.listdir(os.path.join(data_dir,'train_valid_test','test','unknown')))
with open('submission.csv','w') as f:
f.write('id,'+','.join(train_valid_datasets.classes)+'\n')
for id,pred in zip(indexs,preds):
f.write(id.split('.')[0]+','+','.join([str(num) for num in pred])+'\n')
19、输出每个id的预测类别概率
import pandas as pd
pd.read_csv('submission.csv')
物体检测和数据集
物体检测
图像分类是在图片中只有一个主要物体对象,识别主要物体对象的类别;而目标检测是在一张图片中识别多种物体,找到在图片中的具体位置,在图片中利用方框表示。
目标检测可以应用的地方很多,比如无人驾驶,可以去识别图像中的车辆,行人等障碍物的位置。
目标检测可以使用边缘框来描述图片中的位置,边缘框是一个矩形,边缘框可以使用四个数字来表示,常用两种表示方法
第一种方式 利用图片左上角的坐标和右下角的坐标
第二种方式 利用图片中心的坐标和图片的宽和高
对于 x 轴来说,向右为 x 轴的正方向,即 x 的值从左到右依次增大
对于 y 轴来说,向下为 y 轴的正方向,y 的值从上到下依次增大
边缘框的代码实现
1、展示图片
%matplotlib inline
import torch
from d2l import torch as d2l
d2l.set_figsize()
img = d2l.plt.imread('../img/catdog.jpg')
d2l.plt.imshow(img)
2、从(左上、右下)转化到(中间、宽度、高度)的边界框
def box_corner_to_center(boxes):
"""
从(左上、右下)转化到(中间、宽度、高度)
"""
x1,y1,x2,y2 = boxes[:,0],boxes[:,1],boxes[:,2],boxes[:,3]
cx = (x1+x2) / 2
xy = (y1+y2) / 2
w = x2 - x1
h = y2 - y1
boxes = torch.stack((cx,xy,w,h),axis=-1)
return boxes
3、转化到左上,右下的边界框
def box_center_to_corner(boxes):
cx,cy,w,h = boxes[:,0],boxes[:,1],boxes[:,2],boxes[:,3]
x1 = cx - 0.5*w
y1 = cy - 0.5*h
x2 = cx + 0.5*w
y2 = cy + 0.5*h
boxes = torch.stack((x1,y1,x2,y2),axis=-1)
return boxes
4、图片中狗和猫的左上和右下的坐标
dog_bbox,cat_bbox = [60.0,45.0,378.0,516.0],[400.0,112.0,655.0,493.0]
5、验证
boxes = torch.tensor((dog_bbox,cat_bbox))
box_center_to_corner(box_corner_to_center(boxes)) == boxes
'''
tensor([[True, True, True, True],
[True, True, True, True]])
'''
6、定义函数bbox_to_rect,设置边界框位置
def bbox_to_rect(bbox,color):
return d2l.plt.Rectangle(
xy=(bbox[0],bbox[1]),width=bbox[2]-bbox[0],height=bbox[3]-bbox[1],fill=False,edgecolor=color,linewidth=2
)
7、在图片中标出边界框
fig = d2l.plt.imshow(img)
fig.axes.add_patch(bbox_to_rect(dog_bbox,'blue'))
fig.axes.add_patch(bbox_to_rect(cat_bbox,'red'))
数据集的代码实现
1、引入相关的模块
import torch
import os
import pandas as pd
import torchvision
from d2l import torch as d2l
from torch.utils import data
2、下载数据集
d2l.DATA_HUB['banana-detection'] = (
d2l.DATA_URL + 'banana-detection.zip',
'5de26c8fce5ccdea9f91267273464dc968d20d72')
data_dir = d2l.download_extract('banana-detection')
print(data_dir)
'''
../data/banana-detection
'''
数据集分为bananas_train和bananas_val
labels.csv格式如下
4、读取香蕉检测数据集
def read_data_bananas(data_dir,is_train=True):
csv_fname = os.path.join(data_dir,'bananas_train' if is_train else 'bananas_val','label.csv')
csv_data = pd.read_csv(csv_fname)
csv_data = csv_data.set_index('img_name')
images,targets = [],[]
for image_name,target in csv_data.iterrows():
images.append(torchvision.io.read_image(path=os.path.join(data_dir,'bananas_train' if is_train else 'bananas_val','images',f'{image_name}')))
targets.append(list(target))
# 将targets列表转换为pytorch张量,在第一维度上增加一个维度,将标签值除以256进行归一化处理
return images,torch.tensor(targets).unsqueeze(1)/256
images,targets = read_data_bananas(data_dir)
len(images)
'''
1000
'''
targets.shape
'''
torch.Size([1000, 1, 5]) 1000个样本,每个样本中有1个检测目标,每个检测目标有5个相关的位置信息
'''
5、加载香蕉检测数据集的自定义数据集
class BananasDataset(data.Dataset):
def __init__(self,is_train):
self.features,self.labels = read_data_bananas(data_dir,is_train)
def __getitem__(self,item):
return (self.features[item].float(),self.labels[item])
def __len__(self):
return len(self.features)
6、加载香蕉检测数据集
def load_data_bananas(batch_size):
train_iter = data.DataLoader(dataset=BananasDataset(is_train=True),batch_size=batch_size,shuffle=True)
val_iter = data.DataLoader(dataset=BananasDataset(is_train=False),batch_size=batch_size,shuffle=False)
return train_iter,val_iter
7、读取一个小批量,打印其中的图像和标签的形状
batch_size,edge_size = 32,256
train_iter,val_iter = load_data_bananas(batch_size=batch_size)
batch = next(iter(train_iter))
batch[0].shape,batch[1].shape
'''
(torch.Size([32, 3, 256, 256]), torch.Size([32, 1, 5]))
batch[0]为一个批量的图片,批量大小为32,通道数为3,每个图片大小256*256
batch[1]为一个批量的标签,批量大小为32,每个标签的检测目标为1个,标签被长度为5的数组表示,5个相关的位置信息
'''
注:
- 读取小批量的时候,图像的小批量的形状为(批量大小、通道数、高度、宽度),与图像分类任务中的相同
- 标签的小批量的形状为(批量大小,m,5)
- 其中m为 数据集的任何图像中边界框可能出现的最大数量 ,检测目标
- 5为 每个边界框的标签将被长度为5的数组表示,数组第一个元素是边界框中对象的类别,其余的4个元素是边界框左上角和右下角的坐标值,左上角和右下角的位置信息
8、进行打印
# 把每个像素点的RGB三色从0-255缩放到0-1,方便网络读入训练
# 进行维度重排,将张量的维度从 (batch_size, channels, height, width) 调整为 (batch_size, height, width, channels),show_images 函数需要最后一个维度是通道数。
imgs = (batch[0][0:10].permute(0,2,3,1))/255
axes = d2l.show_images(imgs,2,5,scale=2)
for axe,label in zip(axes,batch[1][0:10]):
d2l.show_bboxes(axe,bboxes=[label[0][1:5]*edge_size],colors=['r'])
锚框
大部分的目标检测算法是基于锚框的,在输入图像中采样大量的区域,判断区域中是否包含目标,并调整区域边界从而更加准确的预测真实的边缘框。
- 基于锚框的目标检测算法,是以每个像素为中心,生成多个缩放比和宽高比的不同边界框,锚框是算法预测的边框,是对物体真实位置的预测,而边缘框是真实标签所处区域的边框,是真实物体的位置。
- 并且基于锚框的目标检测算法提出多个称为锚框的区域(边缘框),并预测每个锚框中是否包含有关注的物体,如果有的话,预测这个锚框到真实边缘框的便宜。
IoU是用来计算两个框之间的相似度的,是两个框的交集与两个框的并集的比值
Intersection为两个框的交集,Union为两个框的并集
IoU计算后的取值范围在0和1之间,其中0表示两个框没有重叠,1表示两个框重合,所以越接近1,两个框的相似度越高。
- 在训练过程中,每个锚框是一个训练样本,我们需要每个锚框的类别和与真实边缘框的偏移量;在预测过程中,为每个图像生成多个锚框,并预测所有锚框的类别和偏移量,根据预测的偏移量来调整锚框的位置,最后获得符合条件的预测边缘框。
- 对于每个锚框,要么标注为背景,要么关联上一个真实的边缘框,对于标注为背景的锚框是锚框内不包含我们所关注的物体,只包含背景。
- 基于锚框的目标检测算法会生成大量的锚框,并且绝大部分锚框都是标注为背景,所以会导致产生大量的负类样本,负类样本就是标注为背景的锚框。
- 并且在目标检测算法的训练集中会包含每个物体类别的标签,以及真实边缘框的位置,所以要标记所生成的锚框,可以参考分配到最接近此锚框的真实边缘框的位置和类别标签。
赋予锚框编号的做法:
如下图的矩阵,表示有4个真实的边缘框,和9个生成的锚框,矩阵的每个元素都是一个锚框与一个边缘框的IoU,然后将整个矩阵中的最大IoU值挑选出来,假设是x23(它是锚框2与边缘框3的IoU,也是矩阵中最大的IoU),那么就会将边缘框3中的标号给锚框2,并删除x23所在的行和列的其他值,因为锚框2与边缘框3已经匹配成功了。
紧接着,在删除矩阵最大IoU值所在的行和列后,在剩下的矩阵元素中寻找最大IoU值,假设是x71,那么会跟上述相同,将锚框7与边缘框1关联起来,删除x71所在的行和列的其他值。
根据上述操作,重复进行,直到所有的边缘框与对应的锚框管理起来。
我们可以使用非极大值抑制(NMS)进行输出
- 在预测过程中,会为图像生成多个锚框,每个锚框可以预测一个边缘框,每个边缘框至少有一个锚框,而不是只有一个,因此会有多个相似的锚框围绕着同一个目标,我们需要对这些相似的框进行剔除,最终保留下来比较干净的预测输出结果。
- NMS的方法是首先选择所有预测框中非背景类的最大预测值,然后去掉所有其它和它IoU值大于theta的预测值,去掉和最大预测值相似度比较高的锚框,重复这个过程,直到所有的预测框要么被选中,要么被去掉,得到一个比较干净的输出。
如下图所示
总结
Meta Learning(元学习)
Meta Learning 称为元学习,Machine Learning 是让机器能够学习,Meta Learning 是让机器学会如何去学习
如下图所示
- Machine Learning 是寻找一个函数,计算损失函数,进行优化,进而得到更好的函数模型,可以进行图片的分类等等任务。
- 由人类设计一套学习算法,训练得到算法里面的参数,参数拟合出一个最优的模型,再继续用测试资料来测试这个模型。
- Meta Learning与之不同的是,由人来设计学习方法的过程,比如学习率的调整,神经网络的调整,这些由机器来进行设计一套学习方法。
- Meta Learning是要找到一个Function通过训练样本让机器自动学习原来人为确定的一些超参数,通过训练样本训练出来一个学习算法,再生成一个分类器,并进行测试,简单来说,通过Meta Learning训练出来我们之前Machine Learning的函数,再利用函数进行预测和分类。
Meta Learning的步骤
一、Meta Learning需要学习的部分定义为φ,则Function 为Fφ,Function并不是像Machine Learning那样针对特定任务的,而是针对一群类似的任务,包括猫和狗的分类、橘子和苹果的分类等等,而Function就是要在这一群类似的任务中找到一个好的超参数,下次遇到这些相似任务,可以直接利用初始化参数。
二、Meta Learning需要定义损失函数来确定学习算法Function,但是与Machine Learning不同的是,Machine Learning 的损失函数是在训练集进行计算的,而Meta Learning并不是只有训练集和测试集,它分为训练任务和测试任务,训练任务中分为多个任务,有苹果和橘子的分类,有自行车和汽车的分类等等,训练任务中分为多个任务,每个任务中有训练集和测试集。
Meta Learning中的训练任务中有多个任务,它的损失函数首先在训练任务的训练集上进行训练,得到学习算法Function,在进行生成任务1的算法分类器,在训练任务1的测试集上进行测试,通过比较其真实值,计算Cross-entropy,从而得到训练任务1的损失函数,当然,损失函数值越小,代表这个分类器越好,学习算法也越好。
扩展来说,刚才我们计算了训练任务1的损失函数,训练任务中会有多个任务,通过我们的学习算法Function,我们可以去计算后面任务的分类器,并如训练任务1的步骤一样,在训练任务中的测试集进行测试,计算损失函数,所以最后总的损失函数是每个训练任务的损失函数的和。
三、通过Meta Learning学得学习算法的第二步,我们已经得到了训练任务的损失函数,现在我们可以仿照之前Machine Learning的步骤,进行求得使损失函数最小的φ值-> φ*,如果我们可以去计算损失函数对参数φ的偏导数,那么我们可以利用我们最熟悉的Gradient Descent(梯度下降)方法进行求得我们的最优解;若损失函数Fφ对φ求不了偏导,参数φ可能是神经网络等参数,我们可以利用Reinforcement Learning或者Evolutionary Algotithm来求得我们的最优解(这两个算法目前还不太了解,后续会补),现在已经有了我们的求得最优解的φ*得到的学习算法Fφ*。
通过上面的步骤,我们已经学习到了最优的学习算法,注意我们是通过训练任务中的训练集和测试集学习到的算法,相当于Machine Learning的训练集,现在我们将我们学习到的学习算法应用到测试任务的训练集,得到相应的分类器,在利用测试任务中的测试集进行测试和预测。
我们要知道Meta Learning分为训练任务和测试任务,它们都各自有训练集和测试集,我们真正关心的是我们的测试任务。
Meta Learning与Machine Learning的不同点
目标:机器学习的目标是找到一个函数f,可以对图片进行分类;而元学习的目标是找到函数f的函数F,让机器学会如何去学习,通过函数F大量的训练样本的训练,得到最优的函数f,最终可以更好的对图片分类。
训练的数据:机器学习的训练数据是训练集,也就是一个任务,里面包含猫或者狗,对它们进行训练;元学习的训练数据是训练任务,里面包含多个任务,每个任务中有训练集和测试集,当然,为了避免重复,也把元学习的训练任务中的训练集叫做Support Set,测试集叫做Query Set。
对于机器学习,仅仅是通过训练得到的函数模型,通过测试集进行预测;而元学习则是通过训练任务得到的函数模型,它是学习算法的函数,再通过测试任务的训练集进行训练得到分类器,再对测试任务的训练集进行测试。
机器学习的训练过程叫做Within-task Training,测试过程叫做Within-task Testing;元学习的训练过程叫做Across-task Training,测试过程叫做Across-task Testing,每个训练过程中又包含Within-task Training和Within-task Testing。
注:一般把多任务的训练Across-task Training叫做Outer Loop,Within-task Training叫做Inner Loop。
Meta Learning与Machine Learning的共同点
- 机器学习与元学习都是有很大概率会遇到过拟合问题,在训练的任务中的精度很好,但是在测试的任务中精度很低。
- 机器学习与元学习遇到过拟合问题,依然可以去增加测试的任务来提高模型的精度,减少过拟合现象。
- 虽然元学习是来学习学习算法,学习机器学习函数的算法,但是我们依然要进行调整元学习的超参数,但是这属于一劳永逸,下次遇到这些相似任务,可以直接利用初始化参数。
- 并且元学习依然可以像机器学习那样利用验证集合来调整参数。
个人总结
本周主要学习了深度学习中用于物体检测的方法和理论,以及论文中元学习的一些内容,下周将继续学习其他的一些模型算法和理论知识,并且阅读相应的文献,理论与实践相结合。