#Imports here
#%matplotlib inline 
#%config InlineBackend.figure_format = 'retina'
import matplotlib.pyplot as plt
import torch
import numpy as np
from torch import nn
from torch import optim
from torchvision import datasets, models, transforms
import torch.nn.functional as F
import torch.utils.data 
import pandas as pd
#import helper
from collections import OrderedDict
from PIL import Image
import seaborn as sns
import json 
   
    
   
    
with open('cat_to_name.json', 'r') as f:
    cat_to_name = json.load(f)
    
len (cat_to_name)
cat_to_name

# TODO: Write a function that loads a checkpoint and rebuilds the model

def loading_model (file_path):
    checkpoint = torch.load (file_path) #loading checkpoint from a file
    model = models.alexnet (pretrained = True) #function works solely for Alexnet
    #you can use the arch from the checkpoint and choose the model architecture in a more generic way:
    #model = getattr(models, checkpoint['arch']
        
    model.classifier = checkpoint ['classifier']
    model.load_state_dict (checkpoint ['state_dict'])
    model.class_to_idx = checkpoint ['mapping']
    
    for param in model.parameters(): 
        param.requires_grad = False #turning off tuning of the model
    
    return model


#Now let's test if we did everything in correct way.

model_verify = loading_model ('project_checkpoint.pth')
model_verify

def process_image(image):
    ''' Scales, crops, and normalizes a PIL image for a PyTorch model,
        returns an Numpy array
    '''
    #size = 256, 256
    im = Image.open (image) #loading image
    width, height = im.size #original size
    #proportion = width/ float (height) #to keep aspect ratio
    
    if width > height: 
        height = 256
        im.thumbnail ((50000, height), Image.ANTIALIAS)
    else: 
        width = 256
        im.thumbnail ((width,50000), Image.ANTIALIAS)
        
    
    width, height = im.size #new size of im
    #crop 224x224 in the center
    reduce = 224
    left = (width - reduce)/2 
    top = (height - reduce)/2
    right = left + 224 
    bottom = top + 224
    im = im.crop ((left, top, right, bottom))
    
    #preparing numpy array
    np_image = np.array (im)/255 #to make values from 0 to 1
    np_image -= np.array ([0.485, 0.456, 0.406]) 
    np_image /= np.array ([0.229, 0.224, 0.225])
    
    np_image= np_image.transpose ((2,0,1))
    #np_image.transpose (1,2,0)
    return np_image
    
    # TODO: Process a PIL image for use in a PyTorch model
    
def imshow(image, ax=None, title=None):
    if ax is None:
        fig, ax = plt.subplots()
    
    # PyTorch tensors assume the color channel is the first dimension
    # but matplotlib assumes is the third dimension
    image = np.array (image)
    image = image.transpose((1, 2, 0))
    
    # Undo preprocessing
    mean = np.array([0.485, 0.456, 0.406])
    std = np.array([0.229, 0.224, 0.225])
    image = std * image + mean
    #image = np.multiply (std, image) + mean
    
    # Image needs to be clipped between 0 and 1 or it looks like noise when displayed
    image = np.clip(image, 0, 1)
    
    ax.imshow(image)
    
    return ax

#(np.array([0.229, 0.224, 0.225])).shape
#img = img.transpose ((1,2,0))
#img


#mapping = train_image_datasets.class_to_idx

#indeces = np.array ([1, 10, 100, 101, 102])
#classes = pd.DataFrame ([mapping [item] for item in indeces]) #replacing indeces with classes
#classes = np.array (classes) #converting to Numpy array 

def predict(image_path, model, topkl):
    ''' Predict the class (or classes) of an image using a trained deep learning model.
    '''
    # TODO: Implement the code to predict the class from an image file
    image = process_image (image_path) #loading image and processing it using above defined function
    
    #we cannot pass image to model.forward 'as is' as it is expecting tensor, not numpy array
    #converting to tensor
    im = torch.from_numpy (image).type (torch.FloatTensor)
    
    im = im.unsqueeze (dim = 0) #used to make size of torch as expected. as forward method is working with batches,
    #doing that we will have batch size = 1 
        
    with torch.no_grad ():
        output = model.forward (im)
    output_prob = torch.exp (output) #converting into a probability
    
    probs, indeces = output_prob.topk (topkl)
    probs = probs.numpy () #converting both to numpy array
    indeces = indeces.numpy () 
    
    probs = probs.tolist () [0] #converting both to list
    indeces = indeces.tolist () [0]
    
    
    mapping = {val: key for key, val in
                model.class_to_idx.items()
                }
    
    classes = [mapping [item] for item in indeces]
    #classes = pd.DataFrame ([mapping [item] for item in indeces]) #replacing indeces with classes
    classes = np.array (classes) #converting to Numpy array 
    
    return probs, classes


