Hoe een beeldclassificator met een nauwkeurigheid van meer dan 97% te bouwen

Een duidelijke en complete blauwdruk voor succes

Hoe leer je een computer om naar een afbeelding te kijken en deze correct als een bloem te identificeren? Hoe leer je een computer om een ​​afbeelding van een bloem te zien en je vervolgens precies te vertellen wat voor soort bloem het is, zelfs als je niet weet welke soort het is?

Ik zal het je laten zien!

Dit artikel leidt je door de basisbeginselen van het maken van een beeldclassificator met PyTorch. Je kunt je voorstellen zoiets als dit te gebruiken in een telefoon-app die je de naam vertelt van de bloem waarnaar je camera kijkt. Je kunt, als je dat wilt, deze classificator trainen en vervolgens exporteren voor gebruik in een eigen applicatie.

Wat u vanaf hier doet, hangt volledig af van u en uw verbeelding.

Ik heb dit artikel samengesteld voor iedereen die helemaal nieuw is en op zoek is naar een plek om te beginnen. Het is aan jou om deze informatie te nemen, te verbeteren en je eigen te maken!

Als u het notitieboek wilt bekijken, kunt u het hier vinden.

Omdat deze PyTorch-beeldclassificator is gebouwd als een laatste project voor een Udacity-programma, is de code gebaseerd op code uit Udacity die op zijn beurt is gebaseerd op de officiële PyTorch-documentatie. Udacity leverde ook een JSON-bestand voor labelmapping. Dat bestand is te vinden in deze GitHub-repo.

Informatie over de bloemgegevensset is hier te vinden. De gegevensset bevat een afzonderlijke map voor elk van de 102 bloemklassen. Elke bloem is gelabeld als een nummer en elk van de genummerde mappen bevat een aantal JPG-bestanden.

Laten we beginnen!

Foto door Annie Spratt op Unsplash

Omdat dit een neuraal netwerk is dat een grotere gegevensset gebruikt dan mijn CPU in een redelijke hoeveelheid tijd aankan, ging ik door met het instellen van mijn beeldclassificator in Google Colab. Colab is echt geweldig omdat het gratis GPU biedt. (Als u nieuw bent bij Colab, bekijk dan dit artikel over aan de slag met Google Colab!)

Omdat ik Colab gebruikte, moest ik beginnen met het importeren van PyTorch. U hoeft dit niet te doen als u Colab niet gebruikt.

*** BIJWERKEN! (01/29) *** Colab ondersteunt nu native PyTorch !!! U hoeft de onderstaande code niet uit te voeren, maar ik laat het achter voor het geval iemand problemen ondervindt!

# PyTorch importeren als u Google Colab gebruikt
# http://pytorch.org/
van os.path import bestaat
van wheel.pep425tags import get_abbr_impl, get_impl_ver, get_abi_tag
platform = '{} {} - {}'. format (get_abbr_impl (), get_impl_ver (), get_abi_tag ())
cuda_output =! ldconfig -p | grep cudart.so | sed -e's /.* \. \ ([0-9] * \) \. \ ([0-9] * \) $ / cu \ 1 \ 2 /'
accelerator = cuda_output [0] if bestaat ('/ dev / nvidia0') anders 'cpu'
! pip install -q http://download.pytorch.org/whl/{accelerator}/torch-0.4.1-{platform}-linux_x86_64.whl torchvision
fakkel importeren

Toen, na wat problemen met Pillow (het is buggy in Colab!), Ging ik gewoon door en voer dit uit:

import PIL
afdruk (PIL.PILLOW_VERSION)

Als u iets onder 5.3.0 krijgt, gebruikt u het vervolgkeuzemenu onder "Runtime" om "Runtime opnieuw te starten" en voert u deze cel opnieuw uit. Je zou goed moeten zijn om te gaan!

U wilt GPU gebruiken voor dit project, dat ongelooflijk eenvoudig is in te stellen op Colab. Ga gewoon naar het vervolgkeuzemenu 'runtime', selecteer 'runtime-type wijzigen' en selecteer vervolgens 'GPU' in het vervolgkeuzemenu hardwareversneller!

