Transfer Öğrenimi ile Çiçekleri Sınıflandırın

TensorFlow.org'da görüntüleyin Google Colab'da çalıştırın GitHub'da görüntüle Not defterini indir TF Hub modeline bakın

Hiç güzel bir çiçek gördünüz ve ne tür bir çiçek olduğunu merak ettiniz mi? Pekala, ilk değilsin, o yüzden bir fotoğraftan çiçeğin türünü belirlemenin bir yolunu bulalım!

Görüntüleri sınıflandırmak için, kıvrımlı bir sinir ağı denilen derin sinir ağının belirli bir tip, özellikle güçlü olduğunu kanıtlamıştır. Bununla birlikte, modern evrişimli sinir ağlarının milyonlarca parametresi vardır. Bunları sıfırdan eğitmek, çok sayıda etiketli eğitim verisi ve çok fazla bilgi işlem gücü (yüzlerce GPU saati veya daha fazla) gerektirir. Sadece yaklaşık üç bin etiketli fotoğrafımız var ve çok daha az zaman harcamak istiyoruz, bu yüzden daha akıllı olmamız gerekiyor.

Biz, (yaklaşık bir milyon genel görüntülerde eğitilmiş) önceden eğitilmiş ağı almak özellikleri ayıklamak için kullanabilirsiniz nerede denilen bir teknik aktarım öğrenmeyi kullanın ve çiçek görüntüleri sınıflandırma kendi görev için üstte yeni bir katman eğitim verecek.

Kurmak

import collections
import io
import math
import os
import random
from six.moves import urllib

from IPython.display import clear_output, Image, display, HTML

import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()

import tensorflow_hub as hub

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import sklearn.metrics as sk_metrics
import time
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/compat/v2_compat.py:111: disable_resource_variables (from tensorflow.python.ops.variable_scope) is deprecated and will be removed in a future version.
Instructions for updating:
non-resource variables are not supported in the long term

çiçekler veri seti

Çiçekler veri seti, 5 olası sınıf etiketine sahip çiçek görüntülerinden oluşur.

Bir makine öğrenimi modelini eğitirken verilerimizi eğitim ve test veri kümelerine ayırırız. Modeli eğitim verilerimiz üzerinde eğiteceğiz ve ardından modelin daha önce hiç görmediği veriler - test seti üzerinde ne kadar iyi performans gösterdiğini değerlendireceğiz.

Eğitim ve test örneklerimizi indirelim (biraz zaman alabilir) ve bunları tren ve test setlerine ayıralım.

Aşağıdaki iki hücreyi çalıştırın:

FLOWERS_DIR = './flower_photos'
TRAIN_FRACTION = 0.8
RANDOM_SEED = 2018


def download_images():
  """If the images aren't already downloaded, save them to FLOWERS_DIR."""
  if not os.path.exists(FLOWERS_DIR):
    DOWNLOAD_URL = 'http://download.tensorflow.org/example_images/flower_photos.tgz'
    print('Downloading flower images from %s...' % DOWNLOAD_URL)
    urllib.request.urlretrieve(DOWNLOAD_URL, 'flower_photos.tgz')
    !tar xfz flower_photos.tgz
  print('Flower photos are located in %s' % FLOWERS_DIR)


def make_train_and_test_sets():
  """Split the data into train and test sets and get the label classes."""
  train_examples, test_examples = [], []
  shuffler = random.Random(RANDOM_SEED)
  is_root = True
  for (dirname, subdirs, filenames) in tf.gfile.Walk(FLOWERS_DIR):
    # The root directory gives us the classes
    if is_root:
      subdirs = sorted(subdirs)
      classes = collections.OrderedDict(enumerate(subdirs))
      label_to_class = dict([(x, i) for i, x in enumerate(subdirs)])
      is_root = False
    # The sub directories give us the image files for training.
    else:
      filenames.sort()
      shuffler.shuffle(filenames)
      full_filenames = [os.path.join(dirname, f) for f in filenames]
      label = dirname.split('/')[-1]
      label_class = label_to_class[label]
      # An example is the image file and it's label class.
      examples = list(zip(full_filenames, [label_class] * len(filenames)))
      num_train = int(len(filenames) * TRAIN_FRACTION)
      train_examples.extend(examples[:num_train])
      test_examples.extend(examples[num_train:])

  shuffler.shuffle(train_examples)
  shuffler.shuffle(test_examples)
  return train_examples, test_examples, classes
# Download the images and split the images into train and test sets.
download_images()
TRAIN_EXAMPLES, TEST_EXAMPLES, CLASSES = make_train_and_test_sets()
NUM_CLASSES = len(CLASSES)