0bc8032527743b74a1565ebc9603d2d547f84b6e
<mask token>


def process_image(image):
    """ Scales, crops, and normalizes a PIL image for a PyTorch model,
        returns an Numpy array
    """
    im = Image.open(image)
    width, height = im.size
    if width > height:
        height = 256
        im.thumbnail((50000, height), Image.ANTIALIAS)
    else:
        width = 256
        im.thumbnail((width, 50000), Image.ANTIALIAS)
    width, height = im.size
    reduce = 224
    left = (width - reduce) / 2
    top = (height - reduce) / 2
    right = left + 224
    bottom = top + 224
    im = im.crop((left, top, right, bottom))
    np_image = np.array(im) / 255
    np_image -= np.array([0.485, 0.456, 0.406])
    np_image /= np.array([0.229, 0.224, 0.225])
    np_image = np_image.transpose((2, 0, 1))
    return np_image


def imshow(image, ax=None, title=None):
    if ax is None:
        fig, ax = plt.subplots()
    image = np.array(image)
    image = image.transpose((1, 2, 0))
    mean = np.array([0.485, 0.456, 0.406])
    std = np.array([0.229, 0.224, 0.225])
    image = std * image + mean
    image = np.clip(image, 0, 1)
    ax.imshow(image)
    return ax


<mask token>

<mask token>


def process_image(image):
    """ Scales, crops, and normalizes a PIL image for a PyTorch model,
        returns an Numpy array
    """
    im = Image.open(image)
    width, height = im.size
    if width > height:
        height = 256
        im.thumbnail((50000, height), Image.ANTIALIAS)
    else:
        width = 256
        im.thumbnail((width, 50000), Image.ANTIALIAS)
    width, height = im.size
    reduce = 224
    left = (width - reduce) / 2
    top = (height - reduce) / 2
    right = left + 224
    bottom = top + 224
    im = im.crop((left, top, right, bottom))
    np_image = np.array(im) / 255
    np_image -= np.array([0.485, 0.456, 0.406])
    np_image /= np.array([0.229, 0.224, 0.225])
    np_image = np_image.transpose((2, 0, 1))
    return np_image


def imshow(image, ax=None, title=None):
    if ax is None:
        fig, ax = plt.subplots()
    image = np.array(image)
    image = image.transpose((1, 2, 0))
    mean = np.array([0.485, 0.456, 0.406])
    std = np.array([0.229, 0.224, 0.225])
    image = std * image + mean
    image = np.clip(image, 0, 1)
    ax.imshow(image)
    return ax


def predict(image_path, model, topkl):
    """ Predict the class (or classes) of an image using a trained deep learning model.
    """
    image = process_image(image_path)
    im = torch.from_numpy(image).type(torch.FloatTensor)
    im = im.unsqueeze(dim=0)
    with torch.no_grad():
        output = model.forward(im)
    output_prob = torch.exp(output)
    probs, indeces = output_prob.topk(topkl)
    probs = probs.numpy()
    indeces = indeces.numpy()
    probs = probs.tolist()[0]
    indeces = indeces.tolist()[0]
    mapping = {val: key for key, val in model.class_to_idx.items()}
    classes = [mapping[item] for item in indeces]
    classes = np.array(classes)
    return probs, classes

<mask token>


def loading_model(file_path):
    checkpoint = torch.load(file_path)
    model = models.alexnet(pretrained=True)
    model.classifier = checkpoint['classifier']
    model.load_state_dict(checkpoint['state_dict'])
    model.class_to_idx = checkpoint['mapping']
    for param in model.parameters():
        param.requires_grad = False
    return model


<mask token>


