研究白癜风的专家 https://wapjbk.39.net/yiyuanfengcai/ys_bjzkbdfyy/上期图文,我们分析了HydraNets特斯拉AI模型,之所以此模型称之为特斯拉疯狂的AI模型,主要是一个模型来完成自动驾驶上面的所有任务。
HydraNet——特斯拉自动驾驶强大的人工智能神经网络模型
Hydranets
我们知道特斯拉的自动驾驶任务,使用的是纯视觉的自动驾驶任务,完全脱离了雷达。这就跟一个正常的司机驾驶一个真正的汽车一样,在驾驶汽车时,不仅要看得懂路上的红路灯,还要实时地查看行人以及路上的车道线,各种车辆,以及车辆的行驶信息,路标等等信息来指导一个驾驶员正常驾驶汽车
虽然以上的每个任务,在计算机视觉领域中,都有类似的AI模型来识别与检测,但是针对自动驾驶来说,不可能安装那么多的电脑来处理如此多的任务,或者说在一台电脑上,同时运行如此多的AI模型。特斯拉AI研究人员,基于一种新的神经网络Regnet(正则网络结构)开发了自己的神经网络模型,且在处理头部分,更是采用多头任务。这就是我们上期介绍的HydraNets模型。
——1——
Hydranets——特斯拉的疯狂神经网络
计算机视觉任务中,物体检测一般有如下通用的结构:
Input→backbone→neck→head→Output
Backbone:指特征提取网络,用于识别单个图像中的多个对象,并提供对象的丰富特征信息。我们经常使用AlexNet、ResNet、VGGNet作为骨干网络。特斯拉采用的是Regnet(正则网络结构
检测头(head):在特征提取(骨干)之后,它为我们提供了输入的特征图表示。对于一些实际的任务,比如检测对象、分割等。我们通常在特征图上应用一个“检测头”,所以它就像一个头附着在主干上。特斯拉采用的是Hydranets
neck:颈部位于主干和头部之间,用于提取一些更精细的特征。(例如特征金字塔网络(FPN),BiFPN)
Hydranets模型
1、所有8幅图像首先由图像提取器处理。为此,使用了类似于ResNet的架构,Regnet(正则网络结构)
2、然后是多机位融合。这个想法是将所有8个图像组合成一个超级图像。为此,HydraNets使用了类似transformer的架构。
3、时间融合。这个想法是将时间带入神经网络,并将超级图像与所有先前的超级图像融合在一起。为此,有N个图像的视频队列。例如,如果他们想用2秒进行融合,并且假设摄像机以每秒30帧的速度工作,N将为60。时间融合是使用3DCNN、RNN或Transformer完成的。
4、最后,输出被分成HEADS。
正是采用以上的HydraNets模型,特斯拉把所有自动驾驶的任务放在了一个神经网络模型中,包括自动驾驶中的车型识别,车辆追踪,人物识别,人物追踪,车道线的检测与分割人物,距离判断,信号灯与各种路牌指示任务等等,差不多48个任务被特斯拉放置在一个模型中来训练与运行,这里不仅感慨,马斯克的疯狂!!
——2——
HydraNets与pytorch的结合
HydraNets模型,根据一些信息,其模型训练在pytorch架构下,但是自动驾驶汽车作为特斯拉的核心技术,其HydraNets模型并没有开源代码,我们按照一个简单的任务来熟悉一下多任务模型的处理步骤
1、数据集
UTKFace数据集是一个年龄跨度大的大规模人脸数据集,年龄范围从0到岁。这些图像涵盖了姿势、面部表情、光照、遮挡、分辨率等方面的巨大变化。
大小:数据集包含超过2万张带有年龄、性别和种族注释的图像。
项目:该数据集可用于各种任务,例如面部检测、年龄估计、年龄进展、年龄回归、地标定位等。
我们按照UTK数据集来介绍,UTK人脸数据集是一个分类数据集,其中每张图像都有3个标签:
性别(男性或女性)种族(白人、黑人、亚洲人、印度人、其他)年龄(连续数字)
因此,我们的HydraNet将有3个头,每个任务一个头。这些头的任务不会是相同的:
预测年龄是一个回归任务预测性别是一个二元分类任务预测种族是一个多类分类任务
数据集是一组图像,图像的名称给出了神经网络模型标签。
例如图像UTKFace/18_0_0_.jpgUTKFace/是前缀18是年龄0是性别(0:男性,1:女性)0是种族(0:白人,1:黑人,2:亚洲人,3:印度人,4:其他)剩下的是日期和扩展名(jpg)
2、数据初始化处理
根据以上的数据库格式,我们在代码中,需要把图片数据中的年龄,性别,种族,三个参数提取出来,方便我们的神经网络模型进行训练,以便后期添加图片的三个维度标签。
def__init__(self,image_paths):self.transform=transforms.Compose([transforms.Resize((32,32)),transforms.ToTensor(),transforms.Normalize([0.,0.,0.],[0.,0.,0.])])self.image_paths=image_pathsself.images=[]self.ages=[]self.genders=[]self.races=[]forpathinimage_paths
ilename=path[8:].split("_")iflen(filename)==4:self.images.append(path)self.ages.append(int(filename[0]))self.genders.append(int(filename[1]))self.races.append(int(filename[2]))
初始化函数中,我们首先定义了一个tensor变量,来转换我们的输入图片到pytorch能够处理,且模型能够处理的tensor变量。
然后我们遍历所有UTK文件夹下的所有人脸图片,并把图片的路径,图片的年龄,性别,种族信息保存到一个list里面,方便后期进行模型的训练。
3、数据标签的提取与使用
通过第二步的实现,我们已经搜集到了UTK图片的路径信息,以及每个路径图片对应的年龄,性别,种族信息,在我们训练神经网络模型时,我们需要提出保存的信息,送入神经网络模型
def__getitem__(self,index):img=Image.open(self.images[index]).convert(RGB)img=self.transform(img)age=self.ages[index]gender=self.genders[index]race=self.races[index]sample={image:img,age:age,gender
ender,race:race}turnsample
首先,我们打开index索引下的一张图片,并转换到RGB颜色空间,并把图片转换到模型需要的tensor变量,我们可以根据index索引,来获取图片的年龄,性别,种族信息,当然,我们把这些信息保存在一个字典里面。
4、神经网络模型的建立
当然,在计算机视觉任务里,有很多模型可以帮助我们搜集人脸信息,比如ResNet、MobileNet、Inception等等,但是以往的模型训练与检测都是在一个任务上面实现的,我们需要把最后的检测头部分,改写成我们需要的头。
classHydraNet(nn.Module)
ef__init__(self):super().__init__()self.net=models.snet18(ptrained=True)self.n_featus=self.net.fc.in_featusself.net.fc=nn.Identity()self.net.fc1=nn.Sequential(OrdedDict([(linear,nn.Linear(self.n_featus,self.n_featus)),(lu1,nn.ReLU()),(final,nn.Linear(self.n_featus,1))]))self.net.fc2=nn.Sequential(OrdedDict([(linear,nn.Linear(self.n_featus,self.n_featus)),(lu1,nn.ReLU()),(final,nn.Linear(self.n_featus,1))]))self.net.fc3=nn.Sequential(OrdedDict([(linear,nn.Linear(self.n_featus,self.n_featus)),(lu1,nn.ReLU()),(final,nn.Linear(self.n_featus,5))]))defforward(self,x):age_head=self.net.fc1(self.net(x))gender_head=self.net.fc2(self.net(x))race_head=self.net.fc3(self.net(x))turnage_head,gender_head,race_head
本例子采用了ResNet模型,当然其他模型都可以实现,然后我们建立了三个net.fc
fc1:作为年龄的全连接层fc2:对于性别的全连接层fc3:对于种族的全连接层
5、模型的训练
在多任务学习中,我们仍然只有一个loss,不同之处是,此loss是所有损失的和。
AgeLoss,是一种回归损失。例如,均方误差或负对数。RaceLoss,是一种多类分类损失。此例子中,它是交叉熵!GenderLoss,是一种BinaryClassificationloss。二元交叉熵。
net=snet18(ptrained=True)model=HydraNet(net).to(device=device)race_loss=nn.CrossEntropyLoss()#交叉熵损失gender_loss=nn.BCELoss()#二元交叉熵损失age_loss=nn.L1Loss()#取预测值和真实值的绝对误差的平均数optimizer=torch.optim.SGD(model.parameters(),lr=1e-4,momentum=0.09)Sig=nn.Sigmoid()
根据模型不同头的性质,采用不同的loss函数,当然,我们希望所有的loss都是最小的,需要注意的是,对于二元分类,我们将使用不包括softmax的二元交叉熵。相反,我们将使用更适合这种特殊情况的Sigmoid函数。
forepochinrange(n_epochs):model.train()total_training_loss=0fori,datainenumerate(train_dataloader):inputs=data["image"].to(device=device)age_label=data["age"].to(device=device)gender_label=data["gender"].to(device=device)race_label=data["race"].to(device=device)optimizer.zero_grad()age_output,gender_output,race_output=model(inputs)loss_1=race_loss(race_output,race_label)loss_2=gender_loss(sig(gender_output),gender_label.unsqueeze(1).float())loss_3=age_loss(age_output,age_label.unsqueeze(1).float())loss=loss_1+loss_2+loss_3loss.backward()optimizer.step()total_training_loss+=loss
当然经过模型的训练后,loss函数会越来越小,一旦我们的loss达到我们训练的水准后,我们就可以使用此训练模型来进行人脸的性别,年龄,种族的检测。