これは猫ですか、犬ですか.(1)


🔻羽状バニラ:https://github.com/kkamyang/Aiffel_exp/blob/main/cat_dog_1.ipynb

📍 データの準備


分割▼▼データ

import tensorflow as tf
import tensorflow_datasets as tfds

(raw_train, raw_validation, raw_test), metadata = tfds.load(
    'cats_vs_dogs',
    split=['train[:80%]', 'train[80%:90%]', 'train[90%:]'],
    with_info=True,
    as_supervised=True,
)
split=[「train[:80%]」「train[80%:90%]」、「train[90%:]」は、trainデータセット全体に設定されたデータセットを80%、10%、および10%の3つの部分に分け、それぞれtrain data、validation data、test dataとして使用します.
print(raw_train)
print(raw_validation)
print(raw_test)

Datasetの形状は(image,label)の形で表される.最初の再パラメータ画像は(height,width,channel)、上のデータは(None,None,3)と表される.HeightとwidthがNoneと表示されるのは、画像の大きさが異なり、サイズが確定していないためです.チャンネルは、画像の色を表すチャネル数を表します.白黒画像は2、カラー画像はRGBと表示されるので3と表示される.前回のプロジェクトでは、pngファイルのchannelを4に設定したようですが、pngがCMYKとして表示されているためかもしれません.(いいえ、確認してください)2番目のパラメータlabelは、特定の画像が何を表しているかを示す単一の値です.1次元の数字で表されるため、次元は単独では表示されません.

画像サイズの統一

import matplotlib.pyplot as plt
%matplotlib inline
%config InlineBackend.figure_format = 'retina'

plt.figure(figsize=(10, 5))

get_label_name = metadata.features['label'].int2str

for idx, (image, label) in enumerate(raw_train.take(10)):  # 10개의 데이터 가져오기
    plt.subplot(2, 5, idx+1)
    plt.imshow(image)
    plt.title(f'label {label}: {get_label_name(label)}')
    plt.axis('off')

ラベルを調べてみると、猫は0、子犬は1と設定されていました.イメージから見ると、大きさが異なり、イメージを統一する作業が必要です.画像のサイズは160*160ピクセルに統一します.
IMG_SIZE = 160 # resize시킬 이미지의 크기

def format_example(image, label):
    image = tf.cast(image, tf.float32) 
    image = (image/127.5) - 1 # 픽셀값의 scale 수정
    image = tf.image.resize(image, (IMG_SIZE, IMG_SIZE))
    return image, label
image = tf.cast(image,tf.float 32)は、image=float(image)などのタイプのcastingのtenseflowバージョンである.タイプ選択は、タイプ(タイプ)を他のデータ型に変換することを意味します.float()を用いて整数型を実数型に変換することはタイプ鋳造の一例である.画像の元のピクセル値は、RGBで主に使用される0~255の整数値です.これらの値を中間値127.5に分割し、1を除いて-1から1の間の実数値、すなわちimage=(image/127.5)-1にする.
train = raw_train.map(format_example)
validation = raw_validation.map(format_example)
test = raw_test.map(format_example)

print(train)
print(validation)
print(test)

map()関数を使用して、raw train、raw validation、raw testにformat example()関数を適用します.これにより、同じ形状のtrain、validaion、testデータセットが得られる.前に出力した10枚の画像をもう一度チェックして、画像が本当に大きくなったかどうかを見てみましょう.
plt.figure(figsize=(10, 5))


get_label_name = metadata.features['label'].int2str

for idx, (image, label) in enumerate(train.take(10)):
    plt.subplot(2, 5, idx+1)
    image = (image + 1) / 2
    plt.imshow(image)
    plt.title(f'label {label}: {get_label_name(label)}')
    plt.axis('off')

📍 モデリング


ラミネート

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Conv2D, Flatten, MaxPooling2D
モデルには、モデル自体を構築する関数が含まれています.さらに、レイヤにはモデルのコンポーネントである多くのタイプのレイヤ関数があります.前述したように,シーケンスは連続モデルを構築する関数である.シーケンス関数では、複数のレイヤに連続的に入ります.
model = Sequential([
    Conv2D(filters=16, kernel_size=3, padding='same', activation='relu', input_shape=(160, 160, 3)),
    MaxPooling2D(),
    Conv2D(filters=32, kernel_size=3, padding='same', activation='relu'),
    MaxPooling2D(),
    Conv2D(filters=64, kernel_size=3, padding='same', activation='relu'),
    MaxPooling2D(),
    Flatten(),
    Dense(units=512, activation='relu'),
    Dense(units=2, activation='softmax')
])

model.summary()

Conv 2 D、MaxPooling 2 D、Flatten、Deseの4種類のレイヤが使用されています.モデルの全体的な構造をsummary()メソッドで表示すると、階層が表示されます.深さ走はいつもこのような構造を呈している.最初の画像は(160160,3)の大きさであり,層を通過するにつれて形状が変化している.画像は第1層conv 2 dから第6層max pooling 2 d 2にかけて、高さと幅は160→80→40→20から徐々に小さくなり、チャネルは16→32→64から徐々に大きくなる.最初の6層を通過したshapeは(None,height,width,channel)で4次元であった.
Noneは、バッチサイズによっては、異なる数の入力がモデルに入る可能性があることを示しています.1つのデータのサイズは(height,width,channel)3次元であり,6層を通過するとheightとwidthは次第に小さくなり,channelは次第に大きくなり,平坦層に遭遇すると形状は25600(20 x 20 x 64)のデジタル1次元に縮小した.ますます小さなfeature map出力とともに,FlattenとDense層を通過した一次元形状縮小ネットワークはCNNの深さ学習モデルを用いた最も代表的な形式である.
learning_rate = 0.0001
model.compile(optimizer=tf.keras.optimizers.RMSprop(lr=learning_rate),
              loss=tf.keras.losses.sparse_categorical_crossentropy,
              metrics=['accuracy'])
オプティマイザは、どのように学習するかを決定します.最適化の仕方を決めるので、最適化関数とも呼ばれます.
lossはモデルの学習の方向を決定した.この問題では、モデルの出力は、入力画像が猫であるか犬であるかの確率分布と見なされるため、入力画像が猫(label=0)であれば、モデルの出力は[1.0,0.0]、子犬(label=1)であれば[0.0,1.0]に近い方向となる.
metricsはモデルの性能を測定する尺度である.分類問題を解く際,性能を評価できる指標は精度(精度),精度(精密度),再現率(リコール)などである.ここでは精度を使用しています.

#Batchの作成

BATCH_SIZE = 32
SHUFFLE_BUFFER_SIZE = 1000

train_batches = train.shuffle(SHUFFLE_BUFFER_SIZE).batch(BATCH_SIZE)
validation_batches = validation.batch(BATCH_SIZE)
test_batches = test.batch(BATCH_SIZE)
ステップ学習するデータの個数をBATCH SIZEで表し、SHUFFLE BUFFER SIZEを設定し、学習データを混在させることができます.BATCH SIZEに基づき32個のデータをランダムに配布するtrain batch,validation batch,test batchを作成した.train batchはすべてのデータから32個をランダムに抽出し、絶えず学習するためにモデルを提供し続けた.
for image_batch, label_batch in train_batches.take(1):
    pass

image_batch.shape, label_batch.shape

テストでbatchを引いた.イメージバッチのshapeは、(160、160、3)shapeが存在する32個のデータを表す.また,labelが子犬であれば1,猫であれば0で正解labelを表すので,1ロットに32個のデータがある場合,labelは0または1の32個の数字のみからなる.
以下は正式に模型を作る前に作った初期模型です.検証(validation)のデータセットvalidation batchsを用いて20回の予測を行い,平均損失と平均精度を確認した.
validation_steps = 20
loss0, accuracy0 = model.evaluate(validation_batches, steps=validation_steps)

print("initial loss: {:.2f}".format(loss0))
print("initial accuracy: {:.2f}".format(accuracy0))

初期損失は0.70,初期精度は0.52であった.lossはモデルがどれだけ間違っているかを示し,もちろん低ければ低いほどよい.精度は精度を表し,我々が構築したモデルは子犬と猫の2つのモデルのうちの1つを分類したモデルであり,撮っても50%の精度があるため,52%の精度はこのモデルが意味のない予測をしたと判断できる.まだモデルに勉強させていないからです.では、今回は10 epochを学び、精度の変化を確認します.
EPOCHS = 10
history = model.fit(train_batches,
                    epochs=EPOCHS,
                    validation_data=validation_batches)

精度は学習中のデータの精度を表し、val decificationは未学習の検証データの精度を表す.もちろん、トレーニングデータの精度は高い.上記の精度は約97.56%,val精度は78.46であった.学習段階の精度から見ると、以下のようになる.
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']

loss=history.history['loss']
val_loss=history.history['val_loss']

epochs_range = range(EPOCHS)

plt.figure(figsize=(12, 8))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend()
plt.title('Training and Validation Accuracy')

plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend()
plt.title('Training and Validation Loss')
plt.show()

訓練精度は現在学習されているデータセットの精度であるため,モデルの構造やデータセットなどに問題がなければ,一般に学べば学ぶほど堅持される.逆に,検証精度は未学習データセットに対する精度であるため,一定レベルに達した後も上昇し続けるかどうかは保証できない.さらに,損失マップでは訓練損失は安定的に減少してきたが,検証損失値は特定の瞬間以降に再び増大した.モデルの性能を向上させるには,未学習のデータに対しても良好な性能が必要であるが,訓練データのみで学習を継続した結果,それらのデータのみをオーバーフィット(オーバーフィット)し,一般化能力を低下させた.

▼▼▼testデータで予測


最後に,このモデルを用いてテストデータを適用してモデルの予測結果を検証しようとした.
for image_batch, label_batch in test_batches.take(1):
    images = image_batch
    labels = label_batch
    predictions = model.predict(image_batch)
    pass

predictions

model.predicateを用いてモデルの予測結果を確認すると,小数点からなることが確認され,[1.0,0.0]に近づくほどlabelは0の猫ほど,[0.0,1.0]に近づくほどlabelは1の子犬であることが確認された.以下に示すように、表示しやすいラベルと画像に変換します.
import numpy as np

predictions = np.argmax(predictions, axis=1)
predictions
plt.figure(figsize=(20, 12))

for idx, (image, label, prediction) in enumerate(zip(images, labels, predictions)):
    plt.subplot(4, 8, idx+1)
    image = (image + 1) / 2
    plt.imshow(image)
    correct = label == prediction
    title = f'real: {label} / pred :{prediction}\n {correct}!'
    if not correct:
        plt.title(title, fontdict={'color': 'red'})
    else:
        plt.title(title, fontdict={'color': 'blue'})
    plt.axis('off')
count = 0   # 정답을 맞춘 개수
for image, label, prediction in zip(images, labels, predictions):
    correct = label == prediction
    if correct:
        count = count + 1

print(count / 32 * 100)

32枚の画像に対する予測精度は75%であった.これはちょっと残念な精度です.次に,精度を向上させるモデルを用いてみる.