def process_image(image):
    """ Scales, crops, and normalizes a PIL image for a PyTorch model,
        returns an Numpy array
    """
    im = Image.open(image)
    width, height = im.size
    if width > height:
        height = 256
        im.thumbnail((50000, height), Image.ANTIALIAS)
    else:
        width = 256
        im.thumbnail((width, 50000), Image.ANTIALIAS)
    width, height = im.size
    reduce = 224
    left = (width - reduce) / 2
    top = (height - reduce) / 2
    right = left + 224
    bottom = top + 224
    im = im.crop((left, top, right, bottom))
    np_image = np.array(im) / 255
    np_image -= np.array([0.485, 0.456, 0.406])
    np_image /= np.array([0.229, 0.224, 0.225])
    np_image = np_image.transpose((2, 0, 1))
    return np_image


def imshow(image, ax=None, title=None):
    if ax is None:
        fig, ax = plt.subplots()
    image = np.array(image)
    image = image.transpose((1, 2, 0))
    mean = np.array([0.485, 0.456, 0.406])
    std = np.array([0.229, 0.224, 0.225])
    image = std * image + mean
    image = np.clip(image, 0, 1)
    ax.imshow(image)
    return ax


def predict(image_path, model, topkl):
    """ Predict the class (or classes) of an image using a trained deep learning model.
    """
    image = process_image(image_path)
    im = torch.from_numpy(image).type(torch.FloatTensor)
    im = im.unsqueeze(dim=0)
    with torch.no_grad():
        output = model.forward(im)
    output_prob = torch.exp(output)
    probs, indeces = output_prob.topk(topkl)
    probs = probs.numpy()
    indeces = indeces.numpy()
    probs = probs.tolist()[0]
    indeces = indeces.tolist()[0]
    mapping = {val: key for key, val in model.class_to_idx.items()}
    classes = [mapping[item] for item in indeces]
    classes = np.array(classes)
    return probs, classes

<mask token>
with open('cat_to_name.json', 'r') as f:
    cat_to_name = json.load(f)
len(cat_to_name)
cat_to_name


def loading_model(file_path):
    checkpoint = torch.load(file_path)
    model = models.alexnet(pretrained=True)
    model.classifier = checkpoint['classifier']
    model.load_state_dict(checkpoint['state_dict'])
    model.class_to_idx = checkpoint['mapping']
    for param in model.parameters():
        param.requires_grad = False
    return model


<mask token>
model_verify


def process_image(image):
    """ Scales, crops, and normalizes a PIL image for a PyTorch model,
        returns an Numpy array
    """
    im = Image.open(image)
    width, height = im.size
    if width > height:
        height = 256
        im.thumbnail((50000, height), Image.ANTIALIAS)
    else:
        width = 256
        im.thumbnail((width, 50000), Image.ANTIALIAS)
    width, height = im.size
    reduce = 224
    left = (width - reduce) / 2
    top = (height - reduce) / 2
    right = left + 224
    bottom = top + 224
    im = im.crop((left, top, right, bottom))
    np_image = np.array(im) / 255
    np_image -= np.array([0.485, 0.456, 0.406])
    np_image /= np.array([0.229, 0.224, 0.225])
    np_image = np_image.transpose((2, 0, 1))
    return np_image


def imshow(image, ax=None, title=None):
    if ax is None:
        fig, ax = plt.subplots()
    image = np.array(image)
    image = image.transpose((1, 2, 0))
    mean = np.array([0.485, 0.456, 0.406])
    std = np.array([0.229, 0.224, 0.225])
    image = std * image + mean
    image = np.clip(image, 0, 1)
    ax.imshow(image)
    return ax


def predict(image_path, model, topkl):
    """ Predict the class (or classes) of an image using a trained deep learning model.
    """
    image = process_image(image_path)
    im = torch.from_numpy(image).type(torch.FloatTensor)
    im = im.unsqueeze(dim=0)
    with torch.no_grad():
        output = model.forward(im)
    output_prob = torch.exp(output)
    probs, indeces = output_prob.topk(topkl)
    probs = probs.numpy()
    indeces = indeces.numpy()
    probs = probs.tolist()[0]
    indeces = indeces.tolist()[0]
    mapping = {val: key for key, val in model.class_to_idx.items()}
    classes = [mapping[item] for item in indeces]
    classes = np.array(classes)
    return probs, classes

#Imports here
#%matplotlib inline 
#%config InlineBackend.figure_format = 'retina'
import matplotlib.pyplot as plt
import torch
import numpy as np
from torch import nn
from torch import optim
from torchvision import datasets, models, transforms
import torch.nn.functional as F
import torch.utils.data 
import pandas as pd
#import helper
from collections import OrderedDict
from PIL import Image
import seaborn as sns
import json 
   
    
   
    
with open('cat_to_name.json', 'r') as f:
    cat_to_name = json.load(f)
    
