1。序文
このタスクは、ResNet18 ネットワークを使用して、より一般的な画像分類タスクを実践することです。
画像分類の分野でよく知られているアルゴリズムである ResNet シリーズのネットワークは、永続的で時代を超越したものであり、今日まで幅広い研究の重要性とアプリケーション シナリオを持っています。業界によってさまざまな改善が行われており、画像認識タスクによく使用されます。
今日は、主に ResNet-18 ネットワーク構造のケースを紹介します。その他のディープ ネットワークも順番に推測できます。
ResNet-18、数字はネットワークの深さを表しています。つまり、ResNet18 ネットワークには 18 層ありますか? 実際、ここでの 18 は、畳み込み層と全結合層を含み、プーリング層と BN 層を除く、重み付きの 18 層を指定します。
画像分類は、コンピューター ビジョンの基本的なタスクであり、画像のセマンティクスによってさまざまな画像をさまざまなカテゴリに分類します。多くのタスクは、画像分類タスクに変換することもできます。たとえば、顔検出は、領域内に顔があるかどうかを判断することであり、これは 2 値画像分類タスクと見なすことができます。
- データセット: コンピュータ ビジョンの分野で使用される古典的な CIFAR-10 データセット
- ネットワーク層: ネットワークは ResNet18 モデルです
- オプティマイザー: オプティマイザーは Adam オプティマイザーです。
- 損失関数: 損失関数はクロス エントロピー損失です
- 評価指数:評価指数は正解率
ResNet ネットワークの紹介:
2。データの前処理
2.1 データセットの紹介
CIFAR-10 データセットには、合計 60,000 枚の画像を持つ 10 の異なるカテゴリが含まれており、各カテゴリには 6,000 枚の画像があり、画像サイズは 32 × 3232 × 32 ピクセルです。
2.2 データ読み込み
この実験では、元のトレーニング セットが train_set と dev_set の 2 つの部分に分割され、それぞれ 40,000 と 10,000 のサンプルが含まれます。data_batch_1 から data_batch_4 をトレーニング セット、data_batch_5 を検証セット、test_batch をテスト セットとして使用します。最終的なデータセットは次のもので構成されます。
- トレーニング セット: 40,000 サンプル。
- 検証セット: 10,000 サンプル。
- テスト セット: 10,000 サンプル。
データのバッチを読み取るコードは次のとおりです。
import os
import pickle
import numpy as np
def load_cifar10_batch(folder_path, batch_id=1, mode='train'):
if mode == 'test':
file_path = os.path.join(folder_path, 'test_batch')
else:
file_path = os.path.join(folder_path, 'data_batch_'+str(batch_id))
#加载数据集文件
with open(file_path, 'rb') as batch_file:
batch = pickle.load(batch_file, encoding = 'latin1')
imgs = batch['data'].reshape((len(batch['data']),3,32,32)) / 255.
labels = batch['labels']
return np.array(imgs, dtype='float32'), np.array(labels)
imgs_batch, labels_batch = load_cifar10_batch(folder_path='datasets/cifar-10-batches-py',
batch_id=1, mode='train')
データの次元を表示します。
#打印一下每个batch中X和y的维度
print ("batch of imgs shape: ",imgs_batch.shape, "batch of labels shape: ", labels_batch.shape)
imgs 形状のバッチ: (10000, 3, 32, 32) ラベル形状のバッチ: (10000,)
サンプル画像の 1 つと対応するラベルを視覚的に観察すると、コードは次のようになります。
%matplotlib inline
import matplotlib.pyplot as plt
image, label = imgs_batch[1], labels_batch[1]
print("The label in the picture is {}".format(label))
plt.figure(figsize=(2, 2))
plt.imshow(image.transpose(1,2,0))
plt.savefig('cnn-car.pdf')
2.3 Dataset クラスの構築
paddle.io.DataSet
クラスから継承され、データを 1 つずつ処理できるCIFAR10Dataset クラスを構築します。コードは次のように実装されます。
import paddle
import paddle.io as io
from paddle.vision.transforms import Normalize
class CIFAR10Dataset(io.Dataset):
def __init__(self, folder_path='/home/aistudio/cifar-10-batches-py', mode='train'):
if mode == 'train':
#加载batch1-batch4作为训练集
self.imgs, self.labels = load_cifar10_batch(folder_path=folder_path, batch_id=1, mode='train')
for i in range(2, 5):
imgs_batch, labels_batch = load_cifar10_batch(folder_path=folder_path, batch_id=i, mode='train')
self.imgs, self.labels = np.concatenate([self.imgs, imgs_batch]), np.concatenate([self.labels, labels_batch])
elif mode == 'dev':
#加载batch5作为验证集
self.imgs, self.labels = load_cifar10_batch(folder_path=folder_path, batch_id=5, mode='dev')
elif mode == 'test':
#加载测试集
self.imgs, self.labels = load_cifar10_batch(folder_path=folder_path, mode='test')
self.transform = Normalize(mean=[0.4914, 0.4822, 0.4465], std=[0.2023, 0.1994, 0.2010], data_format='CHW')
def __getitem__(self, idx):
img, label = self.imgs[idx], self.labels[idx]
img = self.transform(img)
return img, label
def __len__(self):
return len(self.imgs)
paddle.seed(100)
train_dataset = CIFAR10Dataset(folder_path='datasets/cifar-10-batches-py', mode='train')
dev_dataset = CIFAR10Dataset(folder_path='datasets/cifar-10-batches-py', mode='dev')
test_dataset = CIFAR10Dataset(folder_path='datasets/cifar-10-batches-py', mode='test')
3. モデル構築
Flying Paddle 高レベル API で Resnet18 を使用した画像分類実験。
from paddle.vision.models import resnet18
resnet18_model = resnet18()
パドルの高レベル API は、パドル API のさらなるカプセル化とアップグレードであり、より簡潔で使いやすい API を提供し、パドルの学習と使用の容易さをさらに向上させます。その中で、フライング パドルの高レベル API は次のモジュールをカプセル化します。
- 数行のコードのみでモデルのトレーニングをサポートするモデル クラス。
- 基本的に一般的なデータ処理とデータ強化方法をカバーする、数十のデータ処理機能を含む画像前処理モジュール。
- mobilenet、resnet、yolov3、cyclegan、bert、transformer、seq2seqなどを含むがこれらに限定されない、コンピュータービジョンおよび自然言語処理の分野における一般的なモデル。同時に、対応するモデルの事前トレーニング済みモデルがリリースされます。 、およびこれらのモデルは、二次開発の完了に基づいて、直接またはここで使用できます。
4. モデルトレーニング
RunnerV3 クラスを再利用し、RunnerV3 クラスをインスタンス化し、トレーニング構成を渡します。モデルのトレーニングは、トレーニング セットと検証セットを使用して合計 30 エポック実行されます。実験では、最も精度の高いモデルを最良のモデルとして保存します。コードは次のように実装されます。
import paddle.nn.functional as F
import paddle.optimizer as opt
from nndl import RunnerV3, Accuracy
#指定运行设备
use_gpu = True if paddle.get_device().startswith("gpu") else False
if use_gpu:
paddle.set_device('gpu:0')
#学习率大小
lr = 0.001
#批次大小
batch_size = 64
#加载数据
train_loader = io.DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
dev_loader = io.DataLoader(dev_dataset, batch_size=batch_size)
test_loader = io.DataLoader(test_dataset, batch_size=batch_size)
#定义网络
model = resnet18_model
#定义优化器,这里使用Adam优化器以及l2正则化策略,相关内容在7.3.3.2和7.6.2中会进行详细介绍
optimizer = opt.Adam(learning_rate=lr, parameters=model.parameters(), weight_decay=0.005)
#定义损失函数
loss_fn = F.cross_entropy
#定义评价指标
metric = Accuracy(is_logist=True)
#实例化RunnerV3
runner = RunnerV3(model, optimizer, loss_fn, metric)
#启动训练
log_steps = 3000
eval_steps = 3000
runner.train(train_loader, dev_loader, num_epochs=30, log_steps=log_steps,
eval_steps=eval_steps, save_path="best_model.pdparams")
トレーニング セットと検証セットの精度と損失の変化を視覚的に観察します。
from nndl import plot
plot(runner, fig_name='cnn-loss4.pdf')
この実験では、ネットワークの最適化に 7 章で紹介した Adam オプティマイザを使用していますが、SGD オプティマイザを使用すると、オーバーフィッティングという現象が発生し、検証セットの収束効果が得られません。第 7 章の他の最適化戦略を使用してトレーニング構成を調整して、モデルの精度を高めることができます。
V. モデル評価
テスト データを使用して、トレーニング プロセス中に保存された最適なモデルを評価し、テスト セットでのモデルの精度と損失を観察します。コードは次のように実装されます。
# 加载最优模型
runner.load_model('best_model.pdparams')
# 模型评价
score, loss = runner.evaluate(test_loader)
print("[Test] accuracy/loss: {:.4f}/{:.4f}".format(score, loss))
[テスト] 精度/損失: 0.7234/0.8324
6. モデル予測
同様に、保存されたモデルを使用して、テスト セット内のデータに対してモデル予測を行い、モデルの効果を観察することもできます。具体的なコードは次のように実装されます。
#获取测试集中的一个batch的数据
X, label = next(test_loader())
logits = runner.predict(X)
#多分类,使用softmax计算预测概率
pred = F.softmax(logits)
#获取概率最大的类别
pred_class = paddle.argmax(pred[2]).numpy()
label = label[2][0].numpy()
#输出真实类别与预测类别
print("The true category is {} and the predicted category is {}".format(label[0], pred_class[0]))
#可视化图片
plt.figure(figsize=(2, 2))
imgs, labels = load_cifar10_batch(folder_path='/home/aistudio/datasets/cifar-10-batches-py', mode='test')
plt.imshow(imgs[2].transpose(1,2,0))
plt.savefig('cnn-test-vis.pdf')
真のカテゴリは 8 で、予測されたカテゴリは 8 です
実数は 8、予想は 8 です。輸送する