Прошло 3 недели с тех пор, как я начал свой шестинедельный проект машинного обучения, и я очень счастлив, что смог сделать довольно много вещей и научиться чему-то новому из этого проекта. Всегда лучше заниматься проектом, независимо от того, маленький он или большой, просто попробуйте и посмотрите, как это происходит, чтобы мы могли узнать, как все работает, и исследовать, что происходит.
2 недели вкратце
Неделя 1:
- Изображения и этикетки.
- Создание проверочного набора.
- Предварительная обработка изображений.
- Преобразование данных в пакеты.
(Предыдущая статья на 1-й неделе: Ссылка 1, Ссылка2)
Неделя 2:
- Строим нашу модель.
- Создание необходимых обратных вызовов.
(Предыдущая статья на 2-й неделе: Ссылка
3 неделя
После построения модели и создания обратных вызовов пришло время обучить нашу модель не на полном наборе данных, а на подмножестве наших данных. Мы обучаем модель на подмножестве наших данных, потому что, если после обучения возникают какие-либо ошибки, мы можем легко заметить это, увидев результаты из подмножества, тем самым сэкономив наше драгоценное время. Поэтому лучше обучить нашу модель на подмножестве наших данных, сделать прогноз, оценку, а затем продолжить обучение с полным набором данных.
Обучение нашей модели
Сначала мы устанавливаем количество эпох на определенное количество по нашему выбору, прежде чем начать нашу работу. Его легко установить, инициализировав переменную Num_EPOCHS = 100.
Как и ранее, здесь мы также используем функцию для обучения нашей модели, и эта функция выполняет следующие действия:
- Создайте модель, используя
create_our_model()
(эта функция разработана на неделе 2). - Настройте обратный вызов tenorboard с помощью
create_callback()
(эта функция разработана на неделе 2). - Вызовите функцию
fit()
. - Верните модель.
Мы пишем 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
Теперь мы готовы визуализировать все как есть:
- Ярлыки прогнозов.
- Ярлык проверки.
- Проверочные изображения.
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-ю неделю - обучение нашей модели на полном наборе данных.
Я очень рад, что дошел так далеко, и осталось всего несколько шагов, чтобы добраться до вершины горы. Я достаточно уверен, что смогу закончить работу вовремя и увидеть, как мой проект «Кошка против собаки» очень скоро воплотится в жизнь!