Bu sayfa, Cloud Translation API ile çevrilmiştir.
Switch to English

Görüntü sınıflandırması

TensorFlow.org üzerinde görüntüle Google Colab'da yayınla Kaynağı GitHub'da görüntüle Not defterini indir

Bu eğitimde çiçek görüntülerinin nasıl sınıflandırılacağı gösterilmektedir. Bir keras.Sequential modeli kullanarak bir resim sınıflandırıcı oluşturur ve preprocessing.image_dataset_from_directory kullanarak veri yükler. Aşağıdaki kavramlarla pratik deneyim kazanacaksınız:

  • Veri kümesini diskten verimli bir şekilde yükleme.
  • Veri çoğaltma ve Bırakma dahil olmak üzere aşırı uydurmanın belirlenmesi ve azaltılması için tekniklerin uygulanması.

Bu eğiticide temel bir makine öğrenimi iş akışı izlenmektedir:

  1. Verileri inceleme ve anlama
  2. Bir giriş hattı oluşturun
  3. Modeli oluşturun
  4. Modeli eğitin
  5. Modeli test edin
  6. Modeli geliştirin ve işlemi tekrarlayın
pip install -q tf-nightly

TensorFlow ve diğer kütüphaneleri içe aktarma

 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
 

Veri kümesini indirin ve keşfedin

Bu eğitimde yaklaşık 3.700 çiçek fotoğrafı içeren bir veri kümesi kullanılmıştır. Veri kümesi, sınıf başına bir tane olmak üzere 5 alt dizin içerir:

 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 [==============================] - 4s 0us/step

İndirdikten sonra, artık veri kümesinin bir kopyasına sahip olmalısınız. Toplam 3.670 görüntü var:

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

İşte bazı güller:

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

png

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

png

Ve bazı laleler:

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

png

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

png

Keras.preprocessing kullanarak yükleme

Yararlı image_dataset_from_directory yardımcı programını kullanarak bu görüntüleri diskten yükleyelim . Bu, sizi diskteki bir görüntü dizininden sadece birkaç satır kodda bir tf.data.Dataset . İsterseniz, yükleme resimleri eğiticisini ziyaret ederek kendi veri yükleme kodunuzu sıfırdan da yazabilirsiniz.

Veri kümesi oluşturma

Yükleyici için bazı parametreler tanımlayın:

 batch_size = 32
img_height = 180
img_width = 180
 

Modelinizi geliştirirken bir doğrulama bölümü kullanmak iyi bir uygulamadır. Görüntülerin% 80'ini eğitim için ve% 20'sini doğrulama için kullanacağız.

 train_ds = tf.keras.preprocessing.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.preprocessing.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.

Sınıf adlarını, bu veri kümelerindeki class_names özniteliğinde bulabilirsiniz. Bunlar, dizin adlarına alfabetik sırayla karşılık gelir.

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

Verileri görselleştirin

İşte eğitim veri kümesinden ilk 9 resim.

 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

Bir modeli bu veri kümelerini kullanarak modele model.fit . İsterseniz, veri kümesini manuel olarak yineleyebilir ve görüntü gruplarını alabilirsiniz:

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

image_batch şeklin bir image_batch (32, 180, 180, 3) . Bu, 180x180x3 şeklindeki 32 görüntünün bulunduğu bir 180x180x3 (son boyut RGB renk kanallarını ifade eder). label_batch , şeklin (32,) bir label_batch , bunlar 32 görüntüye karşılık gelen etiketlerdir.

Bir .numpy() dönüştürmek için image_batch ve labels_batch tansörlerinde .numpy() image_batch numpy.ndarray .

Veri kümesini performans için yapılandırma

G / Ç engelleme olmadan diskten veri sağlayabilmemiz için tamponlu ön getirmeyi kullandığınızdan emin olalım. Bunlar veri yüklerken kullanmanız gereken iki önemli yöntemdir.

