ช่วยปกป้อง Great Barrier Reef กับ TensorFlow บน Kaggle เข้าร่วมท้าทาย

การจำแนกรูปภาพ Image

ดูบน TensorFlow.org ทำงานใน Google Colab ดูแหล่งที่มาบน GitHub ดาวน์โหลดโน๊ตบุ๊ค

บทช่วยสอนนี้แสดงวิธีจำแนกรูปภาพดอกไม้ มันสร้างตัวแยกประเภทรูปภาพโดยใช้โมเดล tf.keras.Sequential และโหลดข้อมูลโดยใช้ tf.keras.utils.image_dataset_from_directory คุณจะได้รับประสบการณ์เชิงปฏิบัติด้วยแนวคิดต่อไปนี้:

  • โหลดชุดข้อมูลออกจากดิสก์อย่างมีประสิทธิภาพ
  • ระบุการใช้เทคนิคมากเกินไปเพื่อบรรเทาปัญหา รวมถึงการเสริมข้อมูลและการออกกลางคัน

บทช่วยสอนนี้เป็นไปตามเวิร์กโฟลว์การเรียนรู้ของเครื่องขั้นพื้นฐาน:

  1. ตรวจสอบและทำความเข้าใจข้อมูล
  2. สร้างไปป์ไลน์อินพุต
  3. สร้างแบบจำลอง
  4. ฝึกโมเดล
  5. ทดสอบโมเดล
  6. ปรับปรุงแบบจำลองและทำซ้ำกระบวนการ

นำเข้า TensorFlow และไลบรารีอื่นๆ

import matplotlib.pyplot as plt
import numpy as np
import os
import PIL
import tensorflow as tf

from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.models import Sequential

ดาวน์โหลดและสำรวจชุดข้อมูล

บทช่วยสอนนี้ใช้ชุดข้อมูลภาพถ่ายดอกไม้ประมาณ 3,700 ภาพ ชุดข้อมูลประกอบด้วยไดเร็กทอรีย่อยห้าไดเร็กทอรี หนึ่งไดเร็กทอรีต่อคลาส:

flower_photo/
  daisy/
  dandelion/
  roses/
  sunflowers/
  tulips/
import pathlib
dataset_url = "https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz"
data_dir = tf.keras.utils.get_file('flower_photos', origin=dataset_url, untar=True)
data_dir = pathlib.Path(data_dir)
Downloading data from https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz
228818944/228813984 [==============================] - 9s 0us/step
228827136/228813984 [==============================] - 9s 0us/step

หลังจากดาวน์โหลด คุณควรมีสำเนาของชุดข้อมูลที่พร้อมใช้งาน มีทั้งหมด 3,670 ภาพ:

image_count = len(list(data_dir.glob('*/*.jpg')))
print(image_count)
3670

นี่คือดอกกุหลาบบางส่วน:

roses = list(data_dir.glob('roses/*'))
PIL.Image.open(str(roses[0]))

png

PIL.Image.open(str(roses[1]))

png

และดอกทิวลิปบางส่วน:

tulips = list(data_dir.glob('tulips/*'))
PIL.Image.open(str(tulips[0]))

png

PIL.Image.open(str(tulips[1]))

png

โหลดข้อมูลโดยใช้ยูทิลิตี้ Keras

มาโหลดอิมเมจเหล่านี้จากดิสก์โดยใช้ยูทิลิตี้ tf.keras.utils.image_dataset_from_directory ที่เป็นประโยชน์ ซึ่งจะนำคุณจากไดเร็กทอรีของรูปภาพบนดิสก์ไปยัง tf.data.Dataset ในโค้ดเพียงไม่กี่บรรทัด หากต้องการ คุณยังสามารถเขียนโค้ดการโหลดข้อมูลของคุณเองตั้งแต่ต้นโดยไปที่บทแนะนำการ โหลดและประมวลผลภาพล่วงหน้า

สร้างชุดข้อมูล

กำหนดพารามิเตอร์บางอย่างสำหรับตัวโหลด:

batch_size = 32
img_height = 180
img_width = 180

แนวทางปฏิบัติที่ดีในการใช้การแยกการตรวจสอบความถูกต้องเมื่อพัฒนาแบบจำลองของคุณ ลองใช้รูปภาพ 80% สำหรับการฝึกอบรมและ 20% สำหรับการตรวจสอบ

train_ds = tf.keras.utils.image_dataset_from_directory(
  data_dir,
  validation_split=0.2,
  subset="training",
  seed=123,
  image_size=(img_height, img_width),
  batch_size=batch_size)
Found 3670 files belonging to 5 classes.
Using 2936 files for training.
val_ds = tf.keras.utils.image_dataset_from_directory(
  data_dir,
  validation_split=0.2,
  subset="validation",
  seed=123,
  image_size=(img_height, img_width),
  batch_size=batch_size)
Found 3670 files belonging to 5 classes.
Using 734 files for validation.

คุณสามารถค้นหาชื่อคลาสได้ในแอตทริบิวต์ class_names บนชุดข้อมูลเหล่านี้ ซึ่งสอดคล้องกับชื่อไดเร็กทอรีตามลำดับตัวอักษร

class_names = train_ds.class_names
print(class_names)
['daisy', 'dandelion', 'roses', 'sunflowers', 'tulips']

เห็นภาพข้อมูล

นี่คือภาพเก้าภาพแรกจากชุดข้อมูลการฝึกอบรม:

import matplotlib.pyplot as plt

plt.figure(figsize=(10, 10))
for images, labels in train_ds.take(1):
  for i in range(9):
    ax = plt.subplot(3, 3, i + 1)
    plt.imshow(images[i].numpy().astype("uint8"))
    plt.title(class_names[labels[i]])
    plt.axis("off")

png

คุณจะฝึกโมเดลโดยใช้ชุดข้อมูลเหล่านี้โดยส่งต่อไปยัง Model.fit ในอีกสักครู่ หากต้องการ คุณยังสามารถวนซ้ำชุดข้อมูลด้วยตนเองและเรียกค้นชุดรูปภาพ:

for image_batch, labels_batch in train_ds:
  print(image_batch.shape)
  print(labels_batch.shape)
  break
(32, 180, 180, 3)
(32,)

image_batch คือเทนเซอร์ของรูปร่าง (32, 180, 180, 3) นี่คือชุดรูปภาพขนาด 180x180x3 จำนวน 32 รูป (ขนาดสุดท้ายหมายถึงช่องสี RGB) label_batch คือเทนเซอร์ของรูปร่าง (32,) ซึ่งเป็นป้ายกำกับที่สอดคล้องกับรูปภาพ 32 รูป

คุณสามารถเรียก .numpy() บน image_batch และ labels_batch เพื่อแปลงเป็น numpy.ndarray

กำหนดค่าชุดข้อมูลสำหรับประสิทธิภาพ

ตรวจสอบให้แน่ใจว่าได้ใช้การดึงข้อมูลล่วงหน้าแบบบัฟเฟอร์ เพื่อให้คุณสามารถส่งข้อมูลจากดิสก์โดยไม่ต้องให้ I/O ถูกบล็อก นี่เป็นวิธีสำคัญสองวิธีที่คุณควรใช้เมื่อโหลดข้อมูล:

  • Dataset.cache เก็บภาพไว้ในหน่วยความจำหลังจากที่โหลดออกจากดิสก์ในช่วงยุคแรก เพื่อให้แน่ใจว่าชุดข้อมูลจะไม่กลายเป็นคอขวดขณะฝึกโมเดลของคุณ หากชุดข้อมูลของคุณใหญ่เกินไปที่จะใส่ลงในหน่วยความจำ คุณสามารถใช้วิธีนี้เพื่อสร้างแคชบนดิสก์ที่มีประสิทธิภาพ
  • Dataset.prefetch ทับซ้อนการประมวลผลข้อมูลล่วงหน้าและการดำเนินการโมเดลขณะฝึก

ผู้อ่านที่สนใจสามารถเรียนรู้เพิ่มเติมเกี่ยวกับทั้งสองวิธี รวมถึงวิธีการแคชข้อมูลไปยังดิสก์ในส่วนการ ดึงข้อมูลล่วงหน้า ของประสิทธิภาพที่ ดีขึ้นด้วยคู่มือ tf.data API

AUTOTUNE = tf.data.AUTOTUNE

train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

สร้างมาตรฐานข้อมูล

ค่าช่อง RGB อยู่ในช่วง [0, 255] ไม่เหมาะสำหรับโครงข่ายประสาทเทียม โดยทั่วไป คุณควรพยายามทำให้ค่าอินพุตของคุณมีขนาดเล็ก

