[PYTHON] Ich habe mit Pytorch versucht, Bilder von "Moon and Suppon" zu erkennen (mit torchvision.datasets.ImageFolder, das from_from_directry of keras entspricht).

Mond und Suppon

Der Mond und das Suppon sind ähnlich rund, aber der Unterschied ist so groß, dass sie nicht verglichen werden können. Das Gleichnis, dass die beiden so unterschiedlich sind. https://dictionary.goo.ne.jp/word/%E6%9C%88%E3%81%A8%E9%BC%88/

Es scheint einen großen Unterschied zu geben, also versuchen wir es mit der Bilderkennung mithilfe von Deep Learning!

Ich werde auch Pytorch (ein wenig) nach Bedarf erklären. (Wenn Sie einen Fehler machen, korrigieren Sie ihn bitte. Vielen Dank.)

Der Code ist hier. https://github.com/kyasby/Tuki-Suppon.git

Dieses Schlüsselwort

"Mond und Suppon"

Es scheint ähnlich und anders zu sein.

Pytorch "Fackel Vision.datasets.ImageFolder」

Ich habe es gemacht, weil es nicht viele Artikel gab, die torchvision.datasets.ImageFoldervonpytorch verwendeten, was keras from_from_directry` entspricht. Wenn Sie ein Bild in den Ordner legen, wird es automatisch beschriftet. Praktisch.

Pytorch "Fackel.utils.data.random_split」

Dank dessen müssen Zug und Test nicht getrennt werden, wenn Fotos in einem Ordner abgelegt werden.

Zu verwendende Daten

Von Google Image ・ 67 Bilder von Suppon Wir haben Bilder gesammelt, die aussehen, als wären sie von oben über der Muschel zu sehen. Zum Beispiel ein Bild wie dieses. image.png (Pii-sans Suppon) http://photozou.jp/photo/show/235691/190390795

・ 70 Bilder des Mondes Ich habe Bilder von runden Monden gesammelt. Ich schneide es von Hand aus, so dass ein großer Kreis auf dem Bildschirm erscheint. Zum Beispiel ein Bild wie dieses. image.png

Datensatzerstellung

.
├── main.ipynb
├── pics
   ├── tuki
   |     |-tuki1.png
   |     |-tuki2.png
   |        
   └── kame
        |-kame1.png
        |-kame2.png

Da die Bilder in Verzeichnisse unterteilt sind, verwenden Sie "torchvision.datasets.ImageFolde", um jedes Verzeichnis automatisch zu kennzeichnen.

Modulimport

import matplotlib.pyplot as plt
import numpy as np
import copy
import time
import os
from tqdm import tqdm

import torchvision.transforms as transforms
import torchvision.models as models
import torchvision

import torch.nn as nn
import torch

Vorverarbeitung

transform_dict = {
        'train': transforms.Compose(
            [transforms.Resize((256,256)),
             transforms.RandomHorizontalFlip(),
             transforms.ToTensor(),
             transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                  std=[0.229, 0.224, 0.225]),
             ]),
        'test': transforms.Compose(
            [transforms.Resize((256,256)),
             transforms.ToTensor(),
             transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                  std=[0.229, 0.224, 0.225]),
             ])}

Erstellen Sie ein Vorverarbeitungswörterbuch für Zug und Test. Sie können eine Vorverarbeitungssequenz erstellen, indem Sie "transforms.Compose" verwenden. Es scheint, dass sie in der Reihenfolge verarbeitet werden, in der sie in die Argumente aufgenommen wurden.

Diesmal, transforms.Resize(256, 256) → Ändern Sie die Größe des Bildes auf 256x256.

transforms.RandomHorizontalFlip() → Erstellen Sie ein Bild, das horizontal gespiegelt wird.

transforms.ToTensor() → PIL oder numpy.ndarray ((Höhe x Breite x Kanal) (0 ~ 255)) Zu Es wird in Tensor konvertiert ((Kanal x Höhe x Breite) (0,0 ~ 1,0)).

In PIL und Numpy liegen die Bilder in der Reihenfolge (Höhe x Breite x Kanal), in Pytorch ist jedoch zu beachten, dass (Kanal x Höhe x Breite). Es scheint, dass diese Bestellung einfacher zu handhaben ist.

transforms.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225]) → Normalisiert jeden GRB mit dem angegebenen Mittelwert und der Standardabweichung.

Dokument https://pytorch.org/docs/stable/torchvision/transforms.html

Datensatz

# ex.
# data_folder = "./pics"
# transform   = transform_dict["train"]

data = torchvision.datasets.ImageFolder(root=data_folder, transform=transform_dict[phase])

Erstellen Sie einen Datensatz aus dem obigen Verzeichnis.

Trennung von Zug und Test

# ex.
# train_ratio = 0.8

train_size = int(train_ratio * len(data))
# int()Zu einer ganzen Zahl.
val_size  = len(data) - train_size      
data_size  = {"train":train_size, "val":val_size}
#          =>{"train": 112,       "val": 28}
data_train, data_val = torch.utils.data.random_split(data, [train_size, val_size])

torch.utils.data.random_split(dataset, lengths) Teilt den Datensatz ** zufällig **, ** ohne Deckung **. Natürlich ist der Datensatz Sie können die Anzahl der Datensätze in einer Liste an Längen übergeben.

Ich habe auch den Zug und gültige Datengrößen im Wörterbuch gespeichert.

# ex.
# data_train => Subset(data, [4,5,1,7])
# data_val  => Subset(data, [3,8,2,6])

Es gibt so viele Rückgabewerte wie Listenlängen. Jeder Rückgabewert enthält eine Liste von Datensätzen und Indexnummern.

(Was ist Teilmenge?)

Datenlader

train_loader = torch.utils.data.DataLoader(data_train, batch_size=batch_size, shuffle=True)
val_loader   = torch.utils.data.DataLoader(data_val,   batch_size=batch_size, shuffle=False)
dataloaders  = {"train":train_loader, "val":val_loader}

Erstellen Sie einen Datenlader. In Pytorch wird ein Datenlader erstellt und die Daten auf diese Weise gelesen. Ich habe dies auch in das Wörterbuch aufgenommen.

Überprüfen Sie das Bild

def imshow(img):
    img = img / 2 + 0.5     
    npimg = img.numpy()
    plt.imshow(np.transpose(npimg, (1, 2, 0)))
    plt.show()

#Erfassen Sie nach dem Zufallsprinzip Trainingsdaten
dataiter = iter(dataloaders["train"])
images, labels = dataiter.next()

#Bildschirm
imshow(torchvision.utils.make_grid(images))
#Anzeige des Etiketts
print(' '.join('%5s' % labels[labels[j]] for j in range(8)))

Es scheint, dass der obige Code es so anzeigt. Ich habe es von hier bekommen. Https://qiita.com/kuto/items/0ff3ccb4e089d213871d スクリーンショット 2020-04-20 18.37.17.png

Modellieren

model = models.resnet18(pretrained=True)
for param in model.parameters():
    print(param)
# => Parameter containing:
#tensor([[[[-1.0419e-02, -6.1356e-03, -1.8098e-03,  ...,  5.6615e-02,
#            1.7083e-02, -1.2694e-02],
#          ...
#           -7.1195e-02, -6.6788e-02]]]], requires_grad=True)

Das Modell verwendet ResNet18. Indem Sie "pretrained = True" in das Argument einfügen, können Sie das trainierte Modell verwenden. Das Transferlernen wird durchgeführt, ohne vorhandene Parameter zu lernen. Das als require_grad = True angezeigte Gewicht wird aktualisiert. Stellen Sie Folgendes ein, um eine Aktualisierung zu verhindern.

model
# => ResNet(
#   (conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
#   (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
#   (relu): ReLU(inplace=True)
#   (maxpool): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
#   (layer1): Sequential(
#     (0): BasicBlock(
#       (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
#       (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
#       (relu): ReLU(inplace=True)
#       (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
#       (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
#     )
#   ...
#   (avgpool): AdaptiveAvgPool2d(output_size=(1, 1))
#   (fc): Linear(in_features=512, out_features=1000, bias=True)
# )

Ich wusste, dass die letzte Schicht "(fc)" war, also

for p in model.parameters():
    p.requires_grad=False
model.fc = nn.Linear(512, 2)

Verwenden Sie model.parameters (), um alle Parameter abzurufen, setzen Sie require_grad = False und überschreiben Sie die letzte Ebene.

Lerneinstellungen


model = model.cuda() #Wenn Sie keine GPU haben, benötigen Sie diese Leitung nicht.
lr = 1e-4
epoch = 40
optim = torch.optim.Adam(model.parameters(), lr=lr, weight_decay=1e-4)
criterion = nn.CrossEntropyLoss().cuda() #Ohne GPU.cuda()Ich brauche es nicht

Wenn Sie eine GPU verwenden möchten, müssen Sie das Modell an die GPU senden.

Das Modell ist fast das gleiche wie im Tutorial. https://pytorch.org/tutorials/beginner/transfer_learning_tutorial.html

Modellieren


def train_model(model, criterion, optimizer, scheduler=None, num_epochs=25):
    #:Gibt den Bool-Wert zurück.
    use_gpu = torch.cuda.is_available()
    #Startzeit
    since = time.time()
    
    best_model_wts = copy.deepcopy(model.state_dict())
    best_acc = 0.0
    
    #Erstellen Sie ein Wörterbuch mit einer Liste zum Speichern des Fortschritts.
    loss_dict ={"train" : [],  "val" : []}
    acc_dict = {"train" : [],  "val" : []}  

    for epoch in tqdm(range(num_epochs)):
        if (epoch+1)%5 == 0:#Die Epoche wird alle fünf Male angezeigt.
            print('Epoch {}/{}'.format(epoch, num_epochs - 1))
            print('-' * 10)
        
        #Trainiere in jeder Epoche,Val ausführen.
        #Die im Wörterbuch enthaltene Leistung wird hier demonstriert, und Sie können Zug und Wert auf einmal schreiben.
        for phase in ['train', 'val']:
            if phase == 'train':
                model.train()   #Lernmodus. Dropout etc. machen
            else:
                model.val()  #Inferenzmodus. Nicht aussteigen.
            
            running_loss = 0.0
            running_corrects = 0
            
            for data in dataloaders[phase]:
                inputs, labels = data #Die von ImageFolder erstellten Daten sind
                                      #Sie erhalten ein Etikett für Ihre Daten.
                
                #Nicht erforderlich, wenn keine GPU verwendet wird
                if use_gpu:
                    inputs = inputs.cuda()
                    labels = labels.cuda()
                
                

                #~~~~~~~~~~~~~~forward~~~~~~~~~~~~~~~
                outputs = model(inputs)

                _, preds = torch.max(outputs.data, 1)
               #torch.max gibt den tatsächlichen Wert und den Index zurück.
               #torch.max((0.8, 0.1),1)=> (0.8, 0)
               #Argument 1 ist, ob der Maximalwert in Zeilen- oder Spaltenrichtung zurückgegeben werden soll.
                loss = criterion(outputs, labels)

                if phase == 'train':
                    optimizer.zero_grad()
                    loss.backward()
                    optimizer.step()
                
                # statistics #Artikel ohne GPU()Nicht notwendig
                running_loss += loss.item() * inputs.size(0) 
                running_corrects += torch.sum(preds == labels)
                # (preds == labels)Ist[True, True, False]Usw., aber
                #Python True,Falsch ist jeweils 1,Da es 0 entspricht,
                #Sie können mit Summe addieren.
               
               #Speichern Sie den Fortschritt in der Liste
               loss_dict[phase].append(epoch_loss)
               acc_dict[phase].append(epoch_acc)

            #Teilen Sie durch die Anzahl der Proben, um den Durchschnitt zu erhalten.
            #Das Einfügen der Anzahl von Samples in das Wörterbuch wird zum Leben erweckt.
            epoch_loss = running_loss / data_size[phase]
            #Artikel ohne GPU()Nicht notwendig
            epoch_acc = running_corrects.item() / data_size[phase]

           #tensot().item()Sie können den Wert mithilfe von aus dem Tensor abrufen.
           #print(tensorA)       => tensor(112, device='cuda:0')
           #print(tensorA.itme)) => 112
                        
            #Ich benutze Format,.Mit nf können Sie bis zu n Nachkommastellen ausgeben.
            #Es ist das gleiche wie C-Sprache.
            print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase, epoch_loss, epoch_acc))
            
            # deep copy the model
            #Speichern Sie das Modell, wenn sich die Genauigkeit verbessert
            if phase == 'val' and epoch_acc > best_acc:
                best_acc = epoch_acc
                best_model_wts = copy.deepcopy(model.state_dict())
            #Ohne Deepcopy Modell.state_dict()Aufgrund von Änderungen im Inhalt
            #Die kopierten (Soll-) Daten ändern sich ebenfalls.
            #Der Unterschied zwischen Kopie und Deepcopy ist in diesem Artikel leicht zu verstehen.
            # https://www.headboost.jp/python-copy-deepcopy/

    time_elapsed = time.time() - since
    print('Training complete in {:.0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60))
    print('Best val acc: {:.4f}'.format(best_acc))
    
    #Liest und gibt das beste Gewicht zurück.
    model.load_state_dict(best_model_wts)
    return model, loss_dict, acc_dict

Lernen

model_ft, loss, acc = train_model(model, criterion, optim, num_epochs=epoch)

Lernen visualisieren


#loss,Nehmen Sie gem.
loss_train = loss["train"]
loss_val   = loss["val"]

acc_train = acc["train"]
acc_val   = acc["val"]


#Wenn Sie so schreiben, können Sie ein Diagramm mit Zeilen x Spalten erstellen.
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(10,5))

#0. Grafik
axes[0].plot(range(epoch), loss_train, label = "train")
axes[0].plot(range(epoch), loss_val,    label =  "val")
axes[0].set_title("Loss")
axes[0].legend()#Beschriftung jedes Diagramms anzeigen

#1. Grafik
axes[1].plot(range(epoch), acc_train, label = "train")
axes[1].plot(range(epoch), acc_val,    label =  "val")
axes[1].set_title("Train Loss")
axes[1].legend()

#Stellen Sie so ein, dass sich das 0. und 1. Diagramm nicht überlappen
fig.tight_layout()

Überlernen Sie in etwa 11 oder 12 Epochen? image.png

Bonus

GoogleColabolatory Es gibt eine Zusammenarbeit als einfache Möglichkeit, die GPU zu verwenden. https://colab.research.google.com/notebooks/welcome.ipynb?hl=ja Wenn Sie Bilder in Zusammenarbeit verwenden, können Sie sie bequem als Zip hochladen. (Es ist schwierig, eine nach der anderen hochzuladen.) (Die Methode zum Verknüpfen mit dem Laufwerk ist ebenfalls in Ordnung.) Zu diesem Zeitpunkt kann die Dekomprimierung wie folgt durchgeführt werden.

#/content/pics.Bitte ändern Sie jede Postleitzahl.
!unzip /content/pics.zip -d /content/data > /dev/null 2>&1 &

Auch "Pfad kopieren", der angezeigt wird, wenn Sie mit der rechten Maustaste auf die Datei klicken, ist praktisch.

matplotlib.plt Dieses Mal gebe ich ein Diagramm mit 1 Zeile und 2 Spalten aus. Wenn es sich jedoch beispielsweise um 2 Zeilen und 2 Spalten handelt, können Sie ein Diagramm wie folgt erstellen. Sie können auch ein Diagramm in einem Diagramm überschreiben und zwei gleichzeitig zeichnen. Ich habe jeweils zwei für jedes Diagramm gezeichnet.

loss_train = loss["train"]
loss_val    = loss["val"]

acc_train = acc["train"]
acc_val    = acc["val"]

fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10,5))
axes[0,0].plot(range(epoch), loss_train, label = "train")
axes[0,0].plot(range(epoch), loss_val,    label =  "val")
axes[0,0].set_title("Loss")
axes[0,0].legend()

axes[0,1].plot(range(epoch), acc_train, c="red",  label = "train")
axes[0,1].plot(range(epoch), acc_val,    c="pink", label =  "val")
axes[0,1].set_title("Train Loss")
axes[0,1].legend()

x = np.random.rand(100)
xx = np.random.rand(200)
axes[1,0].hist(xx, bins=25, label="xx")
axes[1,0].hist(x, bins=50,   label="x")
axes[1,0].set_title("histgram")

y = np.random.randn(100)
z = np.random.randn(100)
axes[1,1].scatter(y, z, alpha=0.8, label="y,z") 
axes[1,1].scatter(z, y, alpha=0.8, label="z,y")
axes[1,1].set_title("Scatter")
axes[1,1].legend()

fig.tight_layout()

image.png

Recommended Posts

Ich habe mit Pytorch versucht, Bilder von "Moon and Suppon" zu erkennen (mit torchvision.datasets.ImageFolder, das from_from_directry of keras entspricht).
Ich habe versucht, die handschriftliche Zeichenerkennung von Runenzeichen mit CNN mithilfe von Keras zu erkennen
Ich habe versucht, Bilder mit CIFAR-10 mit Keras-Learning- zu erkennen.
Ich habe versucht, Bilder von CIFAR-10 mit Keras-Bilderkennung zu erkennen.
[Python] Ich habe versucht, das Mitgliederbild der Idolgruppe mithilfe von Keras zu beurteilen
Ich habe versucht, eine einfache Bilderkennungs-API mit Fast API und Tensorflow zu erstellen
Ich habe versucht, Grad-CAM mit Keras und Tensorflow zu implementieren
Ich habe versucht, das Lachproblem mit Keras zu erkennen.
Ich habe versucht, das Gesichtsbild mit sparse_image_warp von TensorFlow Addons zu transformieren
Ich habe versucht, die Trefferergebnisse von Hachinai mithilfe der Bildverarbeitung zu erhalten
Ich habe versucht, datetime <-> string mit tzinfo mit strftime () und strptime () zu konvertieren.
Ich habe versucht, die Phase der Geschichte mit COTOHA zu extrahieren und zu veranschaulichen
Ich habe versucht, CVAE mit PyTorch zu implementieren
Ich habe mit Jupyter eine einfache Bilderkennung versucht
Ich habe versucht, die Genauigkeit der japanischen BERT- und der japanischen Distil-BERT-Satzklassifizierung mit PyTorch & Einführung der BERT-Technik zur Verbesserung der Genauigkeit zu vergleichen
Ich habe versucht, das Update von "Hameln" mit "Beautiful Soup" und "IFTTT" zu benachrichtigen.
Ich habe versucht, Kanas handschriftliche Zeichenerkennung Teil 3/3 Zusammenarbeit mit der GUI mithilfe von Tkinter durchzuführen
Ich habe versucht, Runenfiguren mit Scikit-Learn handschriftlich zu erkennen
Ich habe versucht, das Lesen von Dataset mit PyTorch zu implementieren
Ich habe versucht, Keras in TFv1.1 zu integrieren
Ich habe versucht, die Trapezform des Bildes zu korrigieren
Ich habe versucht, den Bildfilter von OpenCV zu verwenden
Ich habe versucht, das Update von "Werde ein Romanautor" mit "IFTTT" und "Werde ein Romanautor API" zu benachrichtigen.
Ich wollte viele Bilder sammeln, also habe ich versucht, "Google Image Download" zu verwenden.
Ich habe versucht, das Artikel-Update des Livedoor-Blogs mit Python und Selen zu automatisieren.
Ich habe versucht, den Text in der Bilddatei mit Tesseract der OCR-Engine zu extrahieren
Bildverarbeitung mit Python (ich habe versucht, es in 0 und 1 Mosaikkunst zu binarisieren)
Ich habe versucht, die Verarbeitungsgeschwindigkeit mit dplyr von R und pandas von Python zu vergleichen
Ich habe versucht, mit VOICEROID2 2 automatisch zu lesen und zu speichern
[OpenCV / Python] Ich habe versucht, Bilder mit OpenCV zu analysieren
Ich habe versucht, mit VOICEROID2 automatisch zu lesen und zu speichern
[Einführung in Pytorch] Ich habe versucht, Cifar10 mit VGG16 ♬ zu kategorisieren
Ich habe versucht, SSD jetzt mit PyTorch zu implementieren (Dataset)
Ich habe versucht, das Bild mithilfe von maschinellem Lernen zu komprimieren
[Grafikzeichnung] Ich habe versucht, ein mehrreihiges Balkendiagramm mit Matplotlib und Seaborn zu schreiben
Ich habe versucht, mit PI Fu aus einem Bild ein 3D-Modell einer Person zu erstellen
Ich habe versucht, Überlebende der Titanic mit Kaggle vorherzusagen und einzureichen
Ich habe versucht, das Bild mit Python + OpenCV "gammakorrektur" zu machen
Ich habe versucht, mit TensorFlow den Durchschnitt mehrerer Spalten zu ermitteln
Bildklassifizierung mit selbst erstelltem neuronalen Netzwerk von Keras und PyTorch
Ich habe versucht, die Informationen des Webs mit "Requests" und "lxml" abzurufen.
Ich habe versucht, MNIST nach GNN zu klassifizieren (mit PyTorch-Geometrie).
Ich habe versucht, ListNet of Rank Learning mit Chainer zu implementieren
Ich habe versucht, die Benutzeroberfläche neben Python und Tkinter dreiäugig zu gestalten
Ich habe versucht, SSD jetzt mit PyTorch zu implementieren (Modellversion)
Ich habe versucht, Pyenv zu verwenden, das ich ohne Essen hasste, und es war zu bequem, mich hinzusetzen.
Ich habe versucht, die Sprecheridentifikation mithilfe der Sprechererkennungs-API von Azure Cognitive Services mit Python zu überprüfen. # 1
Bilderkennung von Müll mit Edge (Raspberry Pi) aus null Wissen mit AutoML Vsion und TPU
Ich habe versucht, die Sprecheridentifikation mithilfe der Sprechererkennungs-API von Azure Cognitive Services in Python zu überprüfen. # 2
Ich habe versucht, die Höhen und Tiefen des Schlusskurses des Aktienkurses von Guru Navi mit TensorFlow vorherzusagen (Fortschritt)
Ich habe versucht, das Gesicht mit Face ++ zu erkennen
Bilderkennung mit Keras + OpenCV
Ich habe versucht, mit Pandas eine Pferderenn-Datenbank zu erstellen
Ich habe versucht, den Index der Liste mithilfe der Aufzählungsfunktion abzurufen
Ich habe versucht, die Bewässerung des Pflanzgefäßes mit Raspberry Pi zu automatisieren
Ich habe versucht, die Lesezeichen zu visualisieren, die mit Doc2Vec und PCA nach Slack fliegen
Ich habe versucht, Deep Learning mit Spark × Keras × Docker skalierbar zu machen
Ich habe versucht, mit Python einen regulären Ausdruck von "Zeit" zu erstellen
Ich habe versucht, das SD-Boot-Image von LicheePi Nano zu erstellen