گلها را با آموزش انتقال طبقه بندی کنید

مشاهده در TensorFlow.org در Google Colab اجرا شود در GitHub مشاهده کنید دانلود دفترچه یادداشت مدل TF Hub را ببینید

آیا تا به حال یک گل زیبا دیده اید و فکر کرده اید که چه نوع گلی است؟ خب، شما اولین نفر نیستید، پس بیایید راهی برای شناسایی نوع گل از روی عکس بسازیم!

برای طبقه بندی تصاویر، یک نوع خاص از شبکه های عصبی عمیق، به نام یک شبکه عصبی کانولوشن ثابت شده است که بسیار قدرتمند است. با این حال، شبکه های عصبی کانولوشنال مدرن میلیون ها پارامتر دارند. آموزش آنها از ابتدا به داده های آموزشی برچسب گذاری شده زیادی و قدرت محاسباتی زیادی (صدها ساعت GPU یا بیشتر) نیاز دارد. ما فقط حدود سه هزار عکس برچسب دار داریم و می خواهیم زمان بسیار کمتری را صرف کنیم، بنابراین باید باهوش تر باشیم.

ما یک آموزش انتقال تکنیکی به نام استفاده خواهد کرد که در آن ما را به یک شبکه از قبل (آموزش در حدود یک میلیون تصاویر طور کلی)، استفاده از آن برای استخراج ویژگی های، و آموزش یک لایه جدید در بالای برای کار خود ما را از طبقه بندی تصاویر از گل.

برپایی

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

مجموعه داده گل ها

مجموعه داده گل ها شامل تصاویر گل ها با 5 برچسب کلاس ممکن است.

هنگام آموزش یک مدل یادگیری ماشینی، داده های خود را به مجموعه داده های آموزشی و آزمایشی تقسیم می کنیم. ما مدل را بر روی داده‌های آموزشی خود آموزش می‌دهیم و سپس ارزیابی می‌کنیم که مدل بر روی داده‌هایی که هرگز ندیده است - مجموعه آزمایشی چقدر خوب عمل می‌کند.

بیایید نمونه های آموزشی و آزمایشی خود را دانلود کنیم (ممکن است کمی طول بکشد) و آنها را به مجموعه های آموزشی و آزمایشی تقسیم کنیم.

دو سلول زیر را اجرا کنید:

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

داده ها را کاوش کنید

مجموعه داده گل ها شامل نمونه هایی است که تصاویر گل ها را برچسب گذاری کرده اند. هر مثال حاوی یک تصویر گل JPEG و برچسب کلاس است: چه نوع گلی است. بیایید چند تصویر را همراه با برچسب آنها نمایش دهیم.

نمایش برخی از تصاویر برچسب‌گذاری شده

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

مدل را بسازید

ما باید یک بار خواهد TF-توپی ماژول بردار ویژگی تصویر، پشته یک طبقه بندی خطی بر روی آن، و اضافه کردن آموزش و ارزیابی عملیات. سلول زیر یک نمودار TF می سازد که مدل و آموزش آن را توصیف می کند، اما آموزش را اجرا نمی کند (این مرحله بعدی خواهد بود).

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)

شبکه را آموزش دهید

اکنون که مدل ما ساخته شده است، بیایید آن را آموزش دهیم و ببینیم که چگونه در مجموعه آزمایشی ما عمل می کند.

# 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

پیش بینی های نادرست

بیایید نگاهی دقیق‌تر به نمونه‌های آزمایشی بیاندازیم که مدل ما اشتباه کرده است.

  • آیا نمونه هایی با برچسب اشتباه در مجموعه آزمایشی ما وجود دارد؟
  • آیا داده های بدی در مجموعه آزمایشی وجود دارد - تصاویری که در واقع تصاویر گل ها نیستند؟
  • آیا تصاویری وجود دارد که بتوانید دلیل اشتباه مدل را درک کنید؟
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

تمرینات: مدل را بهبود بخشید!