Dataset.cache() , ilk çağda diskten yüklendikten sonra görüntüleri bellekte tutar. Bu, modelinizi eğitirken veri kümesinin bir darboğaz haline gelmemesini sağlayacaktır. Veri kümeniz belleğe sığmayacak kadar büyükse, performans gösteren bir disk önbelleği oluşturmak için de bu yöntemi kullanabilirsiniz.

Dataset.prefetch() , eğitim sırasında veri önişleme ve model yürütme ile çakışır.

İlgilenen okuyucular, her iki yöntem hakkında ve veri performans kılavuzunda verileri diske nasıl önbelleğe alabileceğiniz hakkında daha fazla bilgi edinebilir.

 AUTOTUNE = tf.data.experimental.AUTOTUNE

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

Verileri standartlaştırın

RGB kanalı değerleri [0, 255] aralığındadır. Bu, sinir ağı için ideal değildir; genel olarak girdi değerlerinizi küçük yapmaya çalışmalısınız. Burada, bir Yeniden Ölçeklendirme katmanı kullanarak [0, 1] içindeki değerleri standart hale getireceğiz.

 normalization_layer = layers.experimental.preprocessing.Rescaling(1./255)
 

Bu katmanı kullanmanın iki yolu vardır. Haritayı arayarak veri kümesine uygulayabilirsiniz:

 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 pixels values are now in `[0,1]`.
print(np.min(first_image), np.max(first_image)) 
 
0.0 1.0

Veya, dağıtımı basitleştirebilecek katmanı model tanımınızın içine dahil edebilirsiniz. Burada ikinci yaklaşımı kullanacağız.

Modeli oluşturun

Model, her birinde maksimum havuz tabakası olan üç evrişim bloğundan oluşur. Üzerinde relu aktivasyon fonksiyonu ile aktif hale getirilmiş 128 ünite bulunan tamamen bağlı bir katman var. Bu model yüksek doğruluk için ayarlanmamıştır, bu öğreticinin amacı standart bir yaklaşım göstermektir.

 num_classes = 5

model = Sequential([
  layers.experimental.preprocessing.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)
])
 

Modeli derleyin

Bu öğretici için optimizers.Adam losses.SparseCategoricalCrossentropy optimize edici ve kayıplar. Her egzersiz dönemi için egzersiz ve doğrulama doğruluğunu görüntülemek için metrics bağımsız değişkenini iletin.

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

Model özeti

Modelin summary yöntemini kullanarak ağın tüm katmanlarını görüntüleyin:

 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 (MaxPooling2 (None, 45, 45, 32)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 45, 45, 64)        18496     
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 22, 22, 64)        0         
_________________________________________________________________
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
_________________________________________________________________

Modeli eğitin

 epochs=10
history = model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=epochs
)
 
Epoch 1/10
92/92 [==============================] - 4s 47ms/step - loss: 1.9328 - accuracy: 0.2896 - val_loss: 1.1022 - val_accuracy: 0.5245
Epoch 2/10
92/92 [==============================] - 1s 10ms/step - loss: 1.0441 - accuracy: 0.5761 - val_loss: 1.0057 - val_accuracy: 0.5913
Epoch 3/10
92/92 [==============================] - 1s 10ms/step - loss: 0.8640 - accuracy: 0.6763 - val_loss: 0.8951 - val_accuracy: 0.6499
Epoch 4/10
92/92 [==============================] - 1s 10ms/step - loss: 0.7106 - accuracy: 0.7472 - val_loss: 0.8992 - val_accuracy: 0.6621
Epoch 5/10
92/92 [==============================] - 1s 10ms/step - loss: 0.4817 - accuracy: 0.8285 - val_loss: 0.8997 - val_accuracy: 0.6662
Epoch 6/10
92/92 [==============================] - 1s 10ms/step - loss: 0.3131 - accuracy: 0.8903 - val_loss: 1.0014 - val_accuracy: 0.6567
Epoch 7/10
92/92 [==============================] - 1s 10ms/step - loss: 0.1782 - accuracy: 0.9436 - val_loss: 1.2140 - val_accuracy: 0.6431
Epoch 8/10
92/92 [==============================] - 1s 10ms/step - loss: 0.1024 - accuracy: 0.9703 - val_loss: 1.5144 - val_accuracy: 0.6240
Epoch 9/10
92/92 [==============================] - 1s 10ms/step - loss: 0.0736 - accuracy: 0.9815 - val_loss: 1.7651 - val_accuracy: 0.5926
Epoch 10/10
92/92 [==============================] - 1s 10ms/step - loss: 0.0761 - accuracy: 0.9775 - val_loss: 2.0429 - val_accuracy: 0.5967