ที่นี่ คุณจะกำหนดค่ามาตรฐานให้อยู่ในช่วง [0, 1] โดยใช้ tf.keras.layers.Rescaling :

normalization_layer = layers.Rescaling(1./255)

มีสองวิธีในการใช้เลเยอร์นี้ คุณสามารถใช้กับชุดข้อมูลได้โดยเรียก Dataset.map :

normalized_ds = train_ds.map(lambda x, y: (normalization_layer(x), y))
image_batch, labels_batch = next(iter(normalized_ds))
first_image = image_batch[0]
# Notice the pixel values are now in `[0,1]`.
print(np.min(first_image), np.max(first_image))
0.0 1.0

หรือคุณสามารถรวมเลเยอร์ไว้ในการกำหนดโมเดลของคุณ ซึ่งจะทำให้การปรับใช้ง่ายขึ้น ลองใช้แนวทางที่สองที่นี่

สร้างแบบจำลอง

โมเดล Sequential ประกอบด้วยบล็อกการบิดสามบล็อก ( tf.keras.layers.Conv2D ) ที่มีเลเยอร์การรวมสูงสุด ( tf.keras.layers.MaxPooling2D ) ในแต่ละอัน มีเลเยอร์ที่เชื่อมต่ออย่างสมบูรณ์ ( tf.keras.layers.Dense ) โดยมี 128 ยูนิตอยู่ด้านบนซึ่งเปิดใช้งานโดยฟังก์ชันการเปิดใช้งาน ReLU ( 'relu' ) โมเดลนี้ไม่ได้รับการปรับแต่งให้มีความแม่นยำสูง เป้าหมายของบทช่วยสอนนี้คือการแสดงแนวทางมาตรฐาน

num_classes = len(class_names)

model = Sequential([
  layers.Rescaling(1./255, input_shape=(img_height, img_width, 3)),
  layers.Conv2D(16, 3, padding='same', activation='relu'),
  layers.MaxPooling2D(),
  layers.Conv2D(32, 3, padding='same', activation='relu'),
  layers.MaxPooling2D(),
  layers.Conv2D(64, 3, padding='same', activation='relu'),
  layers.MaxPooling2D(),
  layers.Flatten(),
  layers.Dense(128, activation='relu'),
  layers.Dense(num_classes)
])

รวบรวมโมเดล

สำหรับบทช่วยสอนนี้ ให้เลือกฟังก์ชันเพิ่มประสิทธิภาพ tf.keras.optimizers.Adam และ tf.keras.losses.SparseCategoricalCrossentropy loss ในการดูการฝึกอบรมและการตรวจสอบความถูกต้องสำหรับช่วงการฝึกแต่ละครั้ง ให้ส่งอาร์กิวเมนต์ metrics ไปที่ Model.compile

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

สรุปโมเดล

ดูเลเยอร์ทั้งหมดของเครือข่ายโดยใช้เมธอด Model.summary ของโมเดล:

model.summary()
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 rescaling_1 (Rescaling)     (None, 180, 180, 3)       0         
                                                                 
 conv2d (Conv2D)             (None, 180, 180, 16)      448       
                                                                 
 max_pooling2d (MaxPooling2D  (None, 90, 90, 16)       0         
 )                                                               
                                                                 
 conv2d_1 (Conv2D)           (None, 90, 90, 32)        4640      
                                                                 
 max_pooling2d_1 (MaxPooling  (None, 45, 45, 32)       0         
 2D)                                                             
                                                                 
 conv2d_2 (Conv2D)           (None, 45, 45, 64)        18496     
                                                                 
 max_pooling2d_2 (MaxPooling  (None, 22, 22, 64)       0         
 2D)                                                             
                                                                 
 flatten (Flatten)           (None, 30976)             0         
                                                                 
 dense (Dense)               (None, 128)               3965056   
                                                                 
 dense_1 (Dense)             (None, 5)                 645       
                                                                 
=================================================================
Total params: 3,989,285
Trainable params: 3,989,285
Non-trainable params: 0
_________________________________________________________________

ฝึกโมเดล

