% 97'den daha fazla doğrulukla bir görüntü sınıflandırıcı nasıl oluşturulur

Başarı için net ve eksiksiz bir plan

Bilgisayara bir görüntüye bakmayı ve çiçek olarak tanımlamayı nasıl öğretirsiniz? Bir bilgisayara bir çiçeğin görüntüsünü görmeyi nasıl öğretirsiniz ve daha sonra hangi türün ne olduğunu bile bilmediğiniz zaman, size tam olarak hangi çiçek türünü anlatırsınız?

Sana göstereyim!

Bu makale sizi PyTorch ile bir görüntü sınıflandırıcı oluşturmanın temellerini inceleyecektir. Böyle bir şeyi kameranızın aradığı çiçeğin adını söyleyen bir telefon uygulamasında kullanmayı hayal edebilirsiniz. İsterseniz, bu sınıflandırıcıyı eğitebilir ve kendi uygulamanızda kullanmak için dışa aktarabilirsiniz.

Buradan yapacağınız şey tamamen size ve hayal gücünüze bağlıdır.

Bu makaleyi, hepsi için yepyeni olan ve başlamak için bir yer arayanlar için bir araya getirdim. Bu bilgiyi almak, geliştirmek ve kendin yapmak sana kalmış!

Not defterini görüntülemek istiyorsanız, burada bulabilirsiniz.

Bu PyTorch görüntü sınıflandırıcısı bir Udacity programı için son bir proje olarak oluşturulduğundan, kod, sırayla, resmi PyTorch belgelerine dayanan Udacity'den gelen kodu kullanır. Udacity ayrıca etiket eşleme için bir JSON dosyası sağlamıştır. Bu dosya bu GitHub deposunda bulunabilir.

Çiçek veri seti hakkında bilgiler burada bulunabilir. Veri seti, 102 çiçek sınıfının her biri için ayrı bir klasör içermektedir. Her çiçek bir sayı olarak etiketlenir ve numaralandırılmış dizinlerin her birinde bir dizi .jpg dosyası bulunur.

Başlayalım!

Unsplash'ta Annie Spratt tarafından fotoğraf

Bu, CPU'mun makul bir süre içinde kaldırabileceğinden daha büyük bir veri kümesi kullanan bir sinir ağı olduğundan, devam ettim ve resim sınıflandırıcımı Google Colab'da kurdum. Colab gerçekten harika çünkü ücretsiz GPU sağlıyor. (Colab’da yeniyseniz, Google Colab’a başlamak için bu makaleye göz atın!)

Colab kullandığım için PyTorch'u içeri alarak başlamam gerekiyordu. Colab kullanmıyorsanız bunu yapmanız gerekmez.

*** GÜNCELLEME! (01/29) *** Colab şimdi yerel PyTorch !!! Aşağıdaki kodu çalıştırmanıza gerek yoktur, ancak herhangi bir sorun yaşarsa diye bırakıyorum!

# Google Colab kullanıyorsanız PyTorch'u içe aktarın
# http://pytorch.org/
os.path'dan içe aktarma var
wheel.pep425tag'den 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] varsa ('/ dev / nvidia0') başka 'cpu'
! pip install -q http://download.pytorch.org/whl/{accelerator //tor-0////////////////}}}}}}}}}}} -
meşale almak

Sonra Pillow'la biraz sorun yaşadıktan sonra (Colab’daki arabası!) Devam ettim ve şunu koştum:

PIL ithal
Baskı (PIL.PILLOW_VERSION)

5.3.0 altında bir şey alırsanız, “Çalışma zamanı” altındaki “Çalışma zamanı” altındaki açılır menüyü kullanın ve bu hücreyi tekrar çalıştırın. Gitmek için iyi olmalısın!

Colab'a kurması inanılmaz derecede kolay olan bu proje için GPU kullanmak isteyeceksiniz. Sadece “çalışma zamanı” açılır menüsüne gidin, “çalışma zamanı türünü değiştir” i seçin ve ardından donanım hızlandırıcısı açılır menüsünde “GPU” yu seçin!

Sonra koşmayı severim

train_on_gpu = torch.cuda.is_available ()
değilse train_on_gpu:
    print ('Bummer! İşlemci eğitimi ...')