Eğitim sonuçlarını görselleştirin

Eğitim ve validasyon setlerinde kayıp ve doğruluk grafikleri oluşturun.

 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

Grafiklerden görebileceğiniz gibi, antrenman doğruluğu ve validasyon doğruluğu büyük bir farkla kapalıdır ve model validasyon setinde sadece yaklaşık% 60 doğruluk elde etmiştir.

Neyin yanlış gittiğine bakalım ve modelin genel performansını artırmaya çalışalım.

Aşırı uyum gösterme

Yukarıdaki grafiklerde, eğitim doğruluğu zaman içinde doğrusal olarak artarken, doğrulama doğruluğu eğitim sürecinde% 60 civarında durmaktadır. Ayrıca, eğitim ve onaylama doğruluğu arasındaki doğruluk farkı fark edilir - aşırı uyumun bir işareti.

Az sayıda eğitim örneği olduğunda, model bazen eğitim örneklerinden gelen gürültülerden veya istenmeyen detaylardan öğrenir - bu, modelin performansını yeni örnekler üzerindeki olumsuz yönde etkiler. Bu fenomen aşırı uydurma olarak bilinir. Bu, modelin yeni bir veri kümesi üzerinde genelleme yapmakta zorlanacağı anlamına gelir.

Eğitim sürecinde aşırı sığdırma ile mücadele etmenin birçok yolu vardır. Bu öğreticide, veri artırımı kullanacak ve modelinize Bırakma ekleyeceksiniz.

Veri büyütme

Aşırı takma genellikle az sayıda eğitim örneği olduğunda ortaya çıkar. Veri artırımı , mevcut örneklerinizden ek eğitim verileri üretme yaklaşımını arttırır ve daha sonra inandırıcı görünümlü görüntüler veren rastgele dönüşümler kullanır. Bu, modeli verilerin daha fazla yönüne maruz bırakmaya ve daha iyi genellemeye yardımcı olur.

Deneysel Keras Önişleme Katmanlarını kullanarak veri güçlendirmeyi uygulayacağız. Bunlar, modelinize diğer katmanlar gibi dahil edilebilir ve GPU'da çalıştırılabilir.

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

Aynı görüntüye birkaç kez veri büyütme uygulayarak birkaç artırılmış örneğin neye benzediğini görelim:

 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

Bir anda bir modeli eğitmek için veri büyütmeyi kullanacağız.

Bırakmak

Aşırı takmayı azaltmanın bir diğer tekniği, bir çeşit düzenlileştirme olan Ağa Bırakma'yı tanıtmaktır.

Bir katmana Bırakma uyguladığınızda, eğitim işlemi sırasında katmandan bir dizi çıktı birimini rastgele (etkinleştirme sıfıra ayarlayarak) bırakır. Bırakma, giriş değeri olarak 0,1, 0,2, 0,4 vb. Şeklinde kesirli bir sayı alır. Bu, çıktı birimlerinin% 10'unu,% 20'sini veya% 40'ını uygulanan katmandan rasgele çıkarmak anlamına gelir.

layers.Dropout kullanarak yeni bir sinir ağı layers.Dropout , ardından artırılmış görüntüleri kullanarak layers.Dropout .

 model = Sequential([
  data_augmentation,
  layers.experimental.preprocessing.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)
])
 