epochs=10
history = model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=epochs
)
Epoch 1/10
92/92 [==============================] - 11s 17ms/step - loss: 1.3016 - accuracy: 0.4441 - val_loss: 1.1355 - val_accuracy: 0.5300
Epoch 2/10
92/92 [==============================] - 1s 10ms/step - loss: 0.9780 - accuracy: 0.6236 - val_loss: 1.0084 - val_accuracy: 0.5926
Epoch 3/10
92/92 [==============================] - 1s 10ms/step - loss: 0.7665 - accuracy: 0.7095 - val_loss: 0.9090 - val_accuracy: 0.6512
Epoch 4/10
92/92 [==============================] - 1s 10ms/step - loss: 0.5658 - accuracy: 0.7967 - val_loss: 0.9801 - val_accuracy: 0.6417
Epoch 5/10
92/92 [==============================] - 1s 10ms/step - loss: 0.3663 - accuracy: 0.8743 - val_loss: 1.0953 - val_accuracy: 0.6117
Epoch 6/10
92/92 [==============================] - 1s 10ms/step - loss: 0.2198 - accuracy: 0.9292 - val_loss: 1.1880 - val_accuracy: 0.6471
Epoch 7/10
92/92 [==============================] - 1s 10ms/step - loss: 0.1073 - accuracy: 0.9687 - val_loss: 1.4790 - val_accuracy: 0.6431
Epoch 8/10
92/92 [==============================] - 1s 10ms/step - loss: 0.0795 - accuracy: 0.9768 - val_loss: 1.5939 - val_accuracy: 0.6649
Epoch 9/10
92/92 [==============================] - 1s 10ms/step - loss: 0.0531 - accuracy: 0.9840 - val_loss: 1.7783 - val_accuracy: 0.6213
Epoch 10/10
92/92 [==============================] - 1s 10ms/step - loss: 0.0572 - accuracy: 0.9874 - val_loss: 1.8963 - val_accuracy: 0.6676

เห็นภาพผลการฝึก

