Прошло 3 недели с тех пор, как я начал свой шестинедельный проект машинного обучения, и я очень счастлив, что смог сделать довольно много вещей и научиться чему-то новому из этого проекта. Всегда лучше заниматься проектом, независимо от того, маленький он или большой, просто попробуйте и посмотрите, как это происходит, чтобы мы могли узнать, как все работает, и исследовать, что происходит.

2 недели вкратце

Неделя 1:

  • Изображения и этикетки.
  • Создание проверочного набора.
  • Предварительная обработка изображений.
  • Преобразование данных в пакеты.

(Предыдущая статья на 1-й неделе: Ссылка 1, Ссылка2)

Неделя 2:

  • Строим нашу модель.
  • Создание необходимых обратных вызовов.

(Предыдущая статья на 2-й неделе: Ссылка

3 неделя

После построения модели и создания обратных вызовов пришло время обучить нашу модель не на полном наборе данных, а на подмножестве наших данных. Мы обучаем модель на подмножестве наших данных, потому что, если после обучения возникают какие-либо ошибки, мы можем легко заметить это, увидев результаты из подмножества, тем самым сэкономив наше драгоценное время. Поэтому лучше обучить нашу модель на подмножестве наших данных, сделать прогноз, оценку, а затем продолжить обучение с полным набором данных.

Обучение нашей модели

Сначала мы устанавливаем количество эпох на определенное количество по нашему выбору, прежде чем начать нашу работу. Его легко установить, инициализировав переменную Num_EPOCHS = 100.

Как и ранее, здесь мы также используем функцию для обучения нашей модели, и эта функция выполняет следующие действия:

  1. Создайте модель, используя create_our_model() (эта функция разработана на неделе 2).
  2. Настройте обратный вызов tenorboard с помощью create_callback() (эта функция разработана на неделе 2).
  3. Вызовите функцию fit().
  4. Верните модель.

Мы пишем 2 функции поезда, так как нам нужно сделать это и для кошки, и для собаки.

CAT

# Lets build the model for our cat
# Build a function to train and return a trained model
def train_cat_model():
  """
  Trains a given model and returns the trained version.
  """
  # Create a model
  model = create_our_model()

  # Create new TensorBoard session everytitme we train a model
  tensorboard = create_callback()

  # Fit the model to the data passing it the callbacks we created
  model.fit(x=train_cat_data,
            epochs=NUM_EPOCHS,
            validation_data=val_cat_data,
            validation_freq=1,
            callbacks=[tensorboard, early_stopping])
  # Return the fitted model
  return model

СОБАКА

# Lets build the same for our dog
# Build a function to train and return a trained model
def train_dog_model():
  """
  Trains a given model and returns the trained version.
  """
  # Create a model
  model = create_our_model()

  # Create new TensorBoard session everytitme we train a model
  tensorboard = create_callback()

  # Fit the model to the data passing it the callbacks we created
  model.fit(x=train_dog_data,
            epochs=NUM_EPOCHS,
            validation_data=val_dog_data,
            validation_freq=1,
            callbacks=[tensorboard, early_stopping])
  # Return the fitted model
  return model

Теперь мы создали модель кошки и собаки. Давайте поместим наши данные в соответствующую модель и посмотрим на наш результат.

CAT

model_cat = train_cat_model()
Epoch 1/100
 1/25 [>.............................] - ETA: 0s - loss: 1.0319 - accuracy: 0.1875WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/summary_ops_v2.py:1277: stop (from tensorflow.python.eager.profiler) is deprecated and will be removed after 2020-07-01.
Instructions for updating:
use `tf.profiler.experimental.stop` instead.
WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/summary_ops_v2.py:1277: stop (from tensorflow.python.eager.profiler) is deprecated and will be removed after 2020-07-01.
Instructions for updating:
use `tf.profiler.experimental.stop` instead.
25/25 [==============================] - 412s 16s/step - loss: 0.2104 - accuracy: 0.9013 - val_loss: 0.0239 - val_accuracy: 0.9900
Epoch 2/100
25/25 [==============================] - 5s 210ms/step - loss: 0.0044 - accuracy: 1.0000 - val_loss: 0.0148 - val_accuracy: 0.9950
Epoch 3/100
25/25 [==============================] - 6s 231ms/step - loss: 0.0019 - accuracy: 1.0000 - val_loss: 0.0135 - val_accuracy: 0.9950
Epoch 4/100
25/25 [==============================] - 6s 237ms/step - loss: 0.0014 - accuracy: 1.0000 - val_loss: 0.0128 - val_accuracy: 0.9950
Epoch 5/100
25/25 [==============================] - 5s 209ms/step - loss: 0.0011 - accuracy: 1.0000 - val_loss: 0.0123 - val_accuracy: 0.9950

СОБАКА

model_dog = train_dog_model()
Epoch 1/100
25/25 [==============================] - 526s 21s/step - loss: 0.1677 - accuracy: 0.9688 - val_loss: 0.0543 - val_accuracy: 0.9950
Epoch 2/100
25/25 [==============================] - 5s 214ms/step - loss: 0.0262 - accuracy: 0.9987 - val_loss: 0.0338 - val_accuracy: 0.9950
Epoch 3/100
25/25 [==============================] - 5s 214ms/step - loss: 0.0133 - accuracy: 1.0000 - val_loss: 0.0299 - val_accuracy: 0.9950
Epoch 4/100
25/25 [==============================] - 5s 211ms/step - loss: 0.0091 - accuracy: 1.0000 - val_loss: 0.0275 - val_accuracy: 0.9950

Из приведенных выше результатов мы можем наблюдать важность обратного вызова ранней остановки, потому что после повторения значения точности в течение 3 последовательных периодов запускается обратный вызов ранней остановки и обучение останавливается, поскольку больше не будет улучшений.

Теперь наша модель обучена. Давайте сохраним и загрузим модель для прогнозирования и оценки.

Сохраните и загрузите нашу модель

После обучения нашей модели мы можем просто сохранить и загрузить модель, когда захотим, для будущего использования. Функция save_model() and load_model() используется для сохранения и загрузки нашей модели.

# Create a function to save a model
def save_model(model, suffix=None):
  """ 
  Saves a given model in a models directoory and appends a suffix(string).
  """
  # Create a model directory pathname with current time
  modeldir = os.path.join("drive/My Drive/CatVsDog/models",
                          datetime.datetime.now().strftime("%Y%m%d-%H%M%s"))
  model_path = modeldir + "-" + suffix + ".h5" # Save format of model
  print(f"Saving model to: {model_path}...")
  model.save(model_path)
  return model_path
# Create a function to load the saved model
def load_model(model_path):
  """
  Loads a saved model from a specified path.
  """
  print(f"Loading saved model from {model_path}....")
  model = tf.keras.models.load_model(model_path,
                                     custom_objects={"KerasLayer":hub.KerasLayer})
  return model

Создание и оценка прогнозов с использованием обученной модели

Мы можем делать прогнозы по нашей модели, используя .predict().

# Start with cat
predictions_cat = load_cat_model.predict(val_cat_data, verbose=1)
predictions_cat[:10]
7/7 [==============================] - 76s 11s/step
array([[9.9873966e-01, 1.3146200e-05],
       [9.9852967e-01, 7.7154495e-05],
       [9.9644947e-01, 8.2693979e-05],
       [9.9523073e-01, 3.1922915e-04],
       [9.2441016e-01, 1.4963249e-02],
       [9.8091561e-01, 5.0850637e-04],
       [9.8195803e-01, 2.6257571e-06],
       [9.9035978e-01, 2.1479432e-04],
       [9.9588352e-01, 7.6251227e-04],
       [9.9996185e-01, 3.8020313e-05]], dtype=float32)
# Now do the same with dog
predictions_dog = load_dog_model.predict(val_dog_data, verbose=1)
predictions_dog[:10]
7/7 [==============================] - 78s 11s/step
array([[1.2041514e-02, 9.6527416e-01],
       [2.4055562e-06, 9.9221051e-01],
       [4.7578651e-04, 9.9225640e-01],
       [6.0469288e-06, 9.9614292e-01],
       [2.9330796e-03, 9.8701084e-01],
       [5.5391331e-05, 9.9003279e-01],
       [3.0013523e-04, 9.9073374e-01],
       [3.8970767e-03, 9.7210705e-01],
       [5.4554670e-04, 9.7027451e-01],
       [9.8549217e-06, 9.9355388e-01]], dtype=float32)

Теперь мы можем попытаться взять изображение из набора данных и показать результаты этого изображения, такие как прогнозы, метки и т. Д. Чтобы построить результаты, нам нужно получить несколько вещей, например:

  • Получить метку прогноза: это можно сделать, написав функцию get_pred_label_cat() и get_pred_label_dog().
# Cat
def get_pred_label_cat(prediction_probabilities):
  """
  Turns an array of prediction probabilities into labels.
  """
  return cat_label[np.argmax(prediction_probabilities)]
# Dog
def get_pred_label_dog(prediction_probabilities):
  """
  Turns an array of prediction probabilities into labels.
  """
  return dog_label[np.argmax(prediction_probabilities)]
  • Теперь нам нужно разблокировать наши данные проверки, чтобы сделать прогноз, и это делается с помощью функций unbatchify_cat() и unbatchify_dog().
# Create a function to unbatch a batch dataset
# 1. Cat
def unbatchify_cat(data):
  """
  Takes a batched dataset of (image, label) Tensors and returns separate arrays of images and labels.
  """

  images = []
  labels = []
  # Loop through unbatched data
  for image, label in data.unbatch().as_numpy_iterator():
    images.append(image)
    labels.append(cat_label[np.argmax(label)])

  return images, labels
# Create a function to unbatch a batch dataset
# 2. Dog
def unbatchify_dog(data):
  """
  Takes a batched dataset of (image, label) Tensors and returns separate arrays of images and labels.
  """

  images = []
  labels = []
  # Loop through unbatched data
  for image, label in data.unbatch().as_numpy_iterator():
    images.append(image)
    labels.append(dog_label[np.argmax(label)])

  return images, labels

Теперь мы готовы визуализировать все как есть:

  1. Ярлыки прогнозов.
  2. Ярлык проверки.
  3. Проверочные изображения.

plot_pred_cat() and plot_pred_dog() можно использовать, чтобы:

  • Принимает массив вероятностей предсказания, массив меток истинности и массив изображений и целых чисел.
  • Преобразуйте вероятности предсказания в предсказанную метку.
  • Постройте предсказанную метку, ее предсказанную вероятность, метку истинности и целевое изображение на одном графике.
def plot_pred_cat(prediction_probabilities, labels, images, n=1):
  """
  View the truth, prediction and images for n samples of cat
  """
  pred_prob, true_label, image = prediction_probabilities[n], labels[n], images[n]

  pred_label = get_pred_label_cat(pred_prob)

  # Plot image and remove ticks
  plt.imshow(image)
  plt.xticks([])
  plt.yticks([])

  # Change the colour of the title depending on if the prediction is right or wrong
  if (pred_label == true_label).any():
    color="green"
  else:
    color = "red"

  # Chnage plot title to be predicited, probability of prediction and truth label
  plt.title("{} {:2.0f}% {}".format(pred_label,
                                    np.max(pred_prob)*100,
                                    "cat"), color=color)
plot_pred_cat(prediction_probabilities = predictions_cat,
          labels=val_cat_labels,
          images=val_cat_images)

def plot_pred_dog(prediction_probabilities, labels, images, n=1):
  """
  View the truth, prediction and images for n samples of dog.
  """
  pred_prob, true_label, image = prediction_probabilities[n], labels[n], images[n]

  pred_label = get_pred_label_dog(pred_prob)

  # Plot image and remove ticks
  plt.imshow(image)
  plt.xticks([])
  plt.yticks([])

  # Change the colour of the title depending on if the prediction is right or wrong
  if (pred_label == true_label).any():
    color="green"
  else:
    color = "red"

  # Chnage plot title to be predicited, probability of prediction and truth label
  plt.title("{} {:2.0f}% {}".format(pred_label,
                                    np.max(pred_prob)*100,
                                    "dog"), color=color)
plot_pred_dog(prediction_probabilities = predictions_dog,
          labels=val_dog_labels,
          images=val_dog_images)

Теперь мы обучили нашу модель на подмножестве данных, сохранили и загрузили модель, сделали прогнозы и выполнили визуализацию с изображением.

Мой репозиторий на Github: Ссылка

Что дальше

Следующее, что было запланировано, - это провести обучение на нашем полном наборе данных. Здесь мы видим, что после обучения на подмножестве данных мы получили правильные прогнозы и можем продолжить обучение нашей модели с полным набором данных. Итак, это план на 4-ю неделю - обучение нашей модели на полном наборе данных.

Я очень рад, что дошел так далеко, и осталось всего несколько шагов, чтобы добраться до вершины горы. Я достаточно уверен, что смогу закончить работу вовремя и увидеть, как мой проект «Кошка против собаки» очень скоро воплотится в жизнь!