深度学习:杠杆转移学习
在我当前的项目中,我正在探讨如何利用转移学习技术来提高模型的准确性。在这个博客中,我将分享我在深度学习模型中如何利用转移学习的经验。
在深度学习空间的最新发展中,我们可以开发在非常大的数据集上训练的复杂
神经网络模型。但是,主要挑战是训练模型所需的资源和时间的限制。即使是具有1000张图像的简单图像分类模型,也需要数小时的训练时间和GPU资源。另外,由于训练数据有限,因此获得良好的准确性也是一个挑战。转移学习技术用于帮助解决有限的资源和时间挑战。
简而言之,转移学习利用的是深度学习模型,该模型对数百万个关于不同问题的数据进行了训练,无需进行全面训练即可用于类似问题。一般而言,深度学习模型具有高度的针对性。由于原始数据已经在大型数据集上进行训练,因此它具有减少训练时间并可以降低泛化误差的优势。另外,由于原始的大量训练数据,使用卷积滤波器的权重得到了很好的估计。
流行的预训练模型可用于图像分类
对于图像分类问题,有许多预训练的模型可用于预测,特征提取和微调。实例化Keras模型时,将自动下载模型权重。这是图像分类模型的列表,其权重在ImageNet上进行了训练。可在Keras应用程序页面上找到完整列表 :
?Xception
?VGG16
?VGG19
?ResNet50
我们可以通过多种方式微调原始模型并利用转移学习。根据问题的性质,我们可以按原样使用模型,或者仅训练模型的一部分,或者添加或删除模型的层。我以图像分类为例,让我们详细了解每个选项。
预训练模型作为特征提取器
图像分类模型基于检测到的特征对图像进行分类。此外,在底层中检测到的特征也是图像的一般特征,而到顶部时,它会变得比特定于图像类的特征更狭窄。这意味着来自底层要素的要素可以重新用于相似图像以解决分类问题。因此,我们可以将预训练模型中的某些或所有图层直接用作新模型的特征提取组件。
在VGG16模型中,通过仅删除将图像分类为1000类的顶层,我们可以将整个中性网络用作新数据集的固定特征提取器。要将预训练的VGG16模型用作特征提取,请以“ include_top”参数为“ False”启动VGG16模型,并将新的数据集图像形状定义为其他参数。
num_class = 4
image_size = 300
vgg = VGG16(include_top = False,pooling ='avg',weights ='imagenet',input_shape = {image_size,image_size,3))
vgg.summary()
型号:“ vgg16”
_________________________________________________________________
图层(类型)输出形状参数
================================================== ===============
input_3(InputLayer)(无,300,300,3)0
_________________________________________________________________
block1_conv1(Conv2D)(无,300,300,64)1792
_________________________________________________________________
block1_conv2(Conv2D)(无,300,300,64)36928
_________________________________________________________________
block1_pool(MaxPooling2D)(无,150,150,64)0
_________________________________________________________________
block2_conv1(Conv2D)(无,150,150,128)73856
_________________________________________________________________
block2_conv2(Conv2D)(无,150,150,128)147584
_________________________________________________________________
block2_pool(MaxPooling2D)(无,75,75,128)0
_________________________________________________________________
block3_conv1(Conv2D)(无,75,75,256)295168
_________________________________________________________________
block3_conv2(Conv2D)(无,75,75,256)590080
_________________________________________________________________
block3_conv3(Conv2D)(无,75,75,256)590080
_________________________________________________________________
block3_pool(MaxPooling2D)(无,37,37,256)0
_________________________________________________________________
block4_conv1(Conv2D)(无,37,37,512)1180160
_________________________________________________________________
block4_conv2(Conv2D)(无,37,37,512)2359808
_________________________________________________________________
block4_conv3(Conv2D)(无,37,37,512)2359808
_________________________________________________________________
block4_pool(MaxPooling2D)(无,18,18,512)0
_________________________________________________________________
block5_conv1(Conv2D)(无,18,18,512)2359808
_________________________________________________________________
block5_conv2(Conv2D)(无,18,18,512)2359808
_________________________________________________________________
block5_conv3(Conv2D)(无,18,18,512)2359808
_________________________________________________________________
block5_pool(MaxPooling2D)(无,9,9,9,512)0
_________________________________________________________________
global_average_pooling2d_2((无,512)0
================================================== ===============
参数总计:14
可训练的参数:14
不可训练的参数:0
_________________________________________________________________
具有一些预训练模型的定制模型
对于预测原始VGG16模型中没有的新类的问题,以及可用于训练的小型数据集,我们可以使用一些预训练模型层,以及针对我们要解决的新问题的新附加层。
要部署此模型,请用新的完全连接层的神经网络替换最后几层。我们可以做的是保持模型初始层的权重冻结,而我们仅重新训练较高层。我们可以尝试测试要冻结的层数和要训练的层数。根据我在其他项目中的经验,即使是很小的数据集,这种方法也给我带来了很好的准确性。
重复使用的层中的权重可以用作训练过程的起点,并可以针对新问题进行调整。这种用法将转移学习视为一种权重初始化方案。
这是我们如何仅使用原始模型中的几层来制作新模型,并节省计算时间并提高准确性的方法。
首先,加载没有最终预测层的VGG16预训练模型,然后输入如下图像形状。
num_class = 4
image_size = 300
vgg = VGG16(include_top = False,pooling ='avg',weights ='imagenet',input_shape = {image_size,image_size,3))
在这里,我从VGG16模型的输入层到block1_pool层创建了一个新模型(my_model)。您可以看到总可训练参数从原始模型减少到38k,1400万可训练参数减少到38k
layer_name ='block1_pool'
my_model =模型(inputs = vgg.input,outputs = vgg.get_layer(layer_name).output)
my_model.summary()
型号:“ model_1”
_________________________________________________________________
图层(类型)输出形状参数
================================================== ===============
input_3(InputLayer)(无,300,300,3)0
_________________________________________________________________
block1_conv1(Conv2D)(无,300,300,64)1792
_________________________________________________________________
block1_conv2(Conv2D)(无,300,300,64)36928
_________________________________________________________________
block1_pool(MaxPooling2D)(无,150,150,64)0
================================================== ===============
参数总数:38
可调参数:38
不可训练的参数:0
_________________________________________________________________
使用相同的技术,这次我们将添加其他卷积块和两个完全连接的层。现在,我们在预先训练的模型之上构建了特定于问题的层。我们的自定义模型的顶层具有softmax激活功能,可以预测新的图像类别。最后,我们将可训练标记设置为false,以冻结训练之前第一个块的图层。
从keras.layers导入Dense,Conv2D,MaxPooling2D,BatchNormalization,GlobalAveragePooling2D
模型= models.Sequential()
model.add(my_model)
model.add(Conv2D(128,(3
model.add(MaxPooling2D((2
model.add(Conv2D(256,(3
model.add(MaxPooling2D((2
model.add(GlobalAveragePooling2D())
model.add(密集(64,activation ='relu'))
model.add(BatchNormalization())
model.add(密集(num_class,activation ='softmax'))
model.layers [0] .trainable = False
model.summary()
使用“ model.summary()”的自定义模型的最终体系结构。完整模型只有40万个可训练参数,而原始VGG19中只有1400万个可训练参数。
型号:“ sequential_7”
_________________________________________________________________
图层(类型)输出形状参数
================================================== ===============
型号_1(型号)(无,150,150,64)38720
_________________________________________________________________
conv2d_4(Conv2D)(无,150,150,128)73856
_________________________________________________________________
max_pooling2d_3(MaxPooling2(None,75,75,128)0
_________________________________________________________________
conv2d_5(Conv2D)(无,75,75,256)295168
_________________________________________________________________
max_pooling2d_4(MaxPooling2(None,38,38,256)0
_________________________________________________________________
global_average_pooling2d_4((无,256)0
_________________________________________________________________
density_5(Dense)(None,64)16448
_________________________________________________________________
batch_normalization_2(批处理(无,64)256
_________________________________________________________________
density_6(Dense)(None,4)260
================================================== ===============
参数总计:424
可训练的参数:385
不可训练参数:38
_________________________________________________________________
使用预训练模型的体系结构
这里有一个大型图像数据集,并且类完全不同。在这种情况下,我们可以使用VGG19模型的体系结构并使用新数据训练模型。尽管我们需要巨大的计算能力来训练模型,但它节省了模型构建工作的时间,这是解决新问题的良好起点。在当前的项目中,我正在使用基于ImageNet的更快的RCNN预训练模型之一。最初的培训阶段对我有很大帮助,并且可以轻松自定义图层。在NLP空间上,我确实使用了预训练模型,因为它用于嵌入基于向量的语言模型。我使用了 在医学数据集上经过训练的BioSentVec模型的问答模型,以使用COVID19相关项目。
这是示例代码片段
####加载VGG16并设置为不可训练
conv_base =应用程序。VGG16(权重=“ imagenet”,include_top = False,input_shape = [150,150,3])
conv_base.trainable =假
####用新图像预测班级
ret1 = conv_base.predict(np.ones([1,150,150,3]))
结论
我们可以采用多种方法来利用预训练的模型。人们尝试过各种不同类型的数据集的体系结构,我强烈建议您仔细研究经过预训练的模型的体系结构,并将其应用于您自己的问题陈述中。最好的方法取决于您要解决的问题。我建议从一个小的样本数据集开始评估预训练模型,并查看预训练模型的性能。尝试利用尽可能多的预训练模型层,并添加自定义层以提高准确性。尤其是当您的训练数据有限时,将预训练的模型层与自定义层一起使用是明智的方法。

关注 CDA人工智能学院 ,回复“录播”获取更多人工智能精选直播视频!