สร้างแผนการสูญเสียและความแม่นยำในชุดการฝึกอบรมและการตรวจสอบ:

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=(8, 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(loc='lower right')
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(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()

png

แผนภาพแสดงให้เห็นว่าความแม่นยำในการฝึกและความแม่นยำในการตรวจสอบนั้นลดลงอย่างมาก และโมเดลได้รับความแม่นยำเพียง 60% ในชุดการตรวจสอบ

ตรวจสอบสิ่งที่ผิดพลาดและพยายามเพิ่มประสิทธิภาพโดยรวมของโมเดล

ฟิตเกินไป

ในแผนภาพด้านบน ความแม่นยำในการฝึกอบรมเพิ่มขึ้นเป็นเส้นตรงเมื่อเวลาผ่านไป ในขณะที่ความแม่นยำในการตรวจสอบความถูกต้องหยุดอยู่ที่ประมาณ 60% ในกระบวนการฝึกอบรม นอกจากนี้ จะเห็นความแตกต่างในความแม่นยำระหว่างความแม่นยำในการฝึกและการตรวจสอบ ซึ่งเป็นสัญญาณของ การใส่ มากเกินไป

เมื่อมีตัวอย่างการฝึกอบรมจำนวนเล็กน้อย ในบางครั้ง โมเดลจะเรียนรู้จากเสียงรบกวนหรือรายละเอียดที่ไม่ต้องการจากตัวอย่างการฝึก จนถึงขนาดที่ส่งผลเสียต่อประสิทธิภาพของโมเดลต่อตัวอย่างใหม่ ปรากฏการณ์นี้เรียกว่ามากเกินไป หมายความว่าโมเดลจะมีช่วงเวลาที่ยากลำบากในการสรุปชุดข้อมูลใหม่

มีหลายวิธีในการต่อสู้กับการใส่มากเกินไปในกระบวนการฝึกอบรม ในบทช่วยสอนนี้ คุณจะใช้ การเพิ่มข้อมูล และเพิ่ม Dropout ให้กับโมเดลของคุณ

การเสริมข้อมูล

Overfitting มักเกิดขึ้นเมื่อมีตัวอย่างการฝึกอบรมจำนวนน้อย การเสริมข้อมูล ใช้แนวทางในการสร้างข้อมูลการฝึกอบรมเพิ่มเติมจากตัวอย่างที่มีอยู่ของคุณโดยการเพิ่มโดยใช้การแปลงแบบสุ่มที่ให้ภาพที่ดูน่าเชื่อ ซึ่งช่วยให้โมเดลเปิดเผยข้อมูลในแง่มุมต่างๆ มากขึ้นและสรุปได้ดีขึ้น

คุณจะใช้การเพิ่มข้อมูลโดยใช้เลเยอร์การประมวลผลล่วงหน้าของ Keras ต่อไปนี้: tf.keras.layers.RandomFlip , tf.keras.layers.RandomRotation และ tf.keras.layers.RandomZoom สิ่งเหล่านี้สามารถรวมอยู่ในโมเดลของคุณเหมือนกับเลเยอร์อื่นๆ และรันบน GPU

data_augmentation = keras.Sequential(
  [
    layers.RandomFlip("horizontal",
                      input_shape=(img_height,
                                  img_width,
                                  3)),
    layers.RandomRotation(0.1),
    layers.RandomZoom(0.1),
  ]
)

มาลองนึกภาพว่าตัวอย่างบางส่วนเป็นอย่างไรโดยใช้การเสริมข้อมูลกับรูปภาพเดียวกันหลายๆ ครั้ง:

plt.figure(figsize=(10, 10))
for images, _ in train_ds.take(1):
  for i in range(9):
    augmented_images = data_augmentation(images)
    ax = plt.subplot(3, 3, i + 1)
    plt.imshow(augmented_images[0].numpy().astype("uint8"))
    plt.axis("off")

png

คุณจะใช้การเสริมข้อมูลเพื่อฝึกโมเดลในอีกสักครู่

ถอนออก

อีกเทคนิคหนึ่งในการลดการ overfitting คือการแนะนำการทำให้เครือข่ายเป็นแบบมาตรฐาน

เมื่อคุณปรับใช้ dropout กับเลเยอร์ มันจะสุ่มเอาออก (โดยการตั้งค่าการเปิดใช้งานเป็นศูนย์) จำนวนหน่วยเอาท์พุตจากเลเยอร์ในระหว่างกระบวนการฝึกอบรม Dropout จะใช้ตัวเลขที่เป็นเศษส่วนเป็นค่าอินพุต ในรูปแบบเช่น 0.1, 0.2, 0.4 เป็นต้น ซึ่งหมายถึงการปล่อยหน่วยเอาต์พุต 10%, 20% หรือ 40% แบบสุ่มจากเลเยอร์ที่ใช้

มาสร้างโครงข่ายประสาทเทียมใหม่ด้วย tf.keras.layers.Dropout ก่อนฝึกโดยใช้รูปภาพเสริม:

model = Sequential([
  data_augmentation,
  layers.Rescaling(1./255),
  layers.Conv2D(16, 3, padding='same', activation='relu'),
  layers.MaxPooling2D(),
  layers.Conv2D(32, 3, padding='same', activation='relu'),
  layers.MaxPooling2D(),
  layers.Conv2D(64, 3, padding='same', activation='relu'),
  layers.MaxPooling2D(),
  layers.Dropout(0.2),
  layers.Flatten(),
  layers.Dense(128, activation='relu'),
  layers.Dense(num_classes)
])

รวบรวมและฝึกโมเดล

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])
model.summary()
Model: "sequential_2"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 sequential_1 (Sequential)   (None, 180, 180, 3)       0         
                                                                 
 rescaling_2 (Rescaling)     (None, 180, 180, 3)       0         
                                                                 
 conv2d_3 (Conv2D)           (None, 180, 180, 16)      448       
                                                                 
 max_pooling2d_3 (MaxPooling  (None, 90, 90, 16)       0         
 2D)                                                             
                                                                 
 conv2d_4 (Conv2D)           (None, 90, 90, 32)        4640      
                                                                 
 max_pooling2d_4 (MaxPooling  (None, 45, 45, 32)       0         
 2D)                                                             
                                                                 
 conv2d_5 (Conv2D)           (None, 45, 45, 64)        18496     
                                                                 
 max_pooling2d_5 (MaxPooling  (None, 22, 22, 64)       0         
 2D)                                                             
                                                                 
 dropout (Dropout)           (None, 22, 22, 64)        0         
                                                                 
 flatten_1 (Flatten)         (None, 30976)             0         
                                                                 
 dense_2 (Dense)             (None, 128)               3965056   
                                                                 
 dense_3 (Dense)             (None, 5)                 645       
                                                                 