Modeli derleyin ve eğitin

 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 (MaxPooling2 (None, 90, 90, 16)        0         
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 90, 90, 32)        4640      
_________________________________________________________________
max_pooling2d_4 (MaxPooling2 (None, 45, 45, 32)        0         
_________________________________________________________________
conv2d_5 (Conv2D)            (None, 45, 45, 64)        18496     
_________________________________________________________________
max_pooling2d_5 (MaxPooling2 (None, 22, 22, 64)        0         
_________________________________________________________________
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 20ms/step - loss: 1.4842 - accuracy: 0.3279 - val_loss: 1.0863 - val_accuracy: 0.5640
Epoch 2/15
92/92 [==============================] - 1s 12ms/step - loss: 1.1215 - accuracy: 0.5284 - val_loss: 1.0374 - val_accuracy: 0.6022
Epoch 3/15
92/92 [==============================] - 1s 12ms/step - loss: 0.9680 - accuracy: 0.6117 - val_loss: 0.9200 - val_accuracy: 0.6485
Epoch 4/15
92/92 [==============================] - 1s 12ms/step - loss: 0.8538 - accuracy: 0.6753 - val_loss: 0.9206 - val_accuracy: 0.6417
Epoch 5/15
92/92 [==============================] - 1s 12ms/step - loss: 0.7744 - accuracy: 0.6977 - val_loss: 0.8169 - val_accuracy: 0.6839
Epoch 6/15
92/92 [==============================] - 1s 13ms/step - loss: 0.7758 - accuracy: 0.7093 - val_loss: 0.7743 - val_accuracy: 0.6880
Epoch 7/15
92/92 [==============================] - 1s 13ms/step - loss: 0.6805 - accuracy: 0.7481 - val_loss: 0.8598 - val_accuracy: 0.6540
Epoch 8/15
92/92 [==============================] - 1s 13ms/step - loss: 0.7132 - accuracy: 0.7278 - val_loss: 0.7177 - val_accuracy: 0.7207
Epoch 9/15
92/92 [==============================] - 1s 13ms/step - loss: 0.6634 - accuracy: 0.7580 - val_loss: 0.7152 - val_accuracy: 0.7166
Epoch 10/15
92/92 [==============================] - 1s 13ms/step - loss: 0.6562 - accuracy: 0.7538 - val_loss: 0.7251 - val_accuracy: 0.7248
Epoch 11/15
92/92 [==============================] - 1s 13ms/step - loss: 0.5798 - accuracy: 0.7840 - val_loss: 0.7016 - val_accuracy: 0.7357
Epoch 12/15
92/92 [==============================] - 1s 13ms/step - loss: 0.5635 - accuracy: 0.7913 - val_loss: 0.7755 - val_accuracy: 0.7248
Epoch 13/15
92/92 [==============================] - 1s 13ms/step - loss: 0.5361 - accuracy: 0.7982 - val_loss: 0.7575 - val_accuracy: 0.7153
Epoch 14/15
92/92 [==============================] - 1s 13ms/step - loss: 0.5420 - accuracy: 0.8022 - val_loss: 0.7375 - val_accuracy: 0.7302
Epoch 15/15
92/92 [==============================] - 1s 12ms/step - loss: 0.5132 - accuracy: 0.8120 - val_loss: 0.7561 - val_accuracy: 0.7289

Eğitim sonuçlarını görselleştirin

Veri artırımı ve Bırakma uygulandıktan sonra, öncekinden daha az sığdırma vardır ve eğitim ve doğrulama doğruluğu daha yakındır.

 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

Yeni verileri tahmin etme

Son olarak, eğitim veya doğrulama setlerinde bulunmayan bir resmi sınıflandırmak için modelimizi kullanalım.

 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 = keras.preprocessing.image.load_img(
    sunflower_path, target_size=(img_height, img_width)
)
img_array = keras.preprocessing.image.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
This image most likely belongs to sunflowers with a 89.39 percent confidence.