print('\nThe dataset has %d label classes: %s' % (NUM_CLASSES, CLASSES.values()))
print('There are %d training images' % len(TRAIN_EXAMPLES))
print('there are %d test images' % len(TEST_EXAMPLES))
Downloading flower images from http://download.tensorflow.org/example_images/flower_photos.tgz...
Flower photos are located in ./flower_photos

The dataset has 5 label classes: odict_values(['daisy', 'dandelion', 'roses', 'sunflowers', 'tulips'])
There are 2934 training images
there are 736 test images

Verileri keşfedin

Çiçekler veri seti, çiçek resimlerinin etiketlendiği örneklerden oluşur. Her örnek bir JPEG çiçek resmi ve sınıf etiketi içerir: ne tür bir çiçek. Birkaç görseli etiketleriyle birlikte gösterelim.

Bazı etiketli resimleri göster

def get_label(example):
  """Get the label (number) for given example."""
  return example[1]

def get_class(example):
  """Get the class (string) of given example."""
  return CLASSES[get_label(example)]

def get_encoded_image(example):
  """Get the image data (encoded jpg) of given example."""
  image_path = example[0]
  return tf.gfile.GFile(image_path, 'rb').read()

def get_image(example):
  """Get image as np.array of pixels for given example."""
  return plt.imread(io.BytesIO(get_encoded_image(example)), format='jpg')

def display_images(images_and_classes, cols=5):
  """Display given images and their labels in a grid."""
  rows = int(math.ceil(len(images_and_classes) / cols))
  fig = plt.figure()
  fig.set_size_inches(cols * 3, rows * 3)
  for i, (image, flower_class) in enumerate(images_and_classes):
    plt.subplot(rows, cols, i + 1)
    plt.axis('off')
    plt.imshow(image)
    plt.title(flower_class)

NUM_IMAGES = 15
display_images([(get_image(example), get_class(example))
               for example in TRAIN_EXAMPLES[:NUM_IMAGES]])

png

Modeli oluşturun

Biz yükleyecek TF-Hub , görüntü özelliği vektör modülü üzerinde doğrusal bir fonksiyonu yığını ve eğitim ve değerlendirme oplari ekleyin. Aşağıdaki hücre, modeli ve eğitimini açıklayan bir TF grafiği oluşturur, ancak eğitimi çalıştırmaz (bu bir sonraki adım olacaktır).

LEARNING_RATE = 0.01

tf.reset_default_graph()

# Load a pre-trained TF-Hub module for extracting features from images. We've
# chosen this particular module for speed, but many other choices are available.
image_module = hub.Module('https://tfhub.dev/google/imagenet/mobilenet_v2_035_128/feature_vector/2')

# Preprocessing images into tensors with size expected by the image module.
encoded_images = tf.placeholder(tf.string, shape=[None])
image_size = hub.get_expected_image_size(image_module)


def decode_and_resize_image(encoded):
  decoded = tf.image.decode_jpeg(encoded, channels=3)
  decoded = tf.image.convert_image_dtype(decoded, tf.float32)
  return tf.image.resize_images(decoded, image_size)


batch_images = tf.map_fn(decode_and_resize_image, encoded_images, dtype=tf.float32)

# The image module can be applied as a function to extract feature vectors for a
# batch of images.
features = image_module(batch_images)


def create_model(features):
  """Build a model for classification from extracted features."""
  # Currently, the model is just a single linear layer. You can try to add
  # another layer, but be careful... two linear layers (when activation=None)
  # are equivalent to a single linear layer. You can create a nonlinear layer
  # like this:
  # layer = tf.layers.dense(inputs=..., units=..., activation=tf.nn.relu)
  layer = tf.layers.dense(inputs=features, units=NUM_CLASSES, activation=None)
  return layer


# For each class (kind of flower), the model outputs some real number as a score
# how much the input resembles this class. This vector of numbers is often
# called the "logits".
logits = create_model(features)
labels = tf.placeholder(tf.float32, [None, NUM_CLASSES])

# Mathematically, a good way to measure how much the predicted probabilities
# diverge from the truth is the "cross-entropy" between the two probability
# distributions. For numerical stability, this is best done directly from the
# logits, not the probabilities extracted from them.
cross_entropy = tf.nn.softmax_cross_entropy_with_logits_v2(logits=logits, labels=labels)
cross_entropy_mean = tf.reduce_mean(cross_entropy)

# Let's add an optimizer so we can train the network.
optimizer = tf.train.GradientDescentOptimizer(learning_rate=LEARNING_RATE)
train_op = optimizer.minimize(loss=cross_entropy_mean)