Dan ren ik graag

train_on_gpu = torch.cuda.is_available ()
zo niet train_on_gpu:
    print ('Bummer! Training op CPU ...')
anders:
    print ('Je bent goed om te gaan! Training op GPU ...')

gewoon om te controleren of het werkt. Ren dan

device = torch.device ("cuda: 0" if torch.cuda.is_available () else "cpu")

om het apparaat te definiëren.

Hierna importeert u de bestanden. Er zijn veel manieren om dit te doen, waaronder het koppelen van uw Google Drive als u uw gegevensset daar hebt opgeslagen, wat eigenlijk heel eenvoudig is. Hoewel ik niet de conclusie heb getrokken dat dit de meest bruikbare oplossing is, neem ik die hieronder op, gewoon omdat het zo gemakkelijk en nuttig is.

van google.colab import drive
drive.mount ( '/ content / GDrive')

Dan zie je een link, klik daarop, geef toegang, kopieer de code die verschijnt, plak deze in het vak, druk op enter en je bent klaar om te gaan! Als je je drive niet ziet in het zijvak aan de linkerkant, klik je op "Vernieuwen" en het zou moeten verschijnen.

(Voer de cel uit, klik op de link, kopieer de code op de pagina, plak deze in het vak, druk op enter en je zult dit zien wanneer je je schijf succesvol hebt gemount):

Het is eigenlijk supergemakkelijk!

Als u echter liever een gedeelde zip-bestandslink downloadt (dit is voor dit project eenvoudiger en sneller verlopen), kunt u het volgende gebruiken:

! wget
!uitpakken

Bijvoorbeeld:

! wget -cq https://s3.amazonaws.com/content.udacity-data.com/courses/nd188/flower_data.zip
! unzip -qq flower_data.zip

Dat geeft u de bloemgegevensset van Udacity in seconden!

(Als u kleine bestanden uploadt, kunt u ze rechtstreeks uploaden met een eenvoudige code. Als u wilt, kunt u echter ook naar de linkerkant van het scherm gaan en op "bestanden uploaden" klikken als u dat niet doet. zin om een ​​eenvoudige code uit te voeren om een ​​lokaal bestand te pakken.)

Na het laden van de gegevens heb ik de bibliotheken geïmporteerd die ik wilde gebruiken:

% matplotlib inline
% config InlineBackend.figure_format = 'retina'
import tijd
json importeren
kopie importeren
matplotlib.pyplot importeren als plt
import seaborn als sns
import numpy als np
import PIL
van PIL importeren Afbeelding
uit collecties importeren OrderedDict
fakkel importeren
van fakkelimport nn, optim
van torch.optim import lr_scheduler
van torch.autograd import Variabel
torchvision importeren
van torchvision import datasets, modellen, transformaties
van torch.utils.data.sampler import SubsetRandomSampler
fakkel importeren als nn
fakkel importeren.nn. functioneel als F

Vervolgens komen de datatransformaties! U wilt ervoor zorgen dat u verschillende soorten transformaties in uw trainingsset gebruikt om uw programma te helpen zoveel mogelijk te leren. U kunt een robuuster model maken door het te trainen op gespiegelde, gedraaide en bijgesneden afbeeldingen.

Dit betekent dat standaardafwijkingen worden geboden om de beeldwaarden te normaliseren voordat ze aan ons netwerk worden doorgegeven, maar ze kunnen ook worden gevonden door te kijken naar de gemiddelde en standaardafwijkingswaarden van de verschillende afmetingen van de beeldtensoren. De officiële documentatie is hier ongelooflijk nuttig!

Voor mijn beeldclassificator hield ik het simpel met:

