Это пост, чтобы поделиться с вами моим первым проектом в области компьютерного зрения.
Программа выполнена в рамках программы Data Scientist Nanodegree «Capstone Project».
Введение проблемы:
Правильно классифицировать породу собаки по ее фотографии и получить наиболее похожую на человека породу собаки, если дана фотография человека.
Стратегия решения проблемы:
мы решим эту проблему, используя сверточные нейронные сети (CNN)
Метрики:
мы будем использовать метрику точности.
EDA :
Прежде всего, нам нужно классифицировать фотографию, если это фотография собаки, которую она обнаружит, и если это фотография человека, она обнаружит ее, и узнать, если это ни то, ни другое.
Итак, мы начнем с создания детектора человеческого лица: я использовал cv2 haarcascade для обнаружения человеческих лиц:
import cv2 import matplotlib.pyplot as plt %matplotlib inline # extract pre-trained face detector face_cascade = cv2.CascadeClassifier('haarcascades/haarcascade_frontalface_alt.xml') # load color (BGR) image img = cv2.imread(human_files[3]) # convert BGR image to grayscale gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
Затем, чтобы построить функцию детектора лица, чтобы она возвращала True, если это было человеческое лицо, и False в противном случае.
# returns "True" if face is detected in image stored at img_path def face_detector(img_path): img = cv2.imread(img_path) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray) return len(faces) > 0
Результаты были приемлемыми:
процент обнаруженных человеческих лиц из человеческих файлов: 100%
процент обнаруженных человеческих лиц из файлов с собаками: 11%
Затем, чтобы построить наш детектор собак: я использовал ResNent50, чтобы определить, была ли это фотография собаки или нет.
from keras.applications.resnet50 import ResNet50 # define ResNet50 model ResNet50_model = ResNet50(weights='imagenet')
Но нам нужно предварительно обработать входные данные, поэтому размер изображения должен быть 224×224.
from keras.preprocessing import image from tqdm import tqdm def path_to_tensor(img_path): # loads RGB image as PIL.Image.Image type img = image.load_img(img_path, target_size=(224, 224)) # convert PIL.Image.Image type to 3D tensor with shape (224, 224, 3) x = image.img_to_array(img) # convert 3D tensor to 4D tensor with shape (1, 224, 224, 3) and return 4D tensor return np.expand_dims(x, axis=0) def paths_to_tensor(img_paths): list_of_tensors = [path_to_tensor(img_path) for img_path in tqdm(img_paths)] return np.vstack(list_of_tensors)
Затем построить всю функцию так, чтобы она возвращала True, если это изображение собаки, и False в противном случае.
Результаты были идеальными:
процент изображений в human_files_short с обнаруженной собакой: 0,0 %
процент изображений в dog_files_short с обнаруженной собакой: 100,0 %
Моделирование и настройка гиперпараметров:
Теперь мы построили наши детекторы, так что пришло время построить наши классификаторы:
Я построил три разные модели:
- one from scratch - one using VGG16 - The last one and the main one used , Was built using transfer learning with ResNet50
Первый, который я построил с нуля:
Я использовал 32–64–128, чтобы захватить как можно больше шаблонов из исходной фотографии. И я использовал функцию активации «relu», потому что она давала лучшую точность, чем другие функции активации, такие как «tanh». Я использовал глобальное среднее объединение в конец, чтобы уменьшить количество параметров. Затем использовал плотный слой со 100 узлами для соединения шаблонов. В конце я добавил плотный слой с количеством существующих классов (133) с softmax.
И я использовал оптимизатор «адам».
from keras.layers import Conv2D, MaxPooling2D, GlobalAveragePooling2D from keras.layers import Dropout, Flatten, Dense from keras.models import Sequential model = Sequential() ### TODO: Define your architecture. model.add(Conv2D(filters=32, kernel_size=2, padding='same', activation='relu', input_shape=(224, 224, 3))) model.add(MaxPooling2D(pool_size=2)) model.add(Conv2D(filters=64, kernel_size=2, padding='same', activation='relu')) model.add(MaxPooling2D(pool_size=2)) model.add(Conv2D(filters=128, kernel_size=2, padding='same', activation='relu')) model.add(GlobalAveragePooling2D()) model.add(Dropout(0.2)) #model.add(Flatten()) model.add(Dense(100, activation='relu')) model.add(Dropout(0.2)) model.add(Dense(133, activation='softmax')) model.summary()
Что касается второго, я использовал VGG16, не добавляя к нему никаких слоев:
VGG16_model = Sequential() VGG16_model.add(GlobalAveragePooling2D(input_shape=train_VGG16.shape[1:])) VGG16_model.add(Dense(133, activation='softmax')) VGG16_model.summary()
В третьей модели и той, что использовалась, я использовал трансферное обучение в ResNet50, добавив поверх него плотный слой.
### TODO: Define your architecture. resnet50_model = Sequential() resnet50_model.add(GlobalAveragePooling2D(input_shape=train_ResNet_50.shape[1:])) resnet50_model.add(Dense(150,activation='relu')) resnet50_model.add(Dropout(0.5)) resnet50_model.add(Dense(133, activation='softmax')) resnet50_model.summary()
Результаты:
Модель, которую я построил с нуля. Точность теста составила 4,426%.
Модель VGG16 имела точность испытаний 41,5072%.
Модель ResNet50, с которой я использовал трансферное обучение, имела точность теста 82,1770%.
Вывод:
После этого все, что осталось, это построить алгоритм, чтобы объединить все это в простую функцию:
Если бы это была человеческая картинка, найди к ней наиболее похожую породу собак,
Если это была фотография собаки, классифицируйте ее.
Если это ни то, ни другое, завершите работу оператором «неверный ввод».
### TODO: Write your algorithm. ### Feel free to use as many code cells as needed. def dog_human_preds(img_path): if(face_detector(img_path)): print('That is a human') img = cv2.imread(img_path) # convert BGR image to RGB for plotting cv_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # display the image, along with bounding box plt.imshow(cv_rgb) plt.show() bottleneck_feature = extract_Resnet50(path_to_tensor(img_path)) # obtain predicted vector predicted_vector = resnet50_model.predict(bottleneck_feature) # return dog breed that is predicted by the model return dog_names[np.argmax(predicted_vector)] if(dog_detector(img_path)): print('That is a dog') img = cv2.imread(img_path) # convert BGR image to RGB for plotting cv_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # display the image, along with bounding box plt.imshow(cv_rgb) plt.show() bottleneck_feature = extract_Resnet50(path_to_tensor(img_path)) # obtain predicted vector predicted_vector = resnet50_model.predict(bottleneck_feature) # return dog breed that is predicted by the model return dog_names[np.argmax(predicted_vector)] img = cv2.imread(img_path) # convert BGR image to grayscale # convert BGR image to RGB for plotting cv_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # display the image, along with bounding box plt.imshow(cv_rgb) plt.show() return 'invalid input,This neither a human nor a dog'
Если мы увидим примеры того, как это работает:
Предсказание породы собаки:
Предсказание наиболее похожей на человека породы собак:
Предсказывая, что это ни собака, ни человек картина:
Возможные улучшения:
1- Использовать детектор лиц, использующий подход глубокого обучения.
2- Чтобы повысить точность модели, которая использовалась, используя лучшую архитектуру, чем использовалась выше.
3- Окончательный алгоритм может предоставить фотографию похожей породы собак, когда на входе будет человек, а не просто название породы.
ВОТ И ВСЕ!!!
Спасибо за чтение .
Буду очень благодарен за любой отзыв от вас!
Ссылка на репо на Github здесь.
Мой LinkedIn здесь.