len (cat_to_name)
cat_to_name

# TODO: Write a function that loads a checkpoint and rebuilds the model

def loading_model (file_path):
    checkpoint = torch.load (file_path) #loading checkpoint from a file
    model = models.alexnet (pretrained = True) #function works solely for Alexnet
    #you can use the arch from the checkpoint and choose the model architecture in a more generic way:
    #model = getattr(models, checkpoint['arch']
        
    model.classifier = checkpoint ['classifier']
    model.load_state_dict (checkpoint ['state_dict'])
    model.class_to_idx = checkpoint ['mapping']
    
    for param in model.parameters(): 
        param.requires_grad = False #turning off tuning of the model
    
    return model


#Now let's test if we did everything in correct way.

model_verify = loading_model ('project_checkpoint.pth')
model_verify

def process_image(image):
    ''' Scales, crops, and normalizes a PIL image for a PyTorch model,
        returns an Numpy array
    '''
    #size = 256, 256
    im = Image.open (image) #loading image
    width, height = im.size #original size
    #proportion = width/ float (height) #to keep aspect ratio
    
    if width > height: 
        height = 256
        im.thumbnail ((50000, height), Image.ANTIALIAS)
    else: 
        width = 256
        im.thumbnail ((width,50000), Image.ANTIALIAS)
        
    
    width, height = im.size #new size of im
    #crop 224x224 in the center
    reduce = 224
    left = (width - reduce)/2 
    top = (height - reduce)/2
    right = left + 224 
    bottom = top + 224
    im = im.crop ((left, top, right, bottom))
    
    #preparing numpy array
    np_image = np.array (im)/255 #to make values from 0 to 1
    np_image -= np.array ([0.485, 0.456, 0.406]) 
    np_image /= np.array ([0.229, 0.224, 0.225])
    
    np_image= np_image.transpose ((2,0,1))
    #np_image.transpose (1,2,0)
    return np_image
    
    # TODO: Process a PIL image for use in a PyTorch model
    
def imshow(image, ax=None, title=None):
    if ax is None:
        fig, ax = plt.subplots()
    
    # PyTorch tensors assume the color channel is the first dimension
    # but matplotlib assumes is the third dimension
    image = np.array (image)
    image = image.transpose((1, 2, 0))
    
    # Undo preprocessing
    mean = np.array([0.485, 0.456, 0.406])
    std = np.array([0.229, 0.224, 0.225])
    image = std * image + mean
    #image = np.multiply (std, image) + mean
    
    # Image needs to be clipped between 0 and 1 or it looks like noise when displayed
    image = np.clip(image, 0, 1)
    
    ax.imshow(image)
    
    return ax

#(np.array([0.229, 0.224, 0.225])).shape
#img = img.transpose ((1,2,0))
#img


#mapping = train_image_datasets.class_to_idx

#indeces = np.array ([1, 10, 100, 101, 102])
#classes = pd.DataFrame ([mapping [item] for item in indeces]) #replacing indeces with classes
#classes = np.array (classes) #converting to Numpy array 

def predict(image_path, model, topkl):
    ''' Predict the class (or classes) of an image using a trained deep learning model.
    '''
    # TODO: Implement the code to predict the class from an image file
    image = process_image (image_path) #loading image and processing it using above defined function
    
    #we cannot pass image to model.forward 'as is' as it is expecting tensor, not numpy array
    #converting to tensor
    im = torch.from_numpy (image).type (torch.FloatTensor)
    
    im = im.unsqueeze (dim = 0) #used to make size of torch as expected. as forward method is working with batches,
    #doing that we will have batch size = 1 
        
    with torch.no_grad ():
        output = model.forward (im)
    output_prob = torch.exp (output) #converting into a probability
    
    probs, indeces = output_prob.topk (topkl)
    probs = probs.numpy () #converting both to numpy array
    indeces = indeces.numpy () 
    
    probs = probs.tolist () [0] #converting both to list
    indeces = indeces.tolist () [0]
    
    
    mapping = {val: key for key, val in
                model.class_to_idx.items()
                }
    
    classes = [mapping [item] for item in indeces]
    #classes = pd.DataFrame ([mapping [item] for item in indeces]) #replacing indeces with classes
    classes = np.array (classes) #converting to Numpy array 
    
    return probs, classes