=================================================================
Total params: 3,989,285
Trainable params: 3,989,285
Non-trainable params: 0
_________________________________________________________________
epochs = 15
history = model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=epochs
)
Epoch 1/15
92/92 [==============================] - 2s 15ms/step - loss: 1.3056 - accuracy: 0.4472 - val_loss: 1.1157 - val_accuracy: 0.5681
Epoch 2/15
92/92 [==============================] - 1s 12ms/step - loss: 1.0715 - accuracy: 0.5756 - val_loss: 0.9983 - val_accuracy: 0.6172
Epoch 3/15
92/92 [==============================] - 1s 12ms/step - loss: 0.9467 - accuracy: 0.6274 - val_loss: 0.9802 - val_accuracy: 0.6240
Epoch 4/15
92/92 [==============================] - 1s 12ms/step - loss: 0.8713 - accuracy: 0.6594 - val_loss: 0.8975 - val_accuracy: 0.6553
Epoch 5/15
92/92 [==============================] - 1s 12ms/step - loss: 0.8125 - accuracy: 0.6921 - val_loss: 0.8993 - val_accuracy: 0.6703
Epoch 6/15
92/92 [==============================] - 1s 12ms/step - loss: 0.7631 - accuracy: 0.7081 - val_loss: 0.8429 - val_accuracy: 0.6635
Epoch 7/15
92/92 [==============================] - 1s 12ms/step - loss: 0.7134 - accuracy: 0.7265 - val_loss: 0.8360 - val_accuracy: 0.6730
Epoch 8/15
92/92 [==============================] - 1s 12ms/step - loss: 0.7023 - accuracy: 0.7313 - val_loss: 0.7761 - val_accuracy: 0.6744
Epoch 9/15
92/92 [==============================] - 1s 12ms/step - loss: 0.6569 - accuracy: 0.7486 - val_loss: 0.7240 - val_accuracy: 0.7084
Epoch 10/15
92/92 [==============================] - 1s 12ms/step - loss: 0.6501 - accuracy: 0.7514 - val_loss: 0.7274 - val_accuracy: 0.7098
Epoch 11/15
92/92 [==============================] - 1s 12ms/step - loss: 0.6319 - accuracy: 0.7589 - val_loss: 0.7318 - val_accuracy: 0.7112
Epoch 12/15
92/92 [==============================] - 1s 12ms/step - loss: 0.6026 - accuracy: 0.7721 - val_loss: 0.7513 - val_accuracy: 0.7112
Epoch 13/15
92/92 [==============================] - 1s 12ms/step - loss: 0.5659 - accuracy: 0.7847 - val_loss: 0.7133 - val_accuracy: 0.7207
Epoch 14/15
92/92 [==============================] - 1s 12ms/step - loss: 0.5554 - accuracy: 0.7912 - val_loss: 0.7359 - val_accuracy: 0.7275
Epoch 15/15
92/92 [==============================] - 1s 12ms/step - loss: 0.5275 - accuracy: 0.8021 - val_loss: 0.7532 - val_accuracy: 0.6894

เห็นภาพผลการฝึก

หลังจากใช้ data augmentation และ tf.keras.layers.Dropout แล้ว มี overfitting น้อยกว่าเมื่อก่อน และการฝึกอบรมและการตรวจสอบความถูกต้องมีความสอดคล้องกันมากขึ้น:

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=(8, 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(loc='lower right')
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(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()

png

คาดการณ์ข้อมูลใหม่

สุดท้าย ลองใช้แบบจำลองของเราเพื่อจำแนกรูปภาพที่ไม่รวมอยู่ในชุดการฝึกหรือการตรวจสอบ

sunflower_url = "https://storage.googleapis.com/download.tensorflow.org/example_images/592px-Red_sunflower.jpg"
sunflower_path = tf.keras.utils.get_file('Red_sunflower', origin=sunflower_url)

img = tf.keras.utils.load_img(
    sunflower_path, target_size=(img_height, img_width)
)
img_array = tf.keras.utils.img_to_array(img)
img_array = tf.expand_dims(img_array, 0) # Create a batch

predictions = model.predict(img_array)
score = tf.nn.softmax(predictions[0])

print(
    "This image most likely belongs to {} with a {:.2f} percent confidence."
    .format(class_names[np.argmax(score)], 100 * np.max(score))
)
Downloading data from https://storage.googleapis.com/download.tensorflow.org/example_images/592px-Red_sunflower.jpg
122880/117948 [===============================] - 0s 0us/step
131072/117948 [=================================] - 0s 0us/step
This image most likely belongs to sunflowers with a 74.12 percent confidence.
ตัวยึดตำแหน่ง42