宠物面部分类#
来自 AI for Beginners Curriculum 的实验任务。
获取数据#
在本次任务中,我们将专注于一个相对简单的分类任务——宠物面部分类。我们将使用 Oxford-IIIT Pet Dataset,该数据集包含37种不同品种的猫狗的图片。让我们从下载并可视化数据集开始。
注意: Oxford-IIIT Pet Dataset 包含完整的宠物图片。提取后的文件夹中,图片将按品种进行组织。
!wget https://thor.robots.ox.ac.uk/~vgg/data/pets/images.tar.gz
!tar xfz images.tar.gz
!rm images.tar.gz--2022-02-17 12:32:43-- https://thor.robots.ox.ac.uk/~vgg/data/pets/images.tar.gz
Resolving mslearntensorflowlp.blob.core.windows.net... 20.150.90.68
Connecting to mslearntensorflowlp.blob.core.windows.net|20.150.90.68|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 24483412 (23M) [application/x-gzip]
Saving to: ‘images.tar.gz’
images.tar.gz 100%[===================>] 23.35M 12.5MB/s in 1.9s
2022-02-17 12:32:45 (12.5 MB/s) - ‘images.tar.gz’ saved [24483412/24483412]
我们将定义通用函数以从列表中显示一系列图像:
import matplotlib.pyplot as plt
import os
from PIL import Image
import numpy as np
def display_images(l,titles=None,fontsize=12):
n=len(l)
fig,ax = plt.subplots(1,n)
for i,im in enumerate(l):
ax[i].imshow(im)
ax[i].axis('off')
if titles is not None:
ax[i].set_title(titles[i],fontsize=fontsize)
fig.set_size_inches(fig.get_size_inches()*n)
plt.tight_layout()
plt.show()现在让我们遍历所有类别子目录并绘制每个类别的前几张图像:
# Note: The Oxford-IIIT Pet Dataset extracts to a folder named 'images'
# Images are named by breed (e.g., 'Abyssinian_1.jpg')
# We need to organize them into breed-specific subdirectories
import os
from collections import defaultdict
# Organize images by breed
if not os.path.exists('petfaces'):
os.makedirs('petfaces')
for img_file in os.listdir('images'):
if img_file.endswith(('.jpg', '.png')):
# Extract breed name from filename (everything before the last underscore and number)
breed = '_'.join(img_file.split('_')[:-1])
breed_dir = os.path.join('petfaces', breed)
if not os.path.exists(breed_dir):
os.makedirs(breed_dir)
os.rename(os.path.join('images', img_file), os.path.join(breed_dir, img_file))
for cls in os.listdir('petfaces'):
print(cls)
display_images([Image.open(os.path.join('petfaces',cls,x))
for x in os.listdir(os.path.join('petfaces',cls))[:10]])让我们也定义数据集中的类别数量:
num_classes = len(os.listdir('petfaces'))
num_classes35为深度学习准备数据集#
在开始训练我们的神经网络之前,我们需要将所有图像转换为张量,并创建与标签(类别编号)对应的张量。大多数神经网络框架都包含处理图像的简单工具:
- 在 Tensorflow 中,使用
tf.keras.preprocessing.image_dataset_from_directory - 在 PyTorch 中,使用
torchvision.datasets.ImageFolder
正如你从上面的图片中看到的,所有图片的比例都接近正方形,因此我们需要将所有图像调整为正方形尺寸。此外,我们还可以将图像组织成小批量。
# CODE TO LOAD DATASET现在我们需要将数据集分为训练集和测试集:
# CODE TO DO TRAIN/TEST SPLIT现在让我们打印数据集中张量的大小。如果你一切都设置正确,训练元素的大小应该是:
- 对于 Tensorflow,应该是
(batch_size,image_size,image_size,3);对于 PyTorch,应该是batch_size,3,image_size,image_size - 标签的大小应该是
batch_size
标签应该包含类别的编号。
# Print tensor sizes# Display the data定义神经网络#
对于图像分类,通常需要定义一个具有多层的卷积神经网络。需要注意以下几点:
- 牢记金字塔架构,即随着网络加深,滤波器的数量应该增加。
- 不要忘记在层之间使用激活函数(如 ReLU)和最大池化。
- 最终的分类器可以有隐藏层,也可以没有,但输出神经元的数量应等于类别的数量。
一个重要的点是要正确设置最后一层的激活函数和损失函数:
- 在 Tensorflow 中,可以使用
softmax作为激活函数,并使用sparse_categorical_crossentropy作为损失函数。稀疏类别交叉熵与非稀疏的区别在于,前者期望输出为类别编号,而不是独热向量。 - 在 PyTorch 中,最后一层可以不使用激活函数,并使用
CrossEntropyLoss作为损失函数。该函数会自动应用 softmax。
# CODE TO DEFINE NEURAL NETWORK训练神经网络#
现在我们可以开始训练神经网络了。在训练过程中,请在每个训练周期收集训练数据和测试数据的准确率,然后绘制准确率图表,以观察是否存在过拟合现象。
为了加快训练速度,如果有 GPU 可用,请务必使用 GPU。虽然 TensorFlow/Keras 会自动使用 GPU,但在 PyTorch 中,你需要在训练过程中使用
.to()方法将模型和数据都移到 GPU 上,以利用 GPU 加速。
# TRAIN THE NETWORK# PLOT THE ACCURACY on train and validation dataset关于过拟合,你可以说什么?如何提高模型的准确性?
可选:计算 Top3 准确率#
在本次练习中,我们处理的是一个类别数量较多的分类问题(35个类别),因此我们的结果——大约50%的验证准确率——已经相当不错了。标准的 ImageNet 数据集甚至有更多类别——1000个。
在这种情况下,很难确保模型总是正确预测类别。有些情况下,两种类别非常相似,模型返回的概率也非常接近(例如,0.45和0.43)。如果我们测量标准准确率,这种情况会被认为是错误的,即使模型只犯了一个很小的错误。因此,我们经常测量另一种指标——模型预测中最可能的前三个类别的准确率。
如果目标标签包含在模型预测的前三个类别中,我们就认为该情况是准确的。
要在测试数据集上计算 Top-3 准确率,你需要手动遍历数据集,应用神经网络获取预测结果,然后进行计算。一些提示:
- 在 Tensorflow 中,可以使用
tf.nn.in_top_k函数来查看predictions(模型的输出)是否在 top-k(将k=3作为参数),与targets相比。此函数返回一个布尔值的张量,可以使用tf.cast转换为int,然后使用tf.reduce_sum累积。 - 在 PyTorch 中,可以使用
torch.topk函数获取具有最高概率的类别索引,然后查看正确类别是否属于其中。请参阅 此处 获取更多提示。
# CALCULATE TOP-3 ACCURACY可选:构建猫与狗分类#
我们还想看看在同一数据集上,我们的二元猫与狗分类的准确性如何。为此,我们需要调整标签:
# Define dataset that contains only two labels: 0 = cat, 1 = dog
# Hint: use class name prefix to figure out which one is which# Define neural network architecture and train免责声明:
本文档使用AI翻译服务 Co-op Translator 进行翻译。尽管我们努力确保翻译的准确性,但请注意,自动翻译可能包含错误或不准确之处。原始语言的文档应被视为权威来源。对于关键信息,建议使用专业人工翻译。我们对因使用此翻译而产生的任何误解或误读不承担责任。