·发布于 Towards Data Science ·8 分钟阅读·2024 年 1 月 22 日
--
作者: Ian Stebbins, Benjamin Goldfried, Ben Maizes
对于许多领域特定的问题,数据的匮乏可能会妨碍深度神经网络的有效性,甚至使其无法使用。然而,生成对抗网络(GAN)的最新架构使我们能够通过创建捕捉数据分布中细节、纹理和变异的新样本来合成增强数据。这些合成数据可以作为深度神经网络的额外训练输入,从而使数据稀缺的领域任务变得更加可行。
在这个项目中,我们使用了带有自适应判别器增强(ADA)的 NVIDIA StyleGAN-2,应用于一个小型的胸部 CT 扫描数据集(许可协议:数据库:开放数据库,内容:© 原作者)[1]。此外,我们构建了一个 CNN 分类器,用于区分正常扫描与肿瘤扫描。通过将不同比例的合成生成数据注入到不同模型的训练过程中,我们能够评估仅使用真实数据与使用真实-合成混合数据模型之间的性能差异。
StyleGAN-2 与 ADA 首次由 NVIDIA 在 2020 年 NeurIPS 论文中提出:“在有限数据上训练生成对抗网络” [2]。过去,在小数据集上训练 GAN 通常会导致网络判别器过拟合。因此,判别器往往不是学习区分真实数据和生成数据,而是倾向于记住训练集中的噪声和异常值的模式,而不是学习数据分布的一般趋势。为了解决这个问题,ADA 根据训练中观察到的过拟合程度动态调整数据增强的强度。这有助于模型更好地进行泛化,并在小数据集上实现更好的 GAN 性能。
要使用 StyleGAN-2 ADA 模型,我们使用了来自 GitHub 的官方 NVIDIA 模型实现,具体可以在这里找到。请注意,这是 StyleGAN-3 的仓库,但仍然可以运行 StyleGAN-2。
!git clone https://github.com/NVlabs/stylegan3
根据你的设置,你可能需要安装依赖项并进行一些其他预处理。例如,我们选择将数据集图像调整大小并缩小为 224x224,因为我们只有一个 GPU,使用更大的图像尺寸在计算上更加昂贵。我们选择使用 224x224 的图像尺寸,因为我们为 CNN 选择的预训练模型 ResNet 优化了这种图像大小。
!pip install pillow
from PIL import Image
import os
'''Loops through the files in an input folder (input_folder), resizes them to a
specified new size (new_size), an adds them to an output folder (output_folder).'''
def resize_images_in_folder(input_folder, output_folder, new_size):
# Loop through all files in the input folder
for filename in os.listdir(input_folder):
input_path = os.path.join(input_folder, filename)
# Check if the file is an image
if os.path.isfile(input_path) and filename.lower().endswith(('.png', '.jpg', '.jpeg', '.gif')):
# Open the image file
image = Image.open(input_path)
#Convert to RGB
image = image.convert('RGB')
# Resize the image
resized_image = image.resize(new_size)
# Generate the output file path
output_path = os.path.join(output_folder, filename)
# Save the resized image to the output folder
resized_image.save(output_path)
print(f"Resized {filename} and saved to {output_path}")
要开始训练过程,首先导航到你克隆的仓库目录,然后运行以下命令。
import os
!python dataset_tool.py --source= "Raw Data Directory" --dest="Output Directory" --resolution='256x256'
# Training
EXPERIMENTS = "Output directory where the Network Pickle File will be saved""
DATA = "Your Training DataSet Directory"
SNAP = 10
KIMG = 80
# Build the command and run it
cmd = f"/usr/bin/python3 /content/stylegan3/train.py --snap {SNAP} --outdir {EXPERIMENTS} --data {DATA} --kimg {KIMG} --cfg stylegan2 --gpus 1 --batch 8 --gamma 50"
!{cmd}
SNAP指的是你希望在多少个训练步骤(信息显示的训练步数)后拍摄网络快照并将其保存到 pickle 文件中。
KIMG指的是你希望输入到 GAN 中的成千上万的图像数量。
GAMMA d决定正则化对判别器的影响强度。
初始生成的图像
训练期间生成的图像
一旦你的模型完成训练(根据你的计算资源,这可能需要多个小时),你就可以使用训练好的网络生成图像。
pickle_file = "Network_Snapshot.pkl"
model_path = f'Path to Pickle File/{pickle_file}'
SAMPLES = Number of samples you want to generate
!python /content/stylegan3/gen_images.py --outdir=Output Directory --trunc=1 --seeds {SAMPLES} \
--network=$model_path
正常真实图像(左)与正常生成图像(右)
为了评估我们合成生成数据的有效性,我们首先在原始数据上训练了一个 CNN 模型。一旦我们得到了测试集上的基准准确度,我们就用逐渐增加的合成数据重新训练了模型。
为了将数据输入模型,我们使用了 Keras 数据生成器,它将样本直接从指定目录流入模型。原始数据集有 4 个类别,分别代表不同类型的癌症,但为了简化问题,我们将其转化为二分类问题。我们决定从原始 Kaggle 数据集中选择正常类和鳞状类进行处理。
# Define directories for training, validation, and test datasets
train_dir = 'Your training data directory'
test_dir = 'Your testing data directory'
val_dir = 'Your validation data directory'
# Utilize data genarators to flow directly from directories
train_generator = train_datagen.flow_from_directory(
train_dir,
target_size=(224, 224),
batch_size=20,
class_mode='binary', #Use 'categorical' for multi-class classification
shuffle=True,
seed=42 )
val_generator = val_datagen.flow_from_directory(
val_dir,
target_size=(224, 224),
batch_size=20,
class_mode='binary',
shuffle=True )
test_generator = test_datagen.flow_from_directory(
test_dir,
target_size=(224, 224),
batch_size=20,
class_mode='binary',
shuffle=True )
为了构建我们的模型,我们首先使用了 ResNet50 基础架构和模型权重。我们选择使用 ResNet50 是因为它具有适中的架构大小、良好的文档支持,并且通过 Keras 易于使用。在导入带有 Imagenet 模型权重的 ResNet50 后,我们冻结了 ResNet50 的层,并在其上添加了可训练的密集层,帮助网络学习我们特定的分类任务。
我们还选择了引入批量归一化(batch normalization),通过对层输入进行归一化并减少内部协变量偏移,能够加速收敛并使训练更加稳定[3]。此外,它还可以提供一种正则化效果,有助于防止我们添加的可训练密集层发生过拟合。
我们的模型架构
起初,我们的模型表现不佳。我们通过将激活函数从 ReLU 切换到 leaky ReLU 解决了这个问题。这表明我们的网络可能正面临着 ReLU 死亡或神经元失效的问题。简而言之,由于 ReLU 对负数的梯度始终为零,这可能导致神经元“死亡”,从而无法对网络作出贡献[4][5]。由于 leaky ReLU 对负值不为零,使用它作为激活函数有助于解决这个问题。
为了测试我们的合成数据,我们在 5 个不同实例上训练了上述 CNN,分别使用了 0%、25%、50%、75%和 100%的附加合成样本。例如,0%的合成样本意味着数据全部为原始数据,而 100%则意味着训练集包含相等数量的原始数据和合成数据。对于每个网络,我们随后使用准确度指标在一组未见过的实际测试数据上评估了性能。下图可视化了不同合成数据比例对测试准确率的影响。
二分类(正常与鳞状肿瘤)分类的测试准确率
训练模型时不稳定,因此我们排除了准确度为 1.0 或极低的迭代。这帮助我们避免了过拟合或欠拟合的训练迭代。
我们可以看到,从 0%到 25%时,测试准确度出现了急剧上升,这表明即使是通过少量的数据增强,也能对数据最初较少的问题产生较大影响。
由于我们仅在 80 KIMG 上训练了我们的 GAN(由于计算限制),因此如果有更多的 GAN 训练迭代,我们的合成数据质量可能会更好。值得注意的是,合成数据质量的提高也可能影响上述图表。我们假设,合成数据质量的提高将导致在训练中使用合成数据的最佳比例增加。此外,如果合成图像更好地适应我们训练数据的真实分布,我们就可以在模型训练中融入更多的合成图像而不至于过拟合。
在这个项目中,使用 GAN 进行有限数据的增强被证明是扩展训练集并且更重要的是提高分类精度的有效技术。尽管我们选择了一个小而基础的问题,但这一技术可以通过几种方式轻松扩展。未来的工作可能包括使用更多的计算资源来获取更好的合成样本,引入更多的类别到分类任务中(使其成为一个多分类问题),并实验更新的 GAN 架构。不管怎样,使用 GAN 增强小数据集现在可以将许多以前受数据限制的问题纳入深度神经网络的范畴。
我们将增强和重新调整大小的图像汇编成以下Kaggle 数据集。该数据集包含 501 张正常和 501 张鳞状的 224x224 合成图像,可用于进一步的实验。
引用
[1] Hany, Mohamed, 胸部 CT 扫描图像数据集,Kaggle(2020)。
[2] Karras, Tero,等, 使用有限数据训练生成对抗网络(2020),《神经信息处理系统进展》2020。
[3] Ioffe, Sergey, 和 Christian Szegedy, 批量归一化:通过减少内部协变量偏移加速深度网络训练,(2015),国际机器学习会议。pmlr,2015。
[4] He, Kaiming,等, 深入探讨修正器:在 imagenet 分类中超越人类级别的表现,(2015),IEEE 国际计算机视觉会议论文集。2015。
[5] Bai, Yuhan, RELU 函数及其导函数回顾,(2022),SHS Web of Conferences。第 144 卷。EDP Sciences,2022。