data_transforms = {
    'train': transforms.Compose ([
        transforms.RandomRotation (30),
        transforms.RandomResizedCrop (224),
        transforms.RandomHorizontalFlip (),
        transforms.ToTensor (),
        transforms.Normalize ([0.485, 0.456, 0.406],
                             [0.229, 0.224, 0.225])
    ]),
    'geldig': transforms.Compose ([
        transforms.Resize (256),
        transforms.CenterCrop (224),
        transforms.ToTensor (),
        transforms.Normalize ([0.485, 0.456, 0.406],
                             [0.229, 0.224, 0.225])
    ])
}
# Laad de datasets met ImageFolder
image_datasets = {x: datasets.ImageFolder (os.path.join (data_dir, x),
                                          data_transforms [x])
                  voor x in ['train', 'valid']}
# Definieer de dataloaders met behulp van de beeldgegevenssets en de treinvormen
batchgrootte = 64
dataloaders = {x: torch.utils.data.DataLoader (image_datasets [x], batch_size = batch_size,
                                             shuffle = True, num_workers = 4)
              voor x in ['train', 'valid']}
class_names = image_datasets ['train']. klassen
dataset_sizes = {x: len (image_datasets [x]) voor x in ['train', 'valid']}
class_names = image_datasets ['train']. klassen

Zoals u hierboven kunt zien, heb ik in de bovenstaande code ook de batchgrootte, gegevensladers en klassenamen gedefinieerd.

Om de gegevens heel snel te bekijken en mijn apparaat te controleren, heb ik het volgende uitgevoerd:

afdruk (dataset_sizes)
afdruk (apparaat)
{'train': 6552, 'valid': 818}
cuda: 0

Vervolgens moeten we wat kaarten maken op basis van het labelnummer en de daadwerkelijke bloemnaam. Udacity zorgde voor een JSON-bestand zodat deze toewijzing eenvoudig kon worden uitgevoerd.

met open ('cat_to_name.json', 'r') als f:
    cat_to_name = json.load (f)

Voer het volgende uit om de gegevenslader te testen:

images, labels = next (iter (dataloaders ['train']))
rand_idx = np.random.randint (len (afbeeldingen))
# Afdrukken (rand_idx)
print ("label: {}, class: {}, name: {}". format (labels [rand_idx] .item (),
                                               class_names [labels [rand_idx] .item ()],
                                               cat_to_name [class_names [labels [rand_idx] .item ()]]))

Nu wordt het nog spannender! De afgelopen jaren is een aantal modellen gemaakt door mensen die veel, veel meer gekwalificeerd zijn dan de meesten van ons, voor hergebruik bij computerzichtproblemen. PyTorch maakt het gemakkelijk om vooraf opgeleide modellen te laden en daarop voort te bouwen, en dat is precies wat we voor dit project gaan doen. De keuze van het model is helemaal aan jou!

Enkele van de meest populaire voorgetrainde modellen, zoals ResNet, AlexNet en VGG, komen uit de ImageNet Challenge. Met deze vooraf getrainde modellen kunnen anderen snel geavanceerde resultaten in computer vision behalen zonder dat ze zoveel computervermogen, geduld en tijd nodig hebben. Ik had eigenlijk geweldige resultaten met DenseNet en besloot DenseNet161 te gebruiken, wat me relatief snel zeer goede resultaten gaf.

U kunt dit snel instellen door te rennen

model = models.densenet161 (pretrained = True)

maar het kan interessanter zijn om jezelf een keuze te geven uit model, optimizer en planner. Om een ​​keuze in de architectuur in te stellen, voer je uit

model_name = 'densenet' #vgg
if model_name == 'densenet':
    model = models.densenet161 (pretrained = True)
    num_in_features = 2208
    druk (model)
elif model_name == 'vgg':
    model = models.vgg19 (pretrained = True)
    num_in_features = 25088
    afdruk (model.classifier)
anders:
    print ("Onbekend model, kies 'densenet' of 'vgg'")

waarmee u snel een alternatief model kunt instellen.

Daarna kunt u beginnen met het bouwen van uw classifier, met behulp van de parameters die het beste voor u werken. Ik ging door en bouwde

voor param in model.parameters ():
    param.requires_grad = False
