Commit 065c8858 authored by HMKS Herath's avatar HMKS Herath

add flask API to model

parent 469f315c
Pipeline #1933 failed with stages
.idea/
.vscode/
test/
\ No newline at end of file
upload/*
# Created by https://www.gitignore.io/api/macos,linux,django,python,pycharm
### Django ###
*.log
*.pot
*.pyc
__pycache__/
local_settings.py
db.sqlite3
media
### Linux ###
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
### macOS ###
*.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### PyCharm ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff:
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/dictionaries
# Sensitive or high-churn files:
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.xml
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
# Gradle:
.idea/**/gradle.xml
.idea/**/libraries
# CMake
cmake-build-debug/
# Mongo Explorer plugin:
.idea/**/mongoSettings.xml
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### PyCharm Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
# .idea/misc.xml
# *.ipr
# Sonarlint plugin
.idea/sonarlint
### Python ###
# Byte-compiled / optimized / DLL files
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/
# Translations
*.mo
# Django stuff:
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# dotenv
.env
# virtualenv
.venv
venv/
ENV/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
\ No newline at end of file
# Dog breed classifier
## Intorudction
This model is developed on top of the inception v3 pre-trained model. Using transfer learning, the model has further enhanced. To train the model, the Stanford data set has been used which consists of 20000+ images from 120 different dog breeds. Model is connected with the Flask (python micro-framework for web) server which allows API consumers to request "dog breed" predictions via JSON based API. Server accepts both image and video media types.
### Request
```
curl --location --request POST '{base_url}/predict' \
--form 'file=@/path/to/file'
```
### Response
```
{
"code_name": "N02086240-Shih-Tzu",
"image": "90d00cda8e414e299f8aec70a77d6cb8.jpg",
"name": "Shih-Tzu",
"probability": "0.94594604"
}
```
## Installation
This guide is using conda to setup the enviroment.
1. Create an enviroment
```conda create -n dog-breed python=3.6```
2. Activate created enviroment
```conda activate dog-breed```
3. Install dependencies
```pip install -r requirment.txt```
4. Run server
```python app.py```
import numpy as np
from keras.applications.inception_v3 import preprocess_input
from pathlib import Path
import math
import uuid
from werkzeug.utils import secure_filename
from flask import Flask, request, jsonify
import mimetypes
import model.imagegenerator as im
import cv2
import tensorflow_hub as hub
import os
import model.load_model as lm
import predictor as pd
global hub
global model, graph
# global variables
feature_extractor_url = 'https://tfhub.dev/google/imagenet/inception_v3/feature_vector/3'
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
script_location = Path(__file__).absolute().parent
app = Flask(__name__, static_folder='upload')
app.config.from_mapping(
SECRET_KEY='dev',
DATABASE=os.path.join(app.instance_path, 'dog-breed.sqlite'),
)
app.config['UPLOAD_FOLDER'] = script_location / 'upload'
# load model
model, graph = lm.ModelInitializer()
def get_file_type(filename):
mimetypes.init()
mimestart = mimetypes.guess_type(filename)[0]
return mimestart
def save_image(frame):
filename = secure_filename('{}.{}'.format(uuid.uuid4().hex, 'jpg'))
filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
cv2.imwrite(filepath, frame)
return filename
def predict_from_video(pred_target):
cap = cv2.VideoCapture(pred_target)
# 5 == parameter select frame rate of video source
frameRate = cap.get(5)
# predict dog in each frame
results = []
i = 1
while(cap.isOpened()):
frameId = cap.get(1) # current frame number
ret, frame = cap.read()
if (ret != True):
break
if (frameId % math.floor(frameRate) == 0):
i += i
img_tensor = im.InputImageGeneratorVideo(frame)
prediction = pd.Predict(img_tensor, model, graph)
prediction['frame'] = frame
results.append(prediction)
cap.release()
# get breed which has maximum probability of the list of results
predicted_breed = max(results, key=lambda x: x['probability'])
# add saved image name
predicted_breed['image'] = save_image(predicted_breed['frame'])
# remove frame from the dict
del predicted_breed['frame']
return predicted_breed
def predict_from_image(pred_target):
img_tensor = im.InputImageGeneratorImage(pred_target)
prediction = pd.Predict(img_tensor, model, graph)
return prediction
# index endpoint, can use to check server status
@app.route('/', methods=['GET', 'POST'])
def hello():
return ("Server is running!")
@app.route('/predict', methods=['POST'])
def get_breed_from_image():
# check if the post request has the file part
if 'file' not in request.files:
return jsonify(dict({'message': 'No file attached to the request.'}))
# uploaded file
file = request.files['file']
# if user does not select file, browser also submit an empty part without filename
if file.filename == '':
return jsonify(dict({'message': 'No selected file.'}))
# check file type
mime = get_file_type(file.filename)
filetype, extension = mime.split('/')
if str(filetype) not in ('image', 'video'):
return jsonify(dict({'message': 'File type is not allowed'}))
# create new filename
filename = secure_filename('{}.{}'.format(uuid.uuid4().hex, extension))
# save video in tempory folder
filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(filepath)
# predict base on the type of file
result = {}
if filetype == 'video':
result = predict_from_video(filepath)
# delete video file since we don't need it anymore
os.remove(filepath)
else:
result = predict_from_image(filepath)
# add filename of image to result
result['image'] = filename
return jsonify(result)
if __name__ == "__main__":
app.run(debug=True)
File deleted
{"class_name": "Sequential", "config": {"name": "sequential", "layers": [{"class_name": "Lambda", "config": {"name": "lambda", "trainable": false, "batch_input_shape": [null, 299, 299, 3], "dtype": "float32", "function": ["4wEAAAAAAAAAAgAAAAIAAABDAAAAcxIAAAB0AGoBdAKDAX0BfAF8AIMBUwApAU4pA9oDaHVi2gZN\nb2R1bGXaFWZlYXR1cmVfZXh0cmFjdG9yX3VybCkC2gF42hhmZWF0dXJlX2V4dHJhY3Rvcl9tb2R1\nbGWpAHIGAAAA+h48aXB5dGhvbi1pbnB1dC05LTI3YzBmOGE2OWI0MD7aEWZlYXR1cmVfZXh0cmFj\ndG9yAQAAAHMEAAAAAAEKAQ==\n", null, null], "module": "__main__", "function_type": "lambda", "output_shape": null, "output_shape_type": "raw", "output_shape_module": null, "arguments": {}}}, {"class_name": "Dense", "config": {"name": "dense", "trainable": true, "dtype": "float32", "units": 120, "activation": "softmax", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null, "dtype": "float32"}}, "bias_initializer": {"class_name": "Zeros", "config": {"dtype": "float32"}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}]}, "keras_version": "2.2.4-tf", "backend": "tensorflow"}
\ No newline at end of file
from tensorflow import keras
import tensorflow.keras.backend as K
def ModelInitializer():
import tensorflow as tf
import tensorflow_hub as hub
#Inception model's bottom layer as feature extractor.
# Inception model's bottom layer as feature extractor.
feature_extractor_url = 'https://tfhub.dev/google/imagenet/inception_v3/feature_vector/3'
#Loading the trained dog classification model
# Loading the trained dog classification model
model = tf.contrib.saved_model.load_keras_model('saved_model')
model.summary()
#Variables Intialization
# Variables Intialization
sess = K.get_session()
init = tf.global_variables_initializer()
sess.run(init)
#Loading trained weights
# Loading trained weights
model.load_weights('saved_model/model.h5')
#Compiling the model
# Compiling the model
model.compile(
optimizer=tf.train.AdamOptimizer(),
loss='categorical_crossentropy',
......@@ -23,4 +24,4 @@ def ModelInitializer():
)
graph = tf.get_default_graph()
return model , graph
return model, graph
import os
import argparse
import model.load_model as lm
import predictor as pd
global hub
import tensorflow_hub as hub
global model , graph
import cv2
import model.imagegenerator as im
import mimetypes
mimetypes.init()
feature_extractor_url = 'https://tfhub.dev/google/imagenet/inception_v3/feature_vector/3'
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
parser = argparse.ArgumentParser(description='Input local image path.')
parser.add_argument('-i', metavar='--image', type=str, help='Relative path or absolute path of image.')
# Load model
model , graph = lm.ModelInitializer()
def main():
args = parser.parse_args()
if args.i:
mimestart = mimetypes.guess_type(args.i)[0]
if 'video' in mimestart:
predict_from_video(args.i)
elif 'image' in mimestart:
predict_from_image(args.i)
else:
print("Please enter a valid image or video path")
else:
print("Please enter image path.")
# Opens the video file
#cap = cv2.VideoCapture(r"C:\Users\kumudu\Documents\sliit\research\backup\Dog-Breed-Classifier\test\Sad_Dog.mp4")
def predict_from_video(pred_target):
i = 0
cap = cv2.VideoCapture(pred_target)
while(cap.isOpened()):
ret, frame = cap.read()
if ret == False:
break
img_tensor = im.InputImageGeneratorVideo(frame)
prediction = pd.Predict(img_tensor , model , graph)
print("This is a " + str(prediction))
if prediction:
break
cap.release()
cv2.destroyAllWindows()
def predict_from_image(pred_target):
img_tensor = im.InputImageGeneratorImage(pred_target)
prediction = pd.Predict(img_tensor , model , graph)
print("This is a " + str(prediction))
main()
\ No newline at end of file
import logging, os
import model.imagegenerator as im
import model.formatter as ft
from model.labels import label_names
from tensorflow.keras.preprocessing import image
import tensorflow.keras.backend as K
from tensorflow import keras
import tensorflow as tf
import numpy as np
import logging
import os
from keras.applications.inception_v3 import preprocess_input
logging.disable(logging.WARNING)
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3"
import numpy as np
import tensorflow as tf
from tensorflow import keras
import tensorflow.keras.backend as K
from tensorflow.keras.preprocessing import image
from model.labels import label_names
import model.formatter as ft
import model.imagegenerator as im
def Predict(img_tensor , model , graph1):
def Predict(img_tensor, model, graph1):
with tf.Session(graph=graph1) as sess:
init = tf.global_variables_initializer()
sess.run(init)
......@@ -20,5 +22,5 @@ def Predict(img_tensor , model , graph1):
labels = label_names[np.argmax(result, axis=-1)]
unformatted_prediction = labels[0]
prediction = ft.formatString(unformatted_prediction)
return prediction
probability = max(result[0])
return {'name': prediction, 'probability': str(probability), 'code_name': unformatted_prediction}
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "b37C239lFK3q"
},
"source": [
"**DOG BREED CLASSIFICATION**\n",
"\n",
"This is a dog breed classification script which makes use of Transfer learning. A pre-trained Inception V3 is used as a feature extractor and the fully connected layers have been swapped with the custom dog breed classes.\n",
"\n",
"The Stanford Dog Dataset is used, which contains 120 breeds of dog and has more than 20000 images.\n",
"\n",
"Dataset Reference\n",
"Primary:\n",
" Aditya Khosla, Nityananda Jayadevaprakash, Bangpeng Yao and Li Fei-Fei. Novel dataset for Fine-Grained Image Categorization. First Workshop on Fine-Grained Visual Categorization (FGVC), IEEE Conference on Computer Vision and Pattern Recognition (CVPR), 2011. [pdf] [poster] [BibTex]\n",
"\n",
"Secondary:\n",
" J. Deng, W. Dong, R. Socher, L.-J. Li, K. Li and L. Fei-Fei, ImageNet: A Large-Scale Hierarchical Image Database. IEEE Computer Vision and Pattern Recognition (CVPR), 2009. [pdf] [BibTex]"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"colab": {},
"colab_type": "code",
"id": "YHU1UZF4el76"
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"twisted 18.7.0 requires PyHamcrest>=1.9.0, which is not installed.\n",
"You are using pip version 10.0.1, however version 19.1.1 is available.\n",
"You should consider upgrading via the 'python -m pip install --upgrade pip' command.\n"
]
}
],
"source": [
"!pip install -q tensorflow_hub"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "tpjscK4gGszh"
},
"source": [
"All the necessary imports."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 50
},
"colab_type": "code",
"id": "xDkmPkKrTaAq",
"outputId": "0ca03961-4d45-4322-ecaf-97e55aef2910"
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"WARNING: Logging before flag parsing goes to stderr.\n",
"W0528 21:46:48.592976 16236 __init__.py:56] Some hub symbols are not available because TensorFlow version is less than 1.14\n"
]
}
],
"source": [
"import matplotlib.pyplot as plt\n",
"import tensorflow as tf\n",
"import tensorflow_hub as hub\n",
"import tensorflow.keras.layers as layers\n",
"import os"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"colab_type": "code",
"id": "kCebdjjsTpoR",
"outputId": "3ab45542-0c11-4987-aaf2-73463750321c"
},
"outputs": [
{
"data": {
"text/plain": [
"'1.13.1'"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tf.VERSION\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "hVr7zpFEGwwu"
},
"source": [
"The compressed image file is downloaded from 'http://vision.stanford.edu/aditya86/ImageNetDogs/images.tar ' and decompressed into keras' cache folder.\n",
"\n",
"The get_file() function of the keras.utils returns the file path which is stored in data_root."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 50
},
"colab_type": "code",
"id": "6DX_6-gATwO2",
"outputId": "4e86327c-47af-48c1-8732-4df4745c941f"
},
"outputs": [],
"source": [
"data_root = tf.keras.utils.get_file('Images' , 'http://vision.stanford.edu/aditya86/ImageNetDogs/images.tar' , untar=True)"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "oUT2HqbmHSPG"
},
"source": [
"Confirming the directory."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"colab_type": "code",
"id": "7MekN6c1UV5U",
"outputId": "ccbbd7de-88ef-426a-d230-bff9fb7e3512"
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"'ls' is not recognized as an internal or external command,\n",
"operable program or batch file.\n"
]
}
],
"source": [
"!ls /root/.keras/datasets/\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "eqEZoxlYHWWr"
},
"source": [
"The bottom pre-trained weight vectors of Inception model is downloaded from tfhub.\n",
"Link:- \"https://tfhub.dev/google/imagenet/inception_v3/feature_vector/3 \""
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"colab": {},
"colab_type": "code",
"id": "8GdQmCnEbYB4"
},
"outputs": [],
"source": [
"feature_extractor_url = \"https://tfhub.dev/google/imagenet/inception_v3/feature_vector/3\""
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "cIQqzDwwHsAQ"
},
"source": [
"Creating the module and getting the image size on which the Inception model was trained."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"colab_type": "code",
"id": "qDU7tesGbyV3",
"outputId": "6687ccb1-a908-40f4-b096-7570793ec9b1"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"WARNING:tensorflow:From C:\\Users\\ajax9\\Anaconda3\\lib\\site-packages\\tensorflow\\python\\ops\\control_flow_ops.py:3632: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.\n",
"Instructions for updating:\n",
"Colocations handled automatically by placer.\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"W0528 21:47:51.282402 16236 deprecation.py:323] From C:\\Users\\ajax9\\Anaconda3\\lib\\site-packages\\tensorflow\\python\\ops\\control_flow_ops.py:3632: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.\n",
"Instructions for updating:\n",
"Colocations handled automatically by placer.\n"
]
},
{
"data": {
"text/plain": [
"[299, 299]"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def feature_extractor(x):\n",
" feature_extractor_module = hub.Module(feature_extractor_url)\n",
" return feature_extractor_module(x)\n",
"\n",
"IMAGE_SIZE = hub.get_expected_image_size(hub.Module(feature_extractor_url))\n",
"\n",
"IMAGE_SIZE"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "USsXTZBRH-rW"
},
"source": [
"Image generator to pre-process the images and scale them so that the data is in range [0, 1]"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"colab": {},
"colab_type": "code",
"id": "LumN7476IQd_"
},
"outputs": [],
"source": [
"image_generator = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1/255)"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "PGYrVVZHIxjB"
},
"source": [
"All the images in the diectory are rescaled to the image size accepted by Inception model.\n",
"The resulting object is an iterator which returns image and label batch pairs."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"colab_type": "code",
"id": "j4xm3vUJcND3",
"outputId": "4dee5df9-5524-4358-ed9a-0a0f39b234cc"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Found 16835 images belonging to 99 classes.\n"
]
}
],
"source": [
"image_data = image_generator.flow_from_directory(str(data_root) , target_size = IMAGE_SIZE)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 50
},
"colab_type": "code",
"id": "odb6jDpacicr",
"outputId": "061be4f1-d942-4ab3-eec1-6dc7f2a51683"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(32, 299, 299, 3)\n",
"(32, 99)\n"
]
}
],
"source": [
"for img , lab in image_data:\n",
" print(img.shape)\n",
" print(lab.shape)\n",
" break"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "6brRaZyQJMvM"
},
"source": [
"Wrapping the layers in a keras layer"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"colab": {},
"colab_type": "code",
"id": "HlxnT_bCc0QP"
},
"outputs": [],
"source": [
"feature_extractor_layer = layers.Lambda(feature_extractor , input_shape = IMAGE_SIZE + [3])"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "OzqJKINSJYrO"
},
"source": [
"Freezing the bottom layers so that they arent trained again and only the new custom layer is trained."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"colab": {},
"colab_type": "code",
"id": "m9xe5TWddJYi"
},
"outputs": [],
"source": [
"feature_extractor_layer.trainable = False"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "txS_C308JiB5"
},
"source": [
"Building the custom model with feature extracting layer of Inception on top of custom layer with softmax activation."
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 235
},
"colab_type": "code",
"id": "Dx-zBcHVdPC_",
"outputId": "a9412a28-1baf-4b17-c65d-af2a427312b8"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"INFO:tensorflow:Saver not created because there are no variables in the graph to restore\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"I0528 21:48:16.831165 16236 saver.py:1483] Saver not created because there are no variables in the graph to restore\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"_________________________________________________________________\n",
"Layer (type) Output Shape Param # \n",
"=================================================================\n",
"lambda (Lambda) (None, 2048) 0 \n",
"_________________________________________________________________\n",
"dense (Dense) (None, 99) 202851 \n",
"=================================================================\n",
"Total params: 202,851\n",
"Trainable params: 202,851\n",
"Non-trainable params: 0\n",
"_________________________________________________________________\n"
]
}
],
"source": [
"model = tf.keras.Sequential([\n",
" feature_extractor_layer,\n",
" layers.Dense(image_data.num_classes , activation = \"softmax\")\n",
"])\n",
"\n",
"model.summary()"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "9IoAjM3YJ3Fz"
},
"source": [
"Initializing the tfHub module."
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"colab": {},
"colab_type": "code",
"id": "5aUhinbqdxsU"
},
"outputs": [],
"source": [
"import tensorflow.keras.backend as K\n",
"sess = K.get_session()\n",
"init = tf.global_variables_initializer()\n",
"sess.run(init)"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "yykMyglrJ608"
},
"source": [
"Confirming the resultant shape"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"colab_type": "code",
"id": "3Sx8LmKGeWnb",
"outputId": "b7a9e700-aec8-444d-849c-ef0a02570b26"
},
"outputs": [
{
"data": {
"text/plain": [
"(32, 99)"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"result = model.predict(img)\n",
"result.shape"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "ThMl-dTVKBwF"
},
"source": [
"Configuring the training process. \n",
"\n",
"\n",
"* Using Adam optimizer to optimize the output to maximum accuracy\n",
"* Loss as 'categorical crossentropy' as, multiclass classifiction\n",
"* Metrics as accuracy\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"colab": {},
"colab_type": "code",
"id": "07EnaO1zfWKC"
},
"outputs": [],
"source": [
"model.compile(\n",
" optimizer=tf.train.AdamOptimizer(),\n",
" loss='categorical_crossentropy',\n",
" metrics=['accuracy']\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "hiQibacJKnPO"
},
"source": [
"To visualize the training progress during every epoch, a custom callback to log the loss and accuract of each batch"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"colab": {},
"colab_type": "code",
"id": "P8Mtn6Qpf8cr"
},
"outputs": [],
"source": [
"class CollectBatchStats(tf.keras.callbacks.Callback):\n",
" def __init__(self):\n",
" self.batch_losses = []\n",
" self.batch_acc = []\n",
" \n",
" def on_batch_end(self , batch , logs = None):\n",
" self.batch_losses.append(logs['loss'])\n",
" self.batch_acc.append(logs['acc'])\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"colab_type": "code",
"id": "tzGzbiLoh0XA",
"outputId": "0a56c57c-7c70-4002-fe69-35e65b100256"
},
"outputs": [
{
"data": {
"text/plain": [
"526"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"steps = image_data.samples//image_data.batch_size\n",
"steps"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "3AgNAjUCK9GF"
},
"source": [
"Training the model for 5 epochs."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 322
},
"colab_type": "code",
"id": "apyo6jPJhoD0",
"outputId": "bd9ff985-3335-4945-f9d0-5f999f403c34"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"WARNING:tensorflow:From C:\\Users\\ajax9\\Anaconda3\\lib\\site-packages\\tensorflow\\python\\ops\\math_ops.py:3066: to_int32 (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version.\n",
"Instructions for updating:\n",
"Use tf.cast instead.\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"W0528 21:48:36.506582 16236 deprecation.py:323] From C:\\Users\\ajax9\\Anaconda3\\lib\\site-packages\\tensorflow\\python\\ops\\math_ops.py:3066: to_int32 (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version.\n",
"Instructions for updating:\n",
"Use tf.cast instead.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 1/5\n",
"526/526 [==============================] - 3160s 6s/step - loss: 0.6953 - acc: 0.8397\n",
"Epoch 2/5\n",
"526/526 [==============================] - 3020s 6s/step - loss: 0.2549 - acc: 0.9168\n",
"Epoch 3/5\n",
"202/526 [==========>...................] - ETA: 14:20:44 - loss: 0.1891 - acc: 0.9386"
]
}
],
"source": [
"batch_stats = CollectBatchStats()\n",
"\n",
"model.fit(\n",
" (items for items in image_data),\n",
" epochs = 5,\n",
" steps_per_epoch = steps,\n",
" callbacks = [batch_stats]\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "1ItdX9cLLCT6"
},
"source": [
"Plotting the loss and accuracy in every training step."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 566
},
"colab_type": "code",
"id": "guVibGTZiopC",
"outputId": "08d621a2-5b78-4d3d-aacc-779203c898ba"
},
"outputs": [],
"source": [
"plt.figure()\n",
"plt.ylabel(\"Loss\")\n",
"plt.xlabel(\"Training Steps\")\n",
"plt.ylim([0,2])\n",
"plt.plot(batch_stats.batch_losses)\n",
"\n",
"plt.figure()\n",
"plt.ylabel(\"Accuracy\")\n",
"plt.xlabel(\"Training Steps\")\n",
"plt.ylim([0,1])\n",
"plt.plot(batch_stats.batch_acc)"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "CewM-3WtLI4W"
},
"source": [
"Ordering the class names."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"colab_type": "code",
"id": "b7pHwh535vBO",
"outputId": "40345274-d09f-4b0e-f67e-e33c10aa6d7c"
},
"outputs": [],
"source": [
"import numpy as np\n",
"\n",
"label_names = sorted(image_data.class_indices.items(), key=lambda pair:pair[1])\n",
"label_names = np.array([key.title() for key, value in label_names])\n",
"label_names.shape\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "FAqjXjAdLV8d"
},
"source": [
"Formatting the string to get only the breed name, omitting everything efore the ' - '."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {},
"colab_type": "code",
"id": "pwyAXc6cCtsZ"
},
"outputs": [],
"source": [
"def formatString(x):\n",
" i = x.find('-')\n",
" return x[i+1:]\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "BlIREMWOLhfk"
},
"source": [
"Predicting breeds of input images."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"colab_type": "code",
"id": "R4MmarkQ59Cv",
"outputId": "ccccbf93-8f81-4333-cfe4-bbe7f9a84d1e"
},
"outputs": [],
"source": [
"from keras.preprocessing import image\n",
"image1 = image.load_img('thumbnail-1477089693232.jpg' , target_size=IMAGE_SIZE)\n",
"img_tensor = image.img_to_array(image1)\n",
"img_tensor = np.expand_dims(img_tensor , axis=0)\n",
"img_tensor /= 255.\n",
"\n",
"result_batch = model.predict(img_tensor)\n",
"\n",
"labels_batch = label_names[np.argmax(result_batch, axis=-1)]\n",
"unformatted_prediction = labels_batch[0]\n",
"prediction = formatString(unformatted_prediction)\n",
"prediction"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 356
},
"colab_type": "code",
"id": "S28nvGUd6Lbh",
"outputId": "ac1bc51d-d6f1-4948-d8e7-95ee098a9a75"
},
"outputs": [],
"source": [
"plt.figure(figsize=(5,5))\n",
"\n",
"#plt.subplot(6,5,1)\n",
"plt.imshow(img_tensor[0])\n",
"plt.title(formatString(labels_batch[0]))\n",
"plt.axis('off')\n",
"_ = plt.suptitle(\"Model predictions\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {},
"colab_type": "code",
"id": "d6UsLnde6V1h"
},
"outputs": [],
"source": []
}
],
"metadata": {
"accelerator": "GPU",
"colab": {
"collapsed_sections": [],
"name": "dog_breed_classification.ipynb",
"provenance": [],
"version": "0.3.2"
},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
}
},
"nbformat": 4,
"nbformat_minor": 1
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment