Hogyan építsünk egy képminősítőt 97% -nál nagyobb pontossággal

Világos és teljes terv a sikerhez

Hogyan taníthatja meg a számítógépet egy kép megnézésére és virágnak való megfelelő azonosítására? Hogyan taníthatja meg a számítógépet egy virág képének látására, majd pontosan megmondja, hogy milyen virágfajról van szó, még akkor sem, ha még nem tudja, melyik faj ez?

Hadd mutassam meg!

Ez a cikk bemutatja a kép osztályozó létrehozásának alapjait a PyTorch segítségével. Elképzelheti, hogy használ valami ilyesmit egy telefonos alkalmazásban, amely elmondja neked annak a virágnak a nevét, amelyet a fényképezőgép néz. Ha szeretné, kiképezheti ezt az osztályozót, majd exportálhatja saját alkalmazásához.

Amit itt csinálsz, teljes mértékben tőled és a képzeletedtől függ.

Összeállítottam ezt a cikket bárki számára, aki vadonatúj mindezen körülmények között, és kezdőpontot keres. Önnek kell eldöntenie ezt az információt, továbbfejleszteni és saját kezűvé tenni!

Ha meg szeretné tekinteni a notebookot, itt megtalálja.

Mivel ezt a PyTorch képosztályt egy Udacity program végső projektjeként építették be, a kód az Udacity kódját használja, amely viszont a hivatalos PyTorch dokumentációra támaszkodik. Az Udacity JSON-fájlt is biztosított a címkeleképezéshez. Ez a fájl megtalálható a GitHub repóban.

A virág-adatkészlettel kapcsolatos információk itt találhatók. Az adatkészlet külön mappát tartalmaz a 102 virágosztály mindegyikéhez. Minden virágot számként jelölnek, és a számozott könyvtárak számos .jpg fájlt tartalmaznak.

Kezdjük el!

Fotó: Annie Spratt az Unsplash-en

Mivel ez egy neurális hálózat, amely nagyobb adatkészletet használ, mint amelyet a processzorom ésszerű időn belül képes kezelni, előrementem és beállítottam a képosztályozót a Google Colabban. A Colab valóban fantasztikus, mert ingyenes GPU-t kínál. (Ha még nem ismeri a Colabot, akkor olvassa el ezt a cikket a Google Colab használatának megkezdéséről!)

Mivel a Colab-ot használtam, el kellett kezdenem a PyTorch importálását. Ezt nem kell tennie, ha nem a Colabot használja.

*** UPDATE! (01/29) *** A Colab most támogatja a natív PyTorch-ot !!! Nem kellene futtatnia az alábbi kódot, de hagyom fel, csak arra az esetre, ha valakinek problémája van!

# Importálja a PyTorch-ot, ha a Google Colabot használja
# http://pytorch.org/
az os.path-ból importálás létezik
from wheel.pep425tags import import get_abbr_impl, get_impl_ver, get_abi_tag
platform = '{} {} - {}'. formátum (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 /”
gyorsító = cuda_output [0], ha létezik ('/ dev / nvidia0') egyébként 'cpu'
! pip install -q http://download.pytorch.org/whl/{accelerator}/torch-0.4.1-{platform}-linux_x86_64.whl torchvision
import fáklya

Aztán, miután némi probléma merült fel a Párnával (ez hibás a Colabban!), Csak előrementem és futtam:

import PIL
print (PIL.PILLOW_VERSION)

Ha valami az 5.3.0 alatt van, használja a „Futásidejű” alatti legördülő menüt a „Futásidejű újraindítása” pontra, és futtassa újra ezt a cellát. Jó lenne menni!

A GPU-t kívánja használni ehhez a projekthez, amely hihetetlenül egyszerű a Colabon történő telepítéshez. Csak menjen a „runtime” legördülő menübe, válassza a „runtime type módosítása” lehetőséget, majd válassza a „GPU” lehetőséget a hardveres gyorsító legördülő menüben!

Akkor szeretek futni

train_on_gpu = torch.cuda.is_avable ()
ha nem vonat_on_gpu:
    nyomtatás ('Lökés! Képzés a CPU-n ...')
más:
    nyomtatás ('Jó vagy menni! Képzés a GPU-n ...')

csak annak ellenőrzése érdekében, hogy működik-e. Akkor fuss

eszköz = torch.device ("cuda: 0", ha torch.cuda.is_avable () else "cpu")

az eszköz meghatározása.

Ezután importálja a fájlokat. Rengeteg módon lehet ezt megtenni, ideértve a Google Drive telepítését is, ha az adatkészletét ott tárolja, ami valójában nagyon egyszerű. Annak ellenére, hogy nem tudtam befejezni, hogy ez a leghasznosabb megoldás, belefoglalom az alábbiakat, csak azért, mert olyan könnyű és hasznos.

a google.colab import meghajtóról
drive.mount ( '/ tartalom / GDrive')

Akkor megjelenik egy link, rákattint, hozzáférést enged, másolja a felbukkanó kódot, illessze be a mezőbe, nyomja meg az enter billentyűt, és máris jól megy! Ha nem látja meghajtóját a bal oldali oldalsó dobozban, csak nyomja meg a „frissítés” gombot, és az megjelenik.

(Futtassa a cellát, kattintson a linkre, másolja a kódot az oldalon, illessze be a mezőbe, nyomja meg az enter billentyűt, és ezt meg fogja látni, amikor sikeresen telepítette a meghajtót):

Valójában rendkívül egyszerű!

Ha azonban inkább töltsön le egy megosztott zip fájl linket (ez a projekt egyszerűbb és gyorsabb lesz a projektnél), akkor az alábbiakat használhatja:

! wget
! kicsomagolás

Például:

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

Ez másodpercek alatt megadja az Udacity virágadatait!

(Ha kis fájlokat tölt fel, akkor azokat egyszerűen feltöltheti közvetlenül néhány egyszerű kóddal. Ha szeretne, akkor is léphet a képernyő bal oldalára, és kattintson a „Fájlok feltöltése” elemre, ha nem úgy érzem, futtasson egy egyszerű kódot egy helyi fájl megragadásához.)

Az adatok betöltése után behoztam a használni kívánt könyvtárakat:

% matplotlib inline
% config InlineBackend.figure_format = 'retina'
importálási idő
import json
import példány
import matplotlib.pyplot mint plt
import tengeri született sns
importálni számot, mint np
import PIL
PIL import képből
a gyűjteményekből importálja az OrderedDict fájlt
import fáklya
a fáklya behozatalából nn, optim
from torch.optim import lr_scheduler
a torch.autograd import változóból
import zseblámpa
a zseblámpákból származó import adatkészletekből, modellekből, transzformációkból
A torch.utils.data.sampler importálása SubsetRandomSampler
import torch.nn as nn
import torch.nn.funkcionális, mint F

Ezután következik az adatátalakítások! Biztos, hogy többféle típusú transzformációt használjon az edzőkészletén annak érdekében, hogy a program minél többet megtanuljon. Készíthet robusztusabb modellt úgy, hogy kiképezi a megfordított, elforgatott és levágott képeket.

Ez azt jelenti, hogy szabványos eltéréseket kell biztosítani a képértékek normalizálása előtt, mielőtt azokat hálózatunkba továbbítanánk, de úgy is megtalálhatók, ha megnézzük a kép-tenzorok különböző méretei közép- és szórási értékeit. A hivatalos dokumentáció hihetetlenül hasznos itt!

Képminősítőmnél egyszerűen elkerültem a következőket:

data_transforms = {
    'vonat': átalakul.Komponálás ([
        transforms.RandomRotation (30),
        transforms.RandomResizedCrop (224),
        transforms.RandomHorizontalFlip (),
        transforms.ToTensor (),
        transzformációk.Normalizálja ([0,455, 0,456, 0,406],
                             [0,229, 0,224, 0,225])
    ]),
    'érvényes': transforms.Compose ([
        transforms.Resize (256),
        transforms.CenterCrop (224),
        transforms.ToTensor (),
        transzformációk.Normalizálja ([0,455, 0,456, 0,406],
                             [0,229, 0,224, 0,225])
    ])
}
# Töltse be az adatkészleteket az ImageFolder segítségével
image_datasets = {x: datasets.ImageFolder (os.path.join (data_dir, x),
                                          data_transforms [x])
                  x-re a ['vonat', 'érvényes']}
# A képadatkészletek és a vonatformák segítségével határozza meg az adatgyűjtőket
batch_size = 64
dataloaders = {x: torch.utils.data.DataLoader (image_datasets [x], batch_size = batch_size,
                                             shuffle = Igaz, num_workers = 4)
              x-re a ['vonat', 'érvényes']}
osztály_nevek = image_datasets ['vonat']
dataset_sizes = {x: len (image_datasets [x]) az x számára a ['vonat', 'érvényes']}
osztály_nevek = image_datasets ['vonat']

Ahogy fent láthatja, a fenti kódban meghatároztam a kötegek méretét, az adatbetöltőket és az osztályneveket is.

Az adatok nagyon gyors áttekintése és az eszköz ellenőrzése érdekében futtam:

print (dataset_sizes)
print (eszköz)
{'vonat': 6552, 'érvényes': 818}
CUDA: 0

Ezután le kell készítenünk a leképezést a címke számából és a tényleges virág nevéből. Az Udacity JSON fájlt adott a leképezés egyszerű végrehajtásához.

nyitva ('cat_to_name.json', 'r'), mint f:
    cat_to_name = json.load (f)

Az adatbetöltő teszteléséhez futtassa:

képek, címkék = következő (iter (adatgyűjtők ['vonat']))
rand_idx = np.random.randint (len (képek))
# Nyomtatás (rand_idx)
print ("címke: {}, osztály: {}, név: {}". formátum (címkék [rand_idx] .item (),
                                               class_names [címkék [rand_idx] .item ()],
                                               cat_to_name [class_names [címkék [rand_idx] .item ()]]))

Most még izgalmasabbá válik! Az elmúlt években számos modellt messzire, sokkal jobban képzettek hoztak létre az emberek, mint legtöbben, a számítógépes látási problémák újbóli felhasználására. A PyTorch megkönnyíti az előre képzett modellek betöltését és felépítését, pontosan ezt fogjuk tenni a projekthez. A modell kiválasztása teljesen rajtad múlik!

A legnépszerűbb előre képzett modellek, például a ResNet, az AlexNet és a VGG, az ImageNet Challenge programból származnak. Ezek az előre kiképzett modellek lehetővé teszik mások számára a csúcstechnikai eredmények gyors elérését a számítógépes látásban anélkül, hogy ilyen nagy mennyiségű számítógépes energiára, türelemre és időre lenne szükség. Nagyon jó eredményeket értek el a DenseNet segítségével, és úgy döntöttem, hogy a DenseNet161-et használom, ami viszonylag gyorsan nagyon jó eredményeket adott nekem.

Futtatásával gyorsan beállíthatja ezt

model = models.densenet161 (előképzett = igaz)

de érdekesebb lehet választani a modellnek, az optimalizálónak és az ütemezőnek. Annak érdekében, hogy választást nyújtson az építészetben, futtassa

model_name = 'densenet' #vgg
ha model_name == 'densenet':
    model = models.densenet161 (előképzett = igaz)
    num_in_features = 2208
    print (modell)
elif model_name == 'vgg':
    model = models.vgg19 (előképzett = igaz)
    num_in_features = 25088
    print (model.classifier)
más:
    nyomtatás ("Ismeretlen modell, kérjük, válassza a" densenet "vagy a" vgg "lehetőséget)

amely lehetővé teszi egy alternatív modell gyors beállítását.

Ezt követően elkezdheti az osztályozó létrehozását az Ön számára legjobban megfelelő paraméterek felhasználásával. Előmentem és építettem

a param számára a model.parameters () -ben:
    param.requires_grad = Hamis
def build_classifier (num_in_features, rejtett rétegek, num_out_features):
   
    osztályozó = nn.Sequential ()
    ha hidden_layers == Nincs:
        classifier.add_module ('fc0', nn.Linear (num_in_features, 102))
    más:
        layer_sizes = zip (rejtett rétegek [: - 1], rejtett rétegek [1:])
        classifier.add_module ('fc0', nn.Linear (num_in_features, hidden_layers [0]))
        osztályozó.add_module ('relu0', nn.ReLU ())
        osztályozó.add_modul ('drop0', nn.Dropout (.6))
        osztályozó.add_module ('relu1', nn.ReLU ())
        osztályozó.add_modul ('drop1', nn.Dropout (.5))
        az i, (h1, h2) számára felsorolásban (rétegméret):
            osztályozó.add_modul ('fc' + str (i + 1), nn.Linear (h1, h2))
            osztályozó.add_modul ('relu' + str (i + 1), nn.ReLU ())
            osztályozó.add_modul ('drop' + str (i + 1), nn.Dropout (.5))
        classifier.add_module ('output', nn.Linear (rejtett rétegek [-1], num_out_features))
        
    visszatérő osztályozó

amely lehetővé teszi a használt rejtett rétegek számának egyszerű módosítását, valamint a lemorzsolódás gyors beállítását. Dönthet úgy, hogy további ReLU és lemorzsolódási rétegeket ad hozzá a modell finomabb csiszolása érdekében.

Ezután dolgozzon az osztályozó paramétereinek kiképzésén. Úgy döntöttem, hogy biztosan itt csak az osztályozó paramétereket képzem, miközben a szolgáltatásparamétereket befagyasztom. Az optimalizálóval, a kritériummal és az ütemezővel annyira kreatív lehet, amennyit csak akar. A kritérium a modell illesztésének értékeléséhez használt módszer, az optimalizáló a súlyok frissítéséhez használt optimalizálási módszer, az ütemező különféle módszereket biztosít az optimalizálás során alkalmazott tanulási sebesség és lépésméret beállításához.

Próbáljon meg annyi lehetőséget és kombinációt, amennyit csak tudsz, hogy megtudja, mi adja a legjobb eredményt. Az összes hivatalos dokumentáció itt található. Azt javaslom, hogy nézzen rá, és hozzon saját döntéseket arról, hogy mit szeretne használni. Szó szerint nincs itt végtelen számú lehetőség, de az biztos, hogy érzi magát, amikor elkezdesz játszani!

hidden_layers = Nincs
osztályozó = épít_osztályozó (szám_indexek, rejtett rétegek, 102)
print (osztályozó)
# Csak az osztályozó paramétereket edzheti, a szolgáltatásparaméterek befagytak
ha model_name == 'densenet':
    model.classifier = osztályozó
    kritérium = nn.CrossEntropyLoss ()
    optimalizáló = optim.Adadelta (model.parameters ())
    sched = optim.lr_scheduler.StepLR (optimalizáló, step_size = 4)
elif model_name == 'vgg':
    model.classifier = osztályozó
    kritérium = nn.NLLLoss ()
    optimalizáló = optim.Adam (model.classifier.parameters (), lr = 0.0001)
    sched = lr_scheduler.StepLR (optimalizáló, lépés_mérete = 4, gamma = 0,1)
más:
    elhalad

Itt az ideje, hogy kiképezze a modelljét.

# A https://pytorch.org/tutorials/beginner/transfer_learning_tutorial.html adaptált
def train_model (modell, kritérium, optimalizáló, ütemezés, num_epochs = 5):
    óta = time.time ()
best_model_wts = copy.deepcopy (model.state_dict ())
    best_acc = 0,0
a tartományban lévő korszakra (szám_epochák):
        print ('Epoch {} / {}' formátum (+ 1 korszak, num_epochs))
        nyomtatás ('-' * 10)
# Minden korszaknak van egy képzési és érvényesítési fázisa
        a ['vonat', 'érvényes'] szakaszra:
            ha = = 'vonat' fázis:
                model.train () # Állítsa a modellt edzési módba
            más:
                model.eval () # A modell beállítása az üzemmód értékeléséhez
futási veszteség = 0,0
            futó javítás = 0
# Iterta az adatokat.
            bemenetekhez, adatrögzítők címkéihez [fázis]:
                bemenetek = bemenetek.to (eszköz)
                címkék = tags.to (eszköz)
# Nullázza a paraméter gradienseit
                optimizer.zero_grad ()
# Előre
                # nyomkövetési előzmények, ha csak vonaton van
                torch.set_grad_enabled-vel (fázis == 'vonat'):
                    outputok = modell (bemenetek)
                    _, preds = torch.max (kimenetek, 1)
                    veszteség = kritérium (outputok, címkék)
# Visszafelé + csak akkor optimalizálható, ha edzési szakaszban van
                    ha = = 'vonat' fázis:
                        # Sched.step ()
                        loss.backward ()
                        
                        optimizer.step ()
# Statisztika
                run_loss + = loss.item () * inputs.size (0)
                futó javítások + = torch.sum (preds == labels.data)
epoch_loss = futó veszteség / adatkészlet_méretek [fázis]
            epoch_acc = running_corrects.double () / dataset_sizes [fázis]
print ('{} Veszteség: {: .4f} Acc: {: .4f}'. formátum (
                fázis, epoch_loss, epoch_acc))
# Mélyen másolja a modellt
            ha fázis == 'érvényes' és epoch_acc> best_acc:
                best_acc = epoch_acc
                best_model_wts = copy.deepcopy (model.state_dict ())
nyomtatás()
time_elapsed = time.time () - azóta
    print ('Az edzés teljes: {: .0f} m {: .0f} s'.format (
        time_elapsed // 60, time_elapsed% 60))
    print ('Legjobb val Acc: {: 4f}'. formátum (best_acc))
# A legjobb modellsúlyok betöltése
    model.load_state_dict (best_model_wts)
    
    visszatérési modell
korszak = 30
model.to (eszköz)
modell = vonatmodell (modell, kritérium, optimalizáló, ütemezés, korszakok)

Azt akartam, hogy könnyen megfigyelhessem korszakaimat, és nyomon lehessen követni az eltelt időt, amíg a modell fut. A fenti kód mindkettőt tartalmazza, és az eredmények nagyon jók! Láthatjuk, hogy a modell gyorsan megtanul, és a validálási pontosság pontossága a 7. korszakra gyorsan elérte a 95% -ot!

1/30 korszak
----------
vonat veszteség: 2.4793 Acc: 0.4791
érvényes veszteség: 0.9688 Acc: 0.8191

2/30 korszak
----------
vonat veszteség: 0.8288 Acc: 0.8378
érvényes veszteség: 0,4714 Acc: 0,9010

3/30 korszak
----------
vonat veszteség: 0,5191 Acc: 0,8890
érvényes veszteség: 0,3197 Acc: 0,9181

4/30 korszak
----------
vonat veszteség: 0,4064 számlálás: 0,9095
érvényes veszteség: 0,2975 Acc: 0,9169

5/30 korszak
----------
vonat vesztesége: 0.3401 Acc: 0.9214
érvényes veszteség: 0,2486 Acc: 0,9401

6/30 korszak
----------
vonat veszteség: 0,3111 számlálás: 0,9303
érvényes veszteség: 0,2153 Acc: 0,9487

7/30 korszak
----------
vonat veszteség: 0,2987 számláló: 0,9298
érvényes veszteség: 0,1996 Acc: 0,9584
...
Az edzés 67m 43s alatt teljes
Legjobb val Acc: 0.973105

Láthatja, hogy ennek a kódnak a futtatása a Google Colabban a GPU-val alig több mint egy órát vett igénybe.

Itt az ideje az értékelésnek

model.eval ()
pontosság = 0
bemenetekhez, adatrögzítők címkéi ['érvényes']:
    bemenetek, címkék = bemenetek.to (eszköz), tags.to (eszköz)
    outputok = modell (bemenetek)
    
    # A legvalószínűbb osztály az előrejelzett osztályunk
    egyenlőség = (Label.data == outputok.max (1) [1])
# Pontosság = a helyes előrejelzések száma osztva az összes előrejelzéssel
    pontosság + = egyenlőség.típus_ (torch.FloatTensor ()) átlag ()
    
print ("Teszt pontossága: {: .3f}". formátum (pontosság / len (adatátvitel ['érvényes'])))
A vizsgálat pontossága: 0.973

Fontos, hogy mentse az ellenőrző pontot

model.class_to_idx = image_datasets ['vonat']. class_to_idx
ellenőrzőpont = {'input_size': 2208,
              'output_size': 102,
              „korszakok”: korszakok,
              'batch_size': 64,
              „modell”: models.densenet161 (előre képzett = igaz),
              „osztályozó”: osztályozó,
              „ütemező”: ütemezett,
              'optimalizáló': optimizer.state_dict (),
              'state_dict': model.state_dict (),
              'class_to_idx': model.class_to_idx
             }
   
torch.save (ellenőrzőpont, 'checkpoint.pth')

Nem kell elmentenie az összes paramétert, de példaként szerepeltem itt. Ez az ellenőrző pont kifejezetten elmenti a modellt egy előre képzett densenet161 architektúrával, de ha az ellenőrző pontot a kettős választási lehetőséggel szeretné menteni, akkor ezt megteheti. Egyszerűen állítsa be a bemeneti méretet és a modellt.

Most már betöltheti ellenőrzőpontját. Ha beküldi a projektet a Udacity munkaterületre, a dolgok kissé trükkös lehet. Itt található néhány segítség az ellenőrzőpont betöltésének hibaelhárításában.

A billentyűket futással ellenőrizheti

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

Ezután töltse be és újjáépítse a modelljét!

def load_checkpoint (fájlútvonal):
    ellenőrzőpont = torch.load (fájlútvonal)
    modell = ellenőrzőpont ['modell']
    model.classifier = ellenőrzőpont ['osztályozó']
    model.load_state_dict (checkpoint [ 'state_dict'])
    model.class_to_idx = ellenőrzőpont ['class_to_idx']
    optimalizáló = ellenőrzőpont ['optimalizáló']
    korszak = ellenőrző pont ['korszak']
    
    a param számára a model.parameters () -ben:
        param.requires_grad = Hamis
        
    visszatérő modell, ellenőrzőpont ['class_to_idx']
modell, class_to_idx = load_checkpoint ('checkpoint.pth')

Folytatni akarja? Jó ötlet a kép előfeldolgozása és a besorolás következtetése. Adja meg a kép elérési útját, és nyisson meg egy képet:

image_path = 'virág_adata / érvényes / 102 / image_08006.jpg'
img = Image.open (image_path)

Feldolgozza fel a képet, és nézzen meg egy feldolgozott képet:

def process_image (kép):
    '' 'Méretezi, kivágja és normalizálja a PyTorch modell PIL képét,
        Numpy tömböt ad vissza
    „””
    # Feldolgozza fel a PIL-képet PyTorch-modellben történő felhasználásra
    # tensor.numpy (). átültetés (1, 2, 0)
    preprocess = transforms.Compose ([
        transforms.Resize (256),
        transforms.CenterCrop (224),
        transforms.ToTensor (),
        transzformációk. Normalizálni (átlag = [0,455, 0,456, 0,406],
                             std = [0,229, 0,224, 0,225])
    ])
    image = előfeldolgozás (kép)
    visszatérő kép
def imshow (kép, ax = Nincs, cím = Nincs):
    "" "Imshow a Tensor számára." ""
    ha ax nincs:
        ábra, ax = plt.subplots ()
    
    # A PyTorch tenzorok feltételezik, hogy a színcsatorna az első dimenzió
    #, de a matplotlib feltételezi a harmadik dimenziót
    image = image.numpy (). transpose ((1, 2, 0))
    
    # Visszavonja az előfeldolgozást
    átlag = np.array ([0,455, 0,456, 0,406])
    std = np.array ([0,229, 0,224, 0,225])
    image = std * image + átlag
    
    # A képet 0 és 1 közé kell vágni, vagy pedig megjelenéskor zajnak tűnik
    image = np.clip (kép, 0, 1)
    
    ax.imshow (image)
    
    visszirányú ax
Image.open ('virág_adatok / érvényes / 102 / image_08006.jpg') képpel:
    plt.imshow (image)
model.class_to_idx = image_datasets ['vonat']. class_to_idx

Hozzon létre egy függvényt az előrejelzéshez:

def ennt2 (image_path, modell, topk = 5):
    '' 'Jósolja meg a kép osztályát (osztályait) egy képzett mély tanulási modell segítségével.
    „””
    
    # Vigye be a kódot az osztály megjósításához egy képfájlból
    img = Image.open (image_path)
    img = folyamat_kép (img)
    
    # Konvertálja a 2D képet 1D vektorré
    img = np.expand_dims (img, 0)
    
    
    img = torch.from_numpy (img)
    
    model.eval ()
    bemenetek = változó (img) .to (eszköz)
    logits = model.forward (bemenetek)
    
    ps = F.softmax (logit, dim = 1)
    topk = ps.cpu (). topk (topk)
    
    visszatérés (e.data.numpy (). squeeze (). tolist () for e in topk)

Miután a képek a megfelelő formátumban vannak, megírhat egy funkciót, hogy előrejelzéseket készítsen a modelljével. Az egyik leggyakoribb gyakorlat az, hogy megjósolják az öt legjobban felmerülő (általában top-KK) osztályt. Ki kell számítania az osztály valószínűségét, majd meg kell találnia a KK legnagyobb értékeit.

A k.topk () használatával kaphatjuk meg a teniszben a KK legnagyobb értékét. Ez a módszer mind a legmagasabb k valószínűséget, mind az osztályoknak megfelelő valószínűségi mutatókat adja vissza. Ezeket az indexeket át kell konvertálnia a tényleges osztálycímkékre a class_to_idx használatával, amelyet hozzáadott a modellhez, vagy az Image betöltéshez használt mappából. Feltétlenül fordítsa meg a szótárt, hogy leképezést kapjon az indexről az osztályra is.

Ennek a módszernek egy utat kell elérnie egy képhez és egy modell ellenőrző pontjához, majd vissza kell adnia a valószínűségeket és osztályokat.

img_path = 'virág_adata / érvényes / 18 / image_04252.jpg'
próbák, osztályok = előrejelzés2 (img_path, model.to (eszköz))
print (probs)
print (osztály)
virág_nevek = [macska_neve [osztálynevek [e]] e osztályokban]
print (flower_names)

Nagyon elégedett voltam a modellem teljesítményével!

[0.9999195337295532, 1.4087702766119037e-05, 1.3897360986447893e-05, 1.1400215043977369e-05, 6.098791800468462e-06]
[12, 86, 7, 88, 40]
['perui liliom', 'sivatagi rózsa', 'király protea', 'magnólia', 'kardliliom']

Alapvetően közel 100% -kal valószínű, hogy az általam megadott kép perui liliom. Vessen egy pillantást? Próbálja meg a matplotlib használatával ábrázolni az oszlopdiagramon az öt legjobb osztály valószínűségét a bemeneti kép mellett:

def view_classify (img_path, prob, osztályok, leképezés):
    '' 'Funkció egy kép és az előrejelzett osztályok megtekintésére.
    „””
    image = Image.open (img_path)
ábra, (ax1, ax2) = plt.sublottok (ábra = (6,10), ncols = 1, nrows = 2)
    virág_neve = leképezés [img_path.split ('/') [- 2]]
    ax1.set_title (flower_name)
    ax1.imshow (image)
    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 () # feliratok olvashatók fentről lefelé
    ax2.set_title ('Osztály valószínűség')
view_classify (img_path, probs, osztályok, cat_to_name)

Látnia kellene valami ilyesmit:

Azt kell mondanom, hogy nagyon boldog vagyok ezzel! Azt javaslom, tesztelje néhány további képet, hogy megnézze, milyen közel állnak az előrejelzések a különféle képeken.

Itt az ideje, hogy készítsen egy saját modellt, és tudassa velem az alábbi válaszokban!

Fotó: Pez González az Unsplash-en

Befejezte a mély tanulási vagy gépi tanulási modelljét, de nem tudja, mit kezd vele a következő? Miért nem telepíti azt az internetre?

Vigye oda a modelljét, hogy mindenki láthassa!

Nézze meg ezt a cikket, ahol megtudhatja, hogyan telepítheti gépi tanulási modelljét a Flask segítségével!