def build_classifier (num_in_features, hidden_layers, num_out_features):
   
    classifier = nn.Sequential ()
    if hidden_layers == Geen:
        classifier.add_module ('fc0', nn.Linear (num_in_features, 102))
    anders:
        layer_sizes = zip (verborgen_lagen [: - 1], verborgen_lagen [1:])
        classifier.add_module ('fc0', nn.Linear (num_in_features, hidden_layers [0]))
        classifier.add_module ('relu0', nn.ReLU ())
        classifier.add_module ('drop0', nn.Dropout (.6))
        classifier.add_module ('relu1', nn.ReLU ())
        classifier.add_module ('drop1', nn.Dropout (.5))
        voor i, (h1, h2) in enumerate (layer_sizes):
            classifier.add_module ('fc' + str (i + 1), nn.Linear (h1, h2))
            classifier.add_module ('relu' + str (i + 1), nn.ReLU ())
            classifier.add_module ('drop' + str (i + 1), nn.Dropout (.5))
        classifier.add_module ('output', nn.Linear (hidden_layers [-1], num_out_features))
        
    terugkeer classifier

waarmee u op een eenvoudige manier het aantal verborgen lagen dat ik gebruik, kunt wijzigen en snel de uitval kunt aanpassen. U kunt besluiten om extra ReLU- en dropout-lagen toe te voegen om uw model fijner aan te scherpen.

Werk vervolgens aan het trainen van uw classificatorparameters. Ik besloot ervoor te zorgen dat ik alleen de classificatorparameters hier trainde terwijl functieparameters bevroren waren. U kunt zo creatief worden als u wilt met uw optimizer, criterium en planner. Het criterium is de methode die wordt gebruikt om de pasvorm van het model te evalueren, de optimizer is de optimalisatiemethode die wordt gebruikt om de gewichten bij te werken en de planner biedt verschillende methoden voor het aanpassen van de leersnelheid en stapgrootte die tijdens de optimalisatie worden gebruikt.

Probeer zoveel mogelijk opties en combinaties om te zien wat u het beste resultaat geeft. U kunt hier alle officiële documentatie bekijken. Ik raad je aan er eens naar te kijken en je eigen beslissingen te nemen over wat je wilt gebruiken. Je hebt hier niet letterlijk een oneindig aantal opties, maar het voelt zeker als je begint met spelen!

hidden_layers = Geen
classifier = build_classifier (num_in_features, hidden_layers, 102)
afdruk (classifier)
# Train alleen de classificatorparameters, functieparameters zijn bevroren
if model_name == 'densenet':
    model.classifier = classifier
    criterium = nn.CrossEntropyLoss ()
    optimizer = optim.Adadelta (model.parameters ())
    sched = optim.lr_scheduler.StepLR (optimizer, step_size = 4)
elif model_name == 'vgg':
    model.classifier = classifier
    criterium = nn.NLLLoss ()
    optimizer = optim.Adam (model.classifier.parameters (), lr = 0.0001)
    sched = lr_scheduler.StepLR (optimizer, step_size = 4, gamma = 0.1)
anders:
    voorbij lopen

Nu is het tijd om uw model te trainen.

# Aangepast van https://pytorch.org/tutorials/beginner/transfer_learning_tutorial.html
def train_model (model, criterium, optimizer, sched, num_epochs = 5):
    sinds = time.time ()
best_model_wts = copy.deepcopy (model.state_dict ())
    best_acc = 0.0
voor epoch in bereik (aantal_pochs):
        print ('Epoch {} / {}'. -indeling (epoch + 1, num_epochs))
        print ('-' * 10)
# Elk tijdperk heeft een training- en validatiefase
        voor fase in ['trein', 'geldig']:
            if phase == 'train':
                model.train () # Stel het model in op de trainingsmodus
            anders:
                model.eval () # Model instellen om de modus te evalueren
running_loss = 0.0
            running_corrects = 0
# Herhaal gegevens.
            voor ingangen, labels in dataloaders [fase]:
                inputs = inputss.to (apparaat)
                labels = labels.to (apparaat)
# Nul de parametergradiënten
                optimizer.zero_grad ()