Başka:
    print ('Gitmekte iyisin! GPU'da eğitim ...')

Sadece çalıştığından emin olmak için. O zaman koş

device = torch.device ("cuda: 0", eğer torch.cuda.is_available () else "cpu")

Cihazı tanımlamak için

Bundan sonra, dosyaları alın. Veri setinizi orada sakladıysanız, Google Drive’ınızı monte etmek de dahil olmak üzere bunun bir sürü yolu var ki bu gerçekten basit. Bunu en faydalı çözüm olarak bulmadım, ancak bunu çok kolay ve kullanışlı olduğu için aşağıya dahil ediyorum.

google.colab ithalat sürücüsünden
drive.mount ( '/ içeriği / GDrive')

Ardından bir bağlantı göreceksiniz, buna tıklayın, erişime izin verin, açılan kodu kopyalayın, kutuya yapıştırın, enter tuşuna basın ve gitmeniz iyi olur! Sürücünüzü soldaki yan kutuda görmüyorsanız, sadece “yenile” düğmesine basmanız yeterlidir.

(Hücreyi çalıştırın, bağlantıyı tıklayın, sayfadaki kodu kopyalayın, kutuya yapıştırın, enter tuşuna basın ve sürücünüzü başarıyla monte ettiğinizde bunu göreceksiniz):

Aslında çok kolay!

Ancak, paylaşılan bir zip dosyası bağlantısını indirmek isterseniz (bu proje bu proje için daha kolay ve daha hızlı olur), şunları kullanabilirsiniz:

! wget
! unzip

Örneğin:

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

Bu size Udacity’nin saniye içindeki çiçek verilerini verecek!

(Küçük dosyalar yüklüyorsanız, onları doğrudan basit bir kodla doğrudan yükleyebilirsiniz. Ancak, isterseniz, ekranın sol tarafına gidebilir ve istemiyorsanız “dosyaları yükle” yi tıklayabilirsiniz. Yerel bir dosyayı almak için basit bir kod çalıştırmak gibi hissediyorum.)

Verileri yükledikten sonra kullanmak istediğim kütüphaneleri içe aktardım:

% matplotlib satır içi
% config InlineBackend.figure_format = 'retina'
ithalat zamanı
json ithal
ithalat kopyası
matplotlib.pyplot dosyasını plt olarak al
seans ithalatı
nump np olarak içe aktar
PIL ithal
PIL'den içe aktarma Image
koleksiyonlardan ithalat OrderedDict
meşale almak
meşale ithalatından nn, optim
torch.optim sitesinden import lr_scheduler
Torch.autograd ithalat değişkeninden
ithal meşale
Torchvision'dan ithal veri setleri, modeller, dönüşümler
Torch.utils.data.sampler İthalat SubsetRandomSampler
torch.nn dosyasını nn olarak içe aktar
F olarak torch.nn.functional dosyasını içe aktar

Sonraki veri dönüşümleri geliyor! Programınızın olabildiğince öğrenmesine yardımcı olmak için eğitim setinizde birkaç farklı dönüşüm türü kullandığınızdan emin olmak istersiniz. Döndürülmüş, döndürülmüş ve kırpılmış görüntülerde çalıştırarak daha sağlam bir model oluşturabilirsiniz.

Görüntü sapmalarını ağımıza aktarmadan önce normalleştirmek için standart sapmaların sağlandığı anlamına gelir, ancak görüntü tansörlerinin farklı boyutlarının ortalama ve standart sapma değerlerine bakarak da bulunabilirler. Resmi belgeler burada inanılmaz derecede yardımcı oluyor!

Resim sınıflandırıcım için basitleştirdim:

data_transforms = {
    'tren': dönüşümler.Compose ([
        transforms.RandomRotation (30),
        transforms.RandomResizedCrop (224),
        transforms.RandomHorizontalFlip (),
        transforms.ToTensor (),
        dönüşümler.Normalize ([0.485, 0.456, 0.406],
                             [0.229, 0.224, 0.225])
    ]),
    'valid': transforms.Compose ([
        transforms.Resize (256),
        transforms.CenterCrop (224),
        transforms.ToTensor (),
        dönüşümler.Normalize ([0.485, 0.456, 0.406],
                             [0.229, 0.224, 0.225])
    ])
}
# Veri setlerini ImageFolder ile yükleyin
image_datasets = {x: datasets.ImageFolder (os.path.join (data_dir, x),
                                          data_transforms [x])
                  ['tren' içindeki x için, 'geçerli']}
# Görüntü veri setlerini ve tren formlarını kullanarak veri yükleyicileri tanımlayın
batch_size = 64
dataloaders = {x: torch.utils.data.DataLoader (image_datasets [x], batch_size = batch_size,
                                             shuffle = Doğru, num_workers = 4)
              ['tren' içindeki x için, 'geçerli']}
class_names = image_datasets ['tren'].
dataset_sizes = ['tren', 'geçerli'] içindeki x için {x: len (image_datasets [x])}
class_names = image_datasets ['tren'].

Yukarıda gördüğünüz gibi, parti kodunu, veri yükleyicileri ve sınıf kodlarını yukarıdaki kodda tanımladım.

Verilere çok hızlı bir şekilde göz atmak ve cihazımı kontrol etmek için koştum:

Baskı (dataset_sizes)
Baskı (cihaz)
{'train': 6552, 'geçerli': 818}
cuda: 0

Daha sonra, etiket numarasından ve gerçek çiçek adından bazı eşlemeler yapmamız gerekir. Udacity, bu haritalamanın basit bir şekilde yapılması için bir JSON dosyası sağlamıştır.

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

Veri yükleyiciyi test etmek için:

resimler, etiketler = sonraki (iter (veri yükleyicileri ['train']))
rand_idx = np.random.randint (len (görüntüler))
# Yazdır (rand_idx)
print ("label: {}, sınıf: {}, ad: {}". formatı (etiketler [rand_idx] .item (),
                                               class_names [etiketler [rand_idx] .item ()],
                                               cat_to_name [class_names [etiketler [rand_idx] .item ()]]))

Şimdi daha da heyecanlanmaya başlıyor! Son birkaç yılda, bilgisayarlı görme problemlerinde tekrar kullanmak için çoğumuzdan daha nitelikli, insanlar tarafından çok sayıda model yaratılmıştır. PyTorch, önceden eğitilmiş modellerin yüklenmesini ve bunlara göre inşa edilmesini kolaylaştırır; bu tam da bu proje için yapacağımız şeydir. Model seçimi tamamen size kalmış!

ResNet, AlexNet ve VGG gibi en popüler önceden eğitilmiş modellerden bazıları ImageNet Challenge'dan geliyor. Bu önceden eğitilmiş modeller, bu kadar büyük miktarda bilgisayar gücü, sabır ve zaman gerektirmeden başkalarının bilgisayar görüntüsünde en yeni sonuçları elde etmelerini sağlar. Aslında DenseNet ile harika sonuçlar elde ettim ve nispeten hızlı bir şekilde çok iyi sonuçlar veren DenseNet161'i kullanmaya karar verdim.

Bunu çalıştırarak hızlıca ayarlayabilirsiniz

model = modeller.densenet161 (önceden tanımlanmış = Doğru)

ancak kendinize bir model, optimize edici ve programlayıcı seçimi vermek daha ilginç olabilir. Mimaride bir seçim yapmak için,

model_name = 'densenet' #vgg
eğer model_adı == 'densenet':
    model = modeller.densenet161 (önceden tanımlanmış = Doğru)
    num_in_features = 2208
    Baskı (model)
elif model_adı == 'vgg':
    model = models.vgg19 (önceden tanımlanmış = Gerçek)
    num_in_features = 25088
    Baskı (model.classifier)
Başka:
    baskı ("Bilinmeyen model, lütfen 'densenet' veya 'vgg'" seçin)

hızlı bir şekilde alternatif bir model oluşturmanıza olanak sağlar.

Ondan sonra, sizin için en uygun parametreleri kullanarak sınıflandırıcınızı oluşturmaya başlayabilirsiniz. Devam ettim ve inşa ettim

model.parameters () içindeki param için:
    param.requires_grad = Yanlış
def build_classifier (num_in_features, hidden_layers, num_out_features):
   
    classifier = nn.Sequential ()
    eğer hidden_layers == Yok:
        classifier.add_module ('fc0', nn.Linear (num_in_features, 102))
    Başka:
        layer_sizes = zip (hidden_layers [: - 1], hidden_layers [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))
        i için, (h1, h2) numaralandırılmış (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 ('damla' + str (i + 1), nn.Dropout (.5))
        classifier.add_module ('output', nn.Linear (hidden_layers [-1], num_out_features)
        
    dönüş sınıflandırıcısı

Bu, kullandığım gizli katmanların sayısını değiştirmenin ve bırakma oranını hızlı bir şekilde ayarlamanın kolay bir yolunu sağlar. Modelinizi daha iyi bilemek için ilave ReLU ve bırakma katmanları eklemeye karar verebilirsiniz.

Ardından, sınıflandırıcı parametrelerinizi eğitmeye çalışın. Özellik parametrelerini dondururken sadece burada sınıflandırıcı parametrelerini çalıştığımdan emin olmaya karar verdim. Optimize edici, ölçüt ve zamanlayıcı ile istediğiniz kadar yaratıcı olabilirsiniz. Kriter, model uyumunu değerlendirmek için kullanılan yöntemdir, optimize edici ağırlıkları güncellemek için kullanılan optimizasyon yöntemidir ve programlayıcı, optimizasyon sırasında kullanılan öğrenme hızını ve adım boyutunu ayarlamak için farklı yöntemler sunar.

Size en iyi sonucu neyin verdiğini görmek için mümkün olduğunca çok seçenek ve kombinasyon deneyin. Tüm resmi belgelere buradan bakabilirsiniz. Bir göz atmanızı ve ne kullanmak istediğiniz konusunda kendi kararlarınızı vermenizi öneririm. Kelimenin tam anlamıyla sınırsız sayıda seçeneğiniz yok, ancak oyun oynamaya başladığınızda böyle bir şey olduğu kesin!

hidden_layers = Yok
classifier = build_classifier (num_in_features, hidden_layers, 102)
Baskı (sınıflandırıcı)
# Sadece sınıflandırıcı parametrelerini eğitin, özellik parametreleri dondurulmuş
eğer model_adı == 'densenet':
    model.classifier = sınıflandırıcı
    ölçüt = nn.CrossEntropyLoss ()
    optimizer = optim.Adadelta (model.parameters ())
    sched = optim.lr_scheduler.StepLR (iyileştirici, step_size = 4)
elif model_adı == 'vgg':
    model.classifier = sınıflandırıcı
    ölçüt = nn.NLLLoss ()
    optimizer = optim.Adam (model.classifier.parameters (), lr = 0.0001)
    sched = lr_scheduler.StepLR (iyileştirici, step_size = 4, gama = 0.1)
Başka:
    geçmek

Şimdi modelinizi geliştirmenin zamanı geldi.

# Https://pytorch.org/tutorials/beginner/transfer_learning_tutorial.html adresinden uyarlanmıştır.
def train_model (model, ölçüt, iyileştirici, sched, num_epochs = 5):
    since = time.time ()
best_model_wts = copy.deepcopy (model.state_dict ())
    best_acc = 0.0
aralıktaki epoch için (num_epochs):
        print ('Epoch {} / {}'. formatı (epoch + 1, num_epochs))
        Yazdır ('-' * 10)
# Her çağın bir eğitim ve onaylama aşaması vardır
        ['tren', 'geçerli'] aşaması için:
            eğer faz == 'tren':
                model.train () # Modeli eğitim moduna ayarla
            Başka:
                model.eval () # Modu değerlendirmek için modeli ayarla
running_loss = 0.0
            running_corrects = 0
# Veriyi tekrar eder.
            girişler için, veri yükleyicideki etiketler [faz]:
                inputs = inputs.to (cihaz)
                labels = labels.to (cihaz)
# Parametre gradyanlarını sıfırlayın
                optimizer.zero_grad ()
# İleri, ileriye doğru
                # eğer sadece trende takip geçmişi
                torch.set_grad_enabled ile (faz == 'tren'):
                    çıkışlar = model (girişler)
                    _, preds = meşale. maks (çıkış, 1)
                    kayıp = kriter (çıktılar, etiketler)
# Geri + sadece eğitim aşamasındaysanız optimize edin
                    eğer faz == 'tren':
                        # Sched.step ()
                        loss.backward ()
                        
                        optimizer.step ()
# İstatistik
                running_loss + = loss.item () * inputs.size (0)
                running_corrects + = torch.sum (preds == labels.data)
epoch_loss = running_loss / dataset_sizes [phase]
            epoch_acc = running_corrects.double () / dataset_sizes [phase]
print ('{} Kayıp: {: .4f} Acc: {: .4f}'. formatı (
                faz, epoch_loss, epoch_acc))
# Modeli kopyala
            eğer faz == 'geçerli' ve epoch_acc> best_acc:
                best_acc = epoch_acc
                best_model_wts = copy.deepcopy (model.state_dict ())
Baskı ()
time_elapsed = time.time () - o zamandan beri
    print ('Eğitim {: .0f} m {: .0f} s'.format (içinde tamamlandı)
        time_elapsed // 60, time_elapsed% 60))
    print ('En iyi değer Acc: {: 4f}'. formatı (best_acc))
# En iyi model ağırlıklarını yükle
    model.load_state_dict (best_model_wts)
    
    dönüş modeli
çağlar = 30
model.to (cihaz)
model = train_model (model, ölçüt, iyileştirici, zamanlama, çağlar)

Çağlarımı kolayca izleyebilmek ve modelim çalışırken geçen süreyi takip etmek istedim. Yukarıdaki kod her ikisini de içerir ve sonuçlar oldukça iyi! Modelin hızlı bir şekilde öğrendiğini ve doğrulama setinin doğruluğunun epoch 7'ye göre% 95'in üzerine hızla ulaştığını görebilirsiniz!

Epoch 1/30
----------
tren kaybı: 2.4793 Acc: 0.4791
geçerli Kayıp: 0,9688 Acc: 0,8191

Epoch 2/30
----------
tren kaybı: 0.8288 Acc: 0.8378
geçerli Kayıp: 0,4714 Acc: 0,9010

Epoch 3/30
----------
tren kaybı: 0.5191 Acc: 0.8890
geçerli Kayıp: 0.3197 Acc: 0.9181

Epoch 4/30
----------
tren kaybı: 0,4064 Acc: 0,9095
geçerli Kayıp: 0.2975 Acc: 0.9169

Epoch 5/30
----------
tren Kaybı: 0,3401 Acc: 0,9214
geçerli Kayıp: 0.2486 Acc: 0.9401

Epoch 6/30
----------
tren kaybı: 0.3111 Acc: 0.9303
geçerli Kayıp: 0.2153 Acc: 0.9487

Epoch 7/30
----------
tren kaybı: 0.2987 Acc: 0.9298
geçerli Kayıp: 0.1969 Acc: 0.9584
...
Eğitim 67m 43s'de tamamlandı
En iyi val Acc: 0,973105

Bu kodu Google Colab’da GPU’da çalıştırmanın yalnızca bir saatten fazla sürdüğünü görebilirsiniz.

Şimdi değerlendirme zamanı

model.eval ()
doğruluk = 0
girişler için, veri yükleyicilerindeki etiketler ['valid']:
    girişler, etiketler = inputs.to (cihaz), labels.to (cihaz)
    çıkışlar = model (girişler)
    
    # En yüksek olasılıkla sınıf bizim öngörülen sınıfımızdır
    eşitlik = (labels.data == outputs.max (1) [1])
# Doğruluk = tüm tahminlere bölünen doğru tahmin sayısı
    doğruluk + = equality.type_as (torch.FloatTensor ()). mean ()
    
baskı ("Test doğruluğu: {: .3f}". formatı (doğruluk / len (veri yükleyicileri ['geçerli']))))
Test doğruluğu: 0.973

Kontrol noktanızı kaydetmeniz önemlidir

model.class_to_idx = image_datasets ['train'].
kontrol noktası = {'input_size': 2208,
              'çıktı_ boyutu': 102,
              'çağlar': çağlar,
              'batch_size': 64,
              'model': modeller.densenet161 (pretrained = Doğru),
              'sınıflandırıcı': sınıflandırıcı,
              'Zamanlayıcı': Zamanlama,
              'optimizer': optimizer.state_dict (),
              'state_dict': model.state_dict (),
              'class_to_idx': model.class_to_idx
             }
   
torch.save (kontrol noktası, 'kontrol noktası.pth')

Tüm parametreleri kaydetmeniz gerekmez, ancak bunları örnek olarak buraya ekliyorum. Bu kontrol noktası modeli önceden eğitilmiş bir densenet161 mimarisi ile özellikle korur, ancak kontrol noktanızı iki seçenekle kaydetmek isterseniz, kesinlikle bunu yapabilirsiniz. Sadece giriş boyutunu ve modelini ayarlayın.

Artık kontrol noktanızı yükleyebilirsiniz. Projenizi Udacity çalışma alanına gönderiyorsanız, işler biraz zorlaşabilir. Denetim noktası yükünüzle ilgili sorunları gidermeye yardımcı olacak bazı noktalar.

Anahtarlarınızı çalıştırarak kontrol edebilirsiniz.

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

Ardından modelinizi yükleyin ve yeniden kurun!

def load_checkpoint (dosya adı):
    denetim noktası = torch.load (dosya adı)
    model = denetim noktası ['model']
    model.classifier = checkpoint ['classifier']
    model.load_state_dict (kontrol noktası [ 'state_dict'])
    model.class_to_idx = kontrol noktası ['class_to_idx']
    optimizer = kontrol noktası ['optimizer']
    epochs = kontrol noktası ['epochs']
    
    model.parameters () içindeki param için:
        param.requires_grad = Yanlış
        
    dönüş modeli, kontrol noktası ['class_to_idx']
model, class_to_idx = load_checkpoint ('checkpoint.pth')

Devam etmek ister misin? Bazı görüntü ön işleme ve sınıflandırma için çıkarım yapmak iyi bir fikirdir. Devam edin ve resim yolunuzu tanımlayın ve bir resim açın:

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

Resminizi işleyin ve işlenmiş bir resme bakın:

def process_image (resim):
    '' 'PyTorch modeli için PIL görüntüsünü ölçeklendirir, kırpar ve normalleştirir,
        Numpy dizisi döndürür
    ' ''
    # PyTorch modelinde kullanmak için bir PIL görüntüsü işle
    # tensor.numpy (). devrik (1, 2, 0)
    preprocess = transforms.Compose ([
        transforms.Resize (256),
        transforms.CenterCrop (224),
        transforms.ToTensor (),
        dönüşümler.Normalize (ortalama = [0.485, 0.456, 0.406],
                             std = [0.229, 0.224, 0.225])
    ])
    image = ön işleme (image)
    görüntü döndür
def imshow (resim, balta = Yok, başlık = Yok):
    "" "Tensör için gösterim." ""
    Balta Yok ise:
        incir, ax = plt.subplots ()
    
    # PyTorch tensörleri renk kanalının ilk boyut olduğunu varsayıyor
    # ama matplotlib üçüncü boyut olduğunu varsayar
    image = image.numpy (). transpose ((1, 2, 0))
    
    # Önişlemeyi geri al
    ortalama = np.array ([0.485, 0.456, 0.406])
    std = np.array ([0.229, 0.224, 0.225])
    image = std * görüntü + ortalama
    
    # Görüntünün 0 ile 1 arasında kırpılması gerekiyor veya görüntülendiğinde ses gibi görünüyor
    image = np.clip (resim, 0, 1)
    
    ax.imshow (görüntü)
    
    dönüş baltası
Image.open ile ('flower_data / valid / 102 / image_08006.jpg') resim olarak:
    plt.imshow (görüntü)
model.class_to_idx = image_datasets ['train'].

Tahmin için bir işlev oluşturun:

def predict2 (image_path, model, topk = 5):
    '' 'Eğitimli bir derin öğrenme modeli kullanarak bir görüntünün sınıfını (veya sınıflarını) tahmin edin.
    ' ''
    
    # Sınıfı bir resim dosyasından tahmin etmek için kodu uygulayın
    img = Image.open (image_path)
    img = process_image (img)
    
    # 2D görüntüyü 1D vektöre dönüştür
    img = np.expand_dims (img, 0)
    
    
    img = torch.from_numpy (img)
    
    model.eval ()
    girişler = Değişken (img). ile (cihaz)
    logits = model.forward (girişler)
    
    ps = F.softmax (logits, dim = 1)
    topk = ps.cpu (). topk (topk)
    
    return (e.data.numpy (). squeeze (). tolist () e topk'ta)

Görüntüler doğru formatta olduktan sonra, modelinizle ilgili öngörülerde bulunmak için bir işlev yazabilirsiniz. Yaygın bir uygulama, en muhtemel sınıfları ilk 5 ya da öylesine (genellikle üst KK olarak adlandırılır) tahmin etmektir. Sınıf olasılıklarını hesaplamak ve ardından KK'nin en büyük değerlerini bulmak istersiniz.

Bir tensördeki en büyük KK değerlerini elde etmek için k.topk () kullanın. Bu yöntem hem en yüksek k olasılığını hem de sınıflara karşılık gelen olasılıkların endekslerini döndürür. Modele eklediğiniz class_to_idx kullanarak veya verileri yüklemek için kullandığınız Görüntü Klasöründen bu indekslerden gerçek sınıf etiketlerine dönüştürmeniz gerekir. Sözlüğü tersine çevirdiğinizden emin olun ki indeksten sınıfa bir eşleme elde edin.

Bu yöntem bir görüntüye ve model kontrol noktasına giden yolu izlemeli, sonra olasılıkları ve sınıfları döndürmelidir.

img_path = 'flower_data / valid / 18 / image_04252.jpg'
Probs, sınıflar = tahmin 2 (img_path, model.to (cihaz))
Baskı (probs)
Baskı (sınıflar)
flower_names = [cat_to_name [class_names [e]] sınıflardaki e]
Baskı (flower_names)

Modelimin performansından oldukça memnun kaldım!

[0.9999195337295532, 1.4087702766119037e-05, 1.3897360986447893e-05, 1.1400215043977369e-05, 6.098791800468462e-06]
[12, 86, 7, 88, 40]
['perulu zambak', 'çöl gülü', 'kral protea', 'manolya', 'kılıç zambak']

Temel olarak, belirttiğim görüntünün bir Perulu Zambak olması neredeyse% 100 ihtimal. Bir göz atmak ister misin? Giriş görüntüsüyle birlikte bir çubuk grafikteki ilk beş sınıfın olasılıklarını çizmek için matplotlib'i kullanmayı deneyin:

def view_classify (img_path, prob, sınıflar, haritalama):
    '' 'Bir görüntüyü görüntüleme işlevi ve öngörülen sınıflar.
    ' ''
    image = Image.open (img_path)
incir, (ax1, ax2) = plt.subplots (figsize = (6,10), ncols = 1, nrows = 2)
    çiçek_adı = eşleme [img_path.split ('/') [- 2]]
    ax1.set_title (flower_name)
    ax1.imshow (görüntü)
    ax1.axis ( 'kapalı')
    
    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 () # etiketleri yukarıdan aşağıya okunur
    ax2.set_title ('Sınıf Olasılığı')
view_classify (img_path, problar, sınıflar, cat_to_name)

Böyle bir şey görmelisin:

Söylemeliyim ki, bundan çok mutluyum! Tahminlerinizin çeşitli görüntülerde ne kadar yakın olduğunu görmek için birkaç görüntüyü test etmenizi öneririm.

Şimdi kendinize ait bir model oluşturma zamanı geldi ve aşağıdaki cevaplara nasıl girdiğini söyleyin!

Fotoğraf Pez González Unsplash'ta

Derin öğrenme veya makine öğrenme modelinizi bitirdiniz, ancak bundan sonra ne yapacağınızı bilmiyor musunuz? Neden internete dağıtmıyorsun?

Modelini oraya çıkar ki herkes görsün!

Makine öğrenim modelinizi Flask ile nasıl dağıtacağınızı öğrenmek için bu makaleye göz atın!