深度学习中的迁移学习技术

深度学习领域,数据问题尤为突出,常常面临数据量不足或数据质量不高的挑战。一个明显的解决方案是获取更多的高质量数据,但这往往意味着需要在数据量和数据质量之间做出权衡。幸运的是,有一种更具创新性的解决方案——迁移学习

迁移学习是一种利用已经训练好的模型来完成另一项任务的方法。最初的训练步骤被称为预训练。其核心思想是,预训练阶段让模型学习到更通用的特征,而最终的微调阶段则让模型学习到特定于自己(有限的)数据的特征。

迁移学习在医学等领域尤其有用,因为这些领域长期面临数据短缺的问题。各种在ImageNet数据上预训练的CNN模型已在不同的医学任务中证明是成功的。只需要几行代码就可以将它们转移到医学数据上。

本文将学习如何使用TensorFlow——截至2021年世界上最广泛使用的深度学习平台——来实现这一点。在深入代码之前,让快速回顾一下TensorFlow和驱动它的Keras API。

TensorFlow和Keras API

TensorFlow是一个端到端的平台,可以构建和部署机器学习模型。只对构建模型感兴趣,而不是部署它们,因此需要使用Keras。Keras是一个为“人类而不是机器”设计的API,用他们自己的话来说,这意味着Keras是为像这样的编码者设计的,想要构建自定义模型。其简单且易于记忆的语法使其几乎令人上瘾。

虽然Keras API本身可以作为一个独立的Python库使用,但它也是TensorFlow库的一部分。推荐使用tensorflow.keras而不是Keras本身,因为它由TensorFlow团队维护,这确保了与其他TensorFlow模块的一致性。

案例研究:二元图像分类

作为第一个例子,将尝试二元图像分类。将使用Kaggle上的“热狗-非热狗”数据集,并尝试预测给定的图像是否是热狗。为此,将使用在ImageNet数据集上预训练的ResNet50模型。ResNet指的是使用残差连接来解决精度退化问题的一系列架构。

上面的图表展示了残差映射。这种连接跳过一个(或多个)层并执行恒等映射,F(x) + x。这种网络架构的微小调整在解决退化问题方面取得了巨大的成功。因此,ResNet架构可以深达1000层。特定的模型选择,ResNet50,是一个相对较浅的例子。可以在下面的图表中看到它的整体架构:

ResNet家族有替代品:MobileNets、Inception等也在图像分类中证明是成功的。也可以选择这些中的一个,或者一个完全不同的网络,并在其上执行迁移学习。

将在Google Colab上工作,推荐给任何计算机不胜任任务的人,尽管这不是一个严格的要求。可以在任何选择的环境中运行代码,包括Jupyter Notebook或PyChram。

设置TensorFlow迁移学习环境

注意:这一步可能根据首选环境而有所不同。

from google.colab import files files.upload() ! mkdir ~/.kaggle ! cp kaggle.json ~/.kaggle/ ! chmod 600 ~/.kaggle/kaggle.json ! pip install -q kaggle ! kaggle datasets download -d dansbecker/hot-dog-not-hot-dog import tensorflow as tf from tensorflow import keras from PIL import Image import os import numpy as np

接下来,将加载数据并开始迁移学习的过程。

!unzip /content/hot-dog-not-hot-dog.zip for image in list(os.walk("/content/train/not_hot_dog"))[0][2]: a = Image.open(f"/content/train/not_hot_dog/{image}") print(np.asarray(a).shape)

这只是输出的一部分,但已经可以看到图像大小不是恒定的。ImageDataGenerator可以处理这类问题,以及其他许多问题。

图像数据本质上是一个数字数组。彩色图像由三个2D矩阵的组合表示。这些矩阵中的每一个都由0到255之间的值组成(这可能有所不同)。这三个值结合在一起(每个值来自一个矩阵)代表像素的颜色。在例子中,图像形状是(512, 512, 3)。也就是说,有512*512=262144个像素和3个通道。(正如已经说过的,不是所有的图像都符合512*512的大小,但将处理它。)

train_datagen = tf.keras.preprocessing.image.ImageDataGenerator() test_datagen = tf.keras.preprocessing.image.ImageDataGenerator() train_data_generator = train_datagen.flow_from_directory( "/content/train", target_size=(512,512) ) test_data_generator = train_datagen.flow_from_directory( "/content/test", target_size=(512,512) )

ImageDataGenerator对象将在需要时为模型批量生成数据。这使能够直接使用存储在硬盘上的数据,而不会过度消耗RAM。train_data_generator和test_data_generator将作为参数分别传递给x和validation_data参数。由于ImageDataGenerator从文件夹名称中获取类别,不需要y参数。(如果尝试传递y参数,Python将抛出错误。)

现在训练和测试数据已经设置好了,可以构建和训练模型了。

首先,将加载Keras实现的ResNet50模型。

resnet_50 = tf.keras.applications.resnet50.ResNet50(include_top=False, weights='imagenet') resnet_50.trainable=False

include_top=False确保ResNet50模型的最后一层不会被加载。weights='imagenet'加载了ImageNet权重。如果设置weights=None,那么权重将被随机初始化(在这种情况下,将不会执行迁移学习)。通过将trainable属性设置为False,确保模型的原始(ImageNet)权重保持不变。

inputs = keras.Input(shape=(512,512,3)) x = resnet_50(inputs) x = keras.layers.GlobalAveragePooling2D()(x) outputs = keras.layers.Dense(2, activation="softmax")(x) model = keras.Model(inputs=inputs, outputs=outputs, name="my_model") model.compile(optimizer="Adam", loss="binary_crossentropy", metrics=["accuracy"]) model.summary() model.fit(train_data_generator, validation_data=test_data_generator, epochs=5)
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485