# Vooruit
                # trackgeschiedenis al was het maar in de trein
                met torch.set_grad_enabled (phase == 'train'):
                    uitgangen = model (ingangen)
                    _, preds = torch.max (uitgangen, 1)
                    verlies = criterium (uitgangen, labels)
# Achteruit + alleen optimaliseren indien in trainingsfase
                    if phase == 'train':
                        # Sched.step ()
                        loss.backward ()
                        
                        optimizer.step ()
# Statistieken
                running_loss + = loss.item () * inputs.size (0)
                running_corrects + = torch.sum (preds == labels.data)
epoch_loss = running_loss / dataset_sizes [fase]
            epoch_acc = running_corrects.double () / dataset_sizes [fase]
print ('{} Verlies: {: .4f} Acc: {: .4f}'. format (
                fase, epoch_loss, epoch_acc))
# Kopieer het model diep
            if phase == 'valid' en epoch_acc> best_acc:
                best_acc = epoch_acc
                best_model_wts = copy.deepcopy (model.state_dict ())
afdrukken()
time_elapsed = time.time () - sinds
    print ('Training voltooid in {: .0f} m {: .0f} s'.format (
        time_elapsed // 60, time_elapsed% 60))
    print ('Best val Acc: {: 4f}'. formaat (best_acc))
# Laad de beste modelgewichten
    model.load_state_dict (best_model_wts)
    
    retourmodel
tijdvakken = 30
model.to (apparaat)
model = train_model (model, criterium, optimizer, schema, tijdvakken)

Ik wilde mijn tijdvakken gemakkelijk kunnen volgen en ook de verstreken tijd bijhouden terwijl mijn model liep. De bovenstaande code bevat beide en de resultaten zijn redelijk goed! Je kunt zien dat het model snel leert en de nauwkeurigheid van de validatieset snel bereikte meer dan 95% in tijdperk 7!

Tijdvak 1/30
----------
treinverlies: 2.4793 Acc: 0.4791
geldig verlies: 0,9688 Acc: 0,8191

Tijdvak 2/30
----------
treinverlies: 0,8288 Acc: 0,8378
geldig verlies: 0,4714 Acc: 0,9010

Tijdvak 3/30
----------
treinverlies: 0,5191 Acc: 0,8890
geldig verlies: 0.3197 Acc: 0.9181

Tijdvak 4/30
----------
treinverlies: 0.4064 Acc: 0.9095
geldig verlies: 0,2975 Acc: 0,9169

Tijdvak 5/30
----------
treinverlies: 0.3401 Acc: 0.9214
geldig verlies: 0,2486 Acc: 0,9401

Tijdvak 6/30
----------
treinverlies: 0.3111 Acc: 0.9303
geldig verlies: 0.2153 Acc: 0.9487

Tijdvak 7/30
----------
treinverlies: 0,2987 Acc: 0,9298
geldig verlies: 0,1969 Acc: 0,9584
...
Training voltooid in 67m 43s
Beste val Acc: 0,973105

Je kunt zien dat het uitvoeren van deze code op Google Colab met GPU iets meer dan een uur duurde.

Nu is het tijd voor evaluatie

model.eval ()
nauwkeurigheid = 0
voor ingangen, labels in dataloaders ['geldig']:
    ingangen, labels = inputs.to (apparaat), labels.to (apparaat)
    uitgangen = model (ingangen)
    
    # Klasse met de grootste waarschijnlijkheid is onze voorspelde klasse
    equality = (labels.data == outputs.max (1) [1])
# Nauwkeurigheid = aantal correcte voorspellingen gedeeld door alle voorspellingen
    nauwkeurigheid + = equality.type_as (torch.FloatTensor ()). mean ()
    
print ("Testnauwkeurigheid: {: .3f}". format (nauwkeurigheid / len (dataloaders ['valid'])))
Testnauwkeurigheid: 0,973

Het is belangrijk om uw checkpoint te bewaren

model.class_to_idx = image_datasets ['train']. class_to_idx
checkpoint = {'input_size': 2208,
              'output_size': 102,
              'tijdperken': tijdperken,
              'batch_grootte': 64,
              'model': models.densenet161 (pretrained = True),
              'classifier': classifier,
              'planner': sched,
              'optimizer': optimizer.state_dict (),
              'state_dict': model.state_dict (),
              'class_to_idx': model.class_to_idx
             }
   
torch.save (checkpoint, 'checkpoint.pth')

U hoeft niet alle parameters op te slaan, maar ik neem ze hier als voorbeeld op. Dit ijkpunt slaat het model specifiek op met een vooraf getrainde densenet161-architectuur, maar als u uw ijkpunt wilt opslaan met de optie met twee opties, kunt u dat absoluut doen. Pas eenvoudig de invoergrootte en het model aan.

Nu kunt u uw checkpoint laden. Als u uw project indient in de Udacity-werkruimte, kunnen dingen een beetje lastig worden. Hier is wat hulp bij het oplossen van problemen met uw checkpoint-belasting.

Je kunt je sleutels controleren door te rennen

ckpt = torch.load ('checkpoint.pth')
ckpt.keys ()

Laad en herbouw vervolgens uw model!

def load_checkpoint (filepath):
    checkpoint = torch.load (filepath)
    model = checkpoint ['model']
    model.classifier = checkpoint ['classifier']
    model.load_state_dict (checkpoint [ 'state_dict'])
    model.class_to_idx = checkpoint ['class_to_idx']
    optimizer = checkpoint ['optimizer']
    epochs = checkpoint ['epochs']
    
    voor param in model.parameters ():
        param.requires_grad = False
        
    retourmodel, checkpoint ['class_to_idx']
model, class_to_idx = load_checkpoint ('checkpoint.pth')

Wil je doorgaan? Het is een goed idee om een ​​aantal afbeeldingen te verwerken en conclusies te trekken voor classificatie. Ga je gang en definieer je afbeeldingspad en open een afbeelding:

image_path = 'flower_data / valid / 102 / image_08006.jpg'
img = Image.open (image_path)

Verwerk je afbeelding en bekijk een verwerkte afbeelding:

def process_image (afbeelding):
    '' Schaalt, snijdt en normaliseert een PIL-afbeelding voor een PyTorch-model,
        geeft een Numpy-array terug
    '''
    # Verwerk een PIL-afbeelding voor gebruik in een PyTorch-model
    # tensor.numpy (). transponeren (1, 2, 0)
    preprocess = transforms.Compose ([
        transforms.Resize (256),
        transforms.CenterCrop (224),
        transforms.ToTensor (),
        transforms.Normalize (gemiddelde = [0.485, 0.456, 0.406],
                             std = [0.229, 0.224, 0.225])
    ])
    afbeelding = preproces (afbeelding)
    afbeelding retourneren
def imshow (afbeelding, bijl = geen, titel = geen):
    "" "Toon voor Tensor." ""
    als axe geen is:
        fig, ax = plt.subplots ()
    
    # PyTorch-tensoren nemen aan dat het kleurkanaal de eerste dimensie is
    # maar matplotlib neemt aan dat dit de derde dimensie is
    image = image.numpy (). transponeren ((1, 2, 0))
    
    # Voorbewerking ongedaan maken
    gemiddelde = np. array ([0.485, 0.456, 0.406])
    std = np.array ([0.229, 0.224, 0.225])
    afbeelding = standaard * afbeelding + gemiddelde
    
    # Afbeelding moet worden geknipt tussen 0 en 1 of het lijkt op ruis wanneer het wordt weergegeven
    image = np.clip (afbeelding, 0, 1)
    
    ax.imshow (beeld)
    
    terugkeer bijl
met Image.open ('flower_data / valid / 102 / image_08006.jpg') als afbeelding:
    plt.imshow (beeld)
model.class_to_idx = image_datasets ['train']. class_to_idx

Maak een functie voor voorspelling:

def predict2 (image_path, model, topk = 5):
    '' 'Voorspellen van de klasse (of klassen) van een afbeelding met behulp van een getraind deep learning-model.
    '''
    
    # Implementeer de code om de klasse uit een afbeeldingsbestand te voorspellen
    img = Image.open (image_path)
    img = process_image (img)
    
    # Converteer 2D-afbeelding naar 1D vector
    img = np.expand_dims (img, 0)
    
    
    img = torch.from_numpy (img)
    
    model.eval ()
    ingangen = Variabel (img) .to (apparaat)
    logits = model.forward (invoer)
    
    ps = F.softmax (logits, dim = 1)
    topk = ps.cpu (). topk (topk)
    
    return (e.data.numpy (). squeeze (). tolist () voor e in topk)

Zodra de afbeeldingen de juiste indeling hebben, kunt u een functie schrijven om voorspellingen te doen met uw model. Een veel voorkomende praktijk is om de meest waarschijnlijke klassen van de top 5 of zo (meestal top-KK genoemd) te voorspellen. U wilt de waarschijnlijkheden van de klasse berekenen en vervolgens de grootste KK-waarden vinden.

Gebruik k.topk () om de hoogste KK-grootste waarden in een tensor te krijgen. Deze methode retourneert zowel de hoogste k-kansen als de indices van die kansen die overeenkomen met de klassen. U moet deze indices converteren naar de eigenlijke klassenlabels met behulp van class_to_idx, die u aan het model hebt toegevoegd of uit de Afbeeldingsmap die u hebt gebruikt om de gegevens te laden. Zorg ervoor dat u het woordenboek omkeert, zodat u ook een indeling van index naar klasse krijgt.

Deze methode moet een pad volgen naar een afbeelding en een modelcontrolepunt en vervolgens de waarschijnlijkheden en klassen retourneren.

img_path = 'flower_data / valid / 18 / image_04252.jpg'
probs, classes = predict2 (img_path, model.to (device))
afdruk (probs)
afdruk (klassen)
flower_names = [cat_to_name [class_names [e]] voor e in klassen]
afdruk (flower_names)

Ik was behoorlijk tevreden met hoe mijn model presteerde!

[0.9999195337295532, 1.4087702766119037e-05, 1.3897360986447893e-05, 1.1400215043977369e-05, 6.098791800468462e-06]
[12, 86, 7, 88, 40]
['Peruaanse lelie', 'woestijnroos', 'koningsprotea', 'magnolia', 'zwaardlelie']

Kortom, het is bijna 100% waarschijnlijk dat de afbeelding die ik heb opgegeven een Peruaanse lelie is. Wil je een kijkje nemen? Probeer matplotlib te gebruiken om de kansen voor de top vijf klassen in een staafdiagram samen met de invoerafbeelding te plotten:

def view_classify (img_path, prob, classes, mapping):
    '' Functie voor het bekijken van een afbeelding en de voorspelde klassen.
    '''
    image = Image.open (img_path)
fig, (ax1, ax2) = plt. subplots (figsize = (6,10), ncols = 1, nrows = 2)
    flower_name = mapping [img_path.split ('/') [- 2]]
    ax1.set_title (flower_name)
    ax1.imshow (beeld)
    ax1.axis ( 'off')
    
    y_pos = np.arange (len (prob))
    ax2.barh (y_pos, prob, align = 'center')
    ax2.set_yticks (y_pos)
    ax2.set_yticklabels (flower_names)
    ax2.invert_yaxis () # labels lezen van boven naar beneden
    ax2.set_title ('Class Probability')
view_classify (img_path, probs, classes, cat_to_name)

Je zou zoiets moeten zien:

Ik moet zeggen, daar ben ik best blij mee! Ik raad aan een paar andere afbeeldingen te testen om te zien hoe dicht uw voorspellingen bij verschillende afbeeldingen liggen.

Nu is het tijd om een ​​eigen model te maken en me te laten weten hoe het gaat in de onderstaande reacties!

Foto door Pez González op Unsplash

Ben je klaar met je deep learning- of machine learning-model, maar weet je niet wat je er verder mee moet doen? Waarom zou u het niet op internet implementeren?

Breng uw model naar buiten zodat iedereen het kan zien!

Lees dit artikel voor meer informatie over het implementeren van uw machine learning-model met Flask!