ما یک مدل پایه را آموزش داده ایم، اکنون بیایید سعی کنیم آن را بهبود بخشیم تا به دقت بهتری دست یابیم. (به یاد داشته باشید که هنگام ایجاد تغییر، باید سلول ها را مجدداً اجرا کنید.)

تمرین 1: یک مدل تصویر متفاوت را امتحان کنید.

با TF-Hub، آزمایش چند مدل تصویر مختلف ساده است. فقط جایگزین "https://tfhub.dev/google/imagenet/mobilenet_v2_050_128/feature_vector/2" دسته در hub.Module() پاسخ با یک دسته از ماژول های مختلف و دوباره تمام کد. شما می توانید تمام ماژول های تصویر موجود در دیدن tfhub.dev .

یک انتخاب خوب ممکن است یکی دیگر از ماژول های MobileNet V2 . بسیاری از ماژول های - از جمله MobileNet ماژول - در آموزش دیده بودند ImageNet مجموعه داده که شامل بیش از 1 میلیون تصاویر و 1000 کلاس. انتخاب یک معماری شبکه، تعادلی بین سرعت و دقت طبقه‌بندی ایجاد می‌کند: مدل‌هایی مانند MobileNet یا NASNet Mobile سریع و کوچک هستند، معماری‌های سنتی‌تر مانند Inception و ResNet برای دقت طراحی شده‌اند.

برای بزرگتر معماری آغاز به کار V3، شما همچنین می توانید از مزایای قبل از آموزش را در یک دامنه نزدیک تر به کار خود کشف: آن نیز موجود است به عنوان یک ماژول آموزش دیده در مجموعه داده iNaturalist از گیاهان و حیوانات.

تمرین 2: یک لایه پنهان اضافه کنید.

یک لایه پنهان بین ویژگی های تصویر استخراج و طبقه بندی خطی (در عملکرد پشته create_model() در بالا). برای ایجاد یک لایه غیر خطی پنهان با به عنوان مثال 100 گره، استفاده tf.layers.dense با واحد را به 100 و فعال سازی مجموعه ای به tf.nn.relu . آیا تغییر اندازه لایه پنهان بر دقت تست تأثیر می گذارد؟ آیا افزودن لایه مخفی دوم دقت را بهبود می بخشد؟

تمرین 3: تغییر پارامترها.

آیا افزایش تعداد مراحل آموزش بهبود دقت و صحت نهایی؟ می توانید میزان یادگیری را به همگرایی مدل خود را با سرعت بیشتری تغییر می دهید؟ آیا آموزش اندازه دسته بر عملکرد مدل شما؟

تمرین 4: یک بهینه ساز متفاوت را امتحان کنید.

به جای GradientDescentOptimizer اساسی با بهینه ساز واب فریبنده، مثل AdagradOptimizer . آیا برای آموزش مدل شما فرقی می کند؟ اگر شما می خواهید برای کسب اطلاعات بیشتر در مورد مزایای الگوریتم های بهینه سازی مختلف، چک کردن این پست .

می خواهید بیشتر بدانید؟

اگر شما در یک نسخه پیشرفته تر از این آموزش علاقه مند، چک کردن تصویر TensorFlow بازآموزی آموزش که شما از طریق پیاده تجسم آموزش با استفاده از TensorBoard، تکنیک های پیشرفته مانند مجموعه داده تقویت با تحریف تصاویر و جایگزین گل مجموعه داده به یادگیری از یک طبقه بندی تصویر بر روی مجموعه داده خودتان

شما می توانید اطلاعات بیشتر در مورد TensorFlow در یاد بگیرند tensorflow.org و دیدن مستندات API TF-توپی در دسترس است tensorflow.org/hub . یافتن دسترس ماژول TensorFlow توپی در tfhub.dev از جمله ماژول های بردار ویژگی تصویر بیشتر و ماژول های تعبیه متن.

همچنین از بررسی یادگیری ماشین تصادف دوره است که به سرعت گام، معرفی عملی گوگل برای یادگیری ماشین است.