# The "softmax" function transforms the logits vector into a vector of
# probabilities: non-negative numbers that sum up to one, and the i-th number
# says how likely the input comes from class i.
probabilities = tf.nn.softmax(logits)

# We choose the highest one as the predicted class.
prediction = tf.argmax(probabilities, 1)
correct_prediction = tf.equal(prediction, tf.argmax(labels, 1))

# The accuracy will allow us to eval on our test set. 
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
WARNING:tensorflow:From /tmp/ipykernel_3995/2879154528.py:20: calling map_fn (from tensorflow.python.ops.map_fn) with dtype is deprecated and will be removed in a future version.
Instructions for updating:
Use fn_output_signature instead
WARNING:tensorflow:From /tmp/ipykernel_3995/2879154528.py:20: calling map_fn (from tensorflow.python.ops.map_fn) with dtype is deprecated and will be removed in a future version.
Instructions for updating:
Use fn_output_signature instead
INFO:tensorflow:Saver not created because there are no variables in the graph to restore
INFO:tensorflow:Saver not created because there are no variables in the graph to restore
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py:34: UserWarning: `tf.layers.dense` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dense` instead.
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/legacy_tf_layers/core.py:255: UserWarning: `layer.apply` is deprecated and will be removed in a future version. Please use `layer.__call__` method instead.
  return layer.apply(inputs)

Ağı eğitin

Şimdi modelimiz oluşturuldu, hadi onu eğitelim ve test setimizde nasıl performans gösterdiğini görelim.

# How long will we train the network (number of batches).
NUM_TRAIN_STEPS = 100
# How many training examples we use in each step.
TRAIN_BATCH_SIZE = 10
# How often to evaluate the model performance.
EVAL_EVERY = 10

def get_batch(batch_size=None, test=False):
  """Get a random batch of examples."""
  examples = TEST_EXAMPLES if test else TRAIN_EXAMPLES
  batch_examples = random.sample(examples, batch_size) if batch_size else examples
  return batch_examples

def get_images_and_labels(batch_examples):
  images = [get_encoded_image(e) for e in batch_examples]
  one_hot_labels = [get_label_one_hot(e) for e in batch_examples]
  return images, one_hot_labels

def get_label_one_hot(example):
  """Get the one hot encoding vector for the example."""
  one_hot_vector = np.zeros(NUM_CLASSES)
  np.put(one_hot_vector, get_label(example), 1)
  return one_hot_vector

with tf.Session() as sess:
  sess.run(tf.global_variables_initializer())
  for i in range(NUM_TRAIN_STEPS):
    # Get a random batch of training examples.
    train_batch = get_batch(batch_size=TRAIN_BATCH_SIZE)
    batch_images, batch_labels = get_images_and_labels(train_batch)
    # Run the train_op to train the model.
    train_loss, _, train_accuracy = sess.run(
        [cross_entropy_mean, train_op, accuracy],
        feed_dict={encoded_images: batch_images, labels: batch_labels})
    is_final_step = (i == (NUM_TRAIN_STEPS - 1))
    if i % EVAL_EVERY == 0 or is_final_step:
      # Get a batch of test examples.
      test_batch = get_batch(batch_size=None, test=True)
      batch_images, batch_labels = get_images_and_labels(test_batch)
      # Evaluate how well our model performs on the test set.
      test_loss, test_accuracy, test_prediction, correct_predicate = sess.run(
        [cross_entropy_mean, accuracy, prediction, correct_prediction],
        feed_dict={encoded_images: batch_images, labels: batch_labels})
      print('Test accuracy at step %s: %.2f%%' % (i, (test_accuracy * 100)))
Test accuracy at step 0: 22.01%
Test accuracy at step 10: 52.04%
Test accuracy at step 20: 63.99%
Test accuracy at step 30: 69.97%
Test accuracy at step 40: 74.59%
Test accuracy at step 50: 75.00%
Test accuracy at step 60: 75.00%
Test accuracy at step 70: 78.26%
Test accuracy at step 80: 80.98%
Test accuracy at step 90: 79.21%
Test accuracy at step 99: 80.30%
def show_confusion_matrix(test_labels, predictions):
  """Compute confusion matrix and normalize."""
  confusion = sk_metrics.confusion_matrix(
    np.argmax(test_labels, axis=1), predictions)
  confusion_normalized = confusion.astype("float") / confusion.sum(axis=1)
  axis_labels = list(CLASSES.values())
  ax = sns.heatmap(
      confusion_normalized, xticklabels=axis_labels, yticklabels=axis_labels,
      cmap='Blues', annot=True, fmt='.2f', square=True)
  plt.title("Confusion matrix")
  plt.ylabel("True label")
  plt.xlabel("Predicted label")

show_confusion_matrix(batch_labels, test_prediction)

png

Yanlış tahminler

Modelimizin yanlış yaptığı test örneklerine yakından bakalım.

  • Test setimizde yanlış etiketlenmiş örnekler var mı?
  • Test setinde herhangi bir kötü veri var mı - aslında çiçek resimleri olmayan resimler mi?
  • Modelin neden hata yaptığını anlayabileceğiniz görseller var mı?
incorrect = [
    (example, CLASSES[prediction])
    for example, prediction, is_correct in zip(test_batch, test_prediction, correct_predicate)
    if not is_correct
]
display_images(
  [(get_image(example), "prediction: {0}\nlabel:{1}".format(incorrect_prediction, get_class(example)))
   for (example, incorrect_prediction) in incorrect[:20]])

png

Alıştırmalar: Modeli geliştirin!

Bir temel model eğittik, şimdi daha iyi doğruluk elde etmek için onu geliştirmeye çalışalım. (Değişiklik yaptığınızda hücreleri yeniden çalıştırmanız gerekeceğini unutmayın.)

Alıştırma 1: Farklı bir görüntü modeli deneyin.

TF-Hub ile birkaç farklı görüntü modelini denemek basittir. Sadece yerine "https://tfhub.dev/google/imagenet/mobilenet_v2_050_128/feature_vector/2" kolu hub.Module() farklı modülün bir sap ile görüşmesi ve tüm kodu yeniden çalıştırın. Sen de kullanılabilir tüm resim modülleri görebilirsiniz tfhub.dev .

İyi bir seçim diğer biri olabilir MobileNet V2 modüllerinin . Modüllerin birçoğu - dahil MobileNet modülleri - eğitilmiştir ImageNet veri kümesi üzerinde 1.000.000 görüntüler ve 1000 sınıfları içeren. Bir ağ mimarisi seçmek, hız ve sınıflandırma doğruluğu arasında bir denge sağlar: MobileNet veya NASNet Mobile gibi modeller hızlı ve küçüktür, Inception ve ResNet gibi daha geleneksel mimariler doğruluk için tasarlanmıştır.

Daha büyük Inception V3 mimarisi için, ayrıca kendi görev daha yakın bir etki alanında ön eğitimin faydalarını keşfetmek: Bir olarak da mevcuttur iNaturalist veri kümesi üzerinde eğitilmiş modül bitki ve hayvan.

Alıştırma 2: Gizli bir katman ekleyin.

Çıkarılmış görüntü özellikleri ve (fonksiyon doğrusal sınıflandırıcı arasındaki gizli katman yığını create_model() yukarıda). 100 düğümleri, kullanım, örneğin bir doğrusal olmayan gizli katman oluşturmak için tf.layers.dense 100 ve aktivasyon grubu ayarlanmış birimleri ile tf.nn.relu . Gizli katmanın boyutunu değiştirmek test doğruluğunu etkiler mi? İkinci gizli katman eklemek doğruluğu artırır mı?

Alıştırma 3: Hiperparametreleri değiştirin.

Eğitim adımlarının artan sayıda nihai doğruluğunu artırır mı? Daha hızlı bir şekilde modeli Converge yapmak için öğrenme oranını değiştirebilir miyim? Eğitim parti boyutu modelinizin performansını etkiler mi?

Alıştırma 4: Farklı bir optimize edici deneyin.

Mesela bir daha pişmek optimize edici, temel GradientDescentOptimizer değiştirin AdagradOptimizer . Model eğitiminiz için bir fark yaratıyor mu? Eğer, farklı optimizasyon algoritmaları yararları hakkında daha fazla bilgi kontrol etmek istiyorsanız bu yazı .

Daha fazla öğrenmek ister misiniz?

Eğer bu yazının daha gelişmiş bir sürümü ilgilenen varsa, kontrol öğretici yeniden eğitim TensorFlow görüntü üzerinde bir görüntü sınıflandırıcı öğrenmek görüntüleri çarpıtarak ve çiçek değiştirerek veri kümesi büyütme gibi TensorBoard kullanarak eğitim, gelişmiş teknikleri görüntülenmesi konusunda size yol gösterecektir veri kümesi kendi veri kümeniz.

En TensorFlow hakkında daha fazla bilgi edinebilir tensorflow.org ve TF-Hub API belgelerine mevcuttur bkz tensorflow.org/hub . Mevcut TensorFlow Hub modüllerini bulun tfhub.dev fazla görüntü özelliği vektör modülleri ve metin katıştırma modülleri dahil.

Ayrıca kontrol Makine Öğrenimi Crash Course makine öğrenimi için Google'ın hızlı tempolu, pratik bir giriştir.