Der gesamte Code in diesem Artikel lautet [Medizinischer KI-Online-Kurs, Kapitel 5, Praktische Ausgabe: Segmentierung von MRT-Bildern](https://japan-medical-ai.github.io/medical-ai-course-materials/notebooks/05_Image_Segmentation] Ich habe versucht zu verstehen, indem ich .html zitierte. </ b> Die ursprüngliche Online-Kurswebsite wurde von der ** Medical AI Society ** erstellt und ist eine sehr anspruchsvolle Seite.
Dieser Artikel ist eine selbsterklärende Organisation dieses ausgeklügelten Codes für Anfänger in Deep Learning. ** In erster Linie ist es jedoch am besten, die oben genannte Website zu besuchen. ** **.
Der erste ist der Daten-Download.
!if [ ! -d train ]; then curl -L -O https://github.com/mitmul/chainer-handson/releases/download/SegmentationDataset/train.zip && unzip train.zip && rm -rf train.zip; fi
!if [ ! -d val ]; then curl -L -O https://github.com/mitmul/chainer-handson/releases/download/SegmentationDataset/val.zip && unzip val.zip && rm -rf val.zip; fi
!
] **Ȇbrigens haben sich viele von Ihnen vielleicht gefragt, was das!
Hier am Anfang hängt.
!
Hinzufügen.Fahren wir mit der Erläuterung des Inhalts fort.
** Über [if
] **
--wenn xxx; dann ooo; fi
bedeutet, ooo auszuführen, wenn es xxx ist. Es ist fast das gleiche wie Englisch.
--Für Python schreiben Sie es wie wenn xxx: ooo.
――Dieses Mal handelt es sich um ein Shell-Skript, daher ist die Notation unterschiedlich, aber was Sie tun, ist dasselbe.
** Über [curl
] **
--curl
bedeutet ** Dateien von der Website abrufen **. (Wahrscheinlich wäre ein Befehl mit ähnlicher Funktionalität "wget" usw.)
-- -L
und -O
sind Optionen für curl
. Fügen Sie -L
hinzu, um die ** Umleitung ** zu aktivieren. Es scheint, dass -O
** Download mit dem Dateinamen der ursprünglichen Site ** bedeutet.
In diesem Fall können Sie durch Hinzufügen von "-O" die Dateien train.sip und val.zip von der gleichnamigen Zielseite von github.com herunterladen.
** Über [&&
] **
--&&
ist einer der sogenannten logischen Operatoren. In diesem Fall wird der nächste Befehl ausgeführt, wenn der vorherige Befehl beendet ist.
** Über [entpacken
] **
--unzip
bedeutet ** die Zip-Datei entpacken **. Entpacken Sie diesmal die komprimierten Dateien train.zip und val.zip in Ordner mit dem Namen train und val.
rm
] ** Über
--rm
ist ein ** Löschbefehl **. Ich habe die heruntergeladene Datei train.zip und val.zip erstellt, die mit unzip entpackt wurden, sodass ich sie nicht eingeben kann. Also lösche ich es.
--Die Option "-rf" sollte im Sinne eines stärkeren Löschens als "rm" ohne Hinzufügen von etwas verstanden werden.-r
wird häufig verwendet, wenn Sie ** Ordner und Dinge ** in einem Shell-Skript löschen möchten.%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
#Laden Sie Bilder mit der PIL-Bibliothek
img = np.asarray(Image.open('train/image/000.png'))
label = np.asarray(Image.open('train/label/000.png'))
#Zeigen Sie mit der matplotlib-Bibliothek zwei Bilder nebeneinander an
fig, axes = plt.subplots(1, 2)
axes[0].set_axis_off()
axes[0].imshow(img, cmap='gray')
axes[1].set_axis_off()
axes[1].imshow(label, cmap='gray')
plt.show()
** Über [% matplotlib inline
] **
Es ist wie ein Zaubertrick beim Schreiben von Python-Code im Notebook-Format. Wenn es Ihnen nichts ausmacht und Sie im ** Notizbuchformat ** schreiben (wenn Sie ein Jupyter-Notizbuch, ein Jupiter-Labor oder Google Colab verwenden), schreiben Sie dies.
** Über [von ooo import xxx als @@@
] **
import matplotlib.pyplot as plt
Es bedeutet, "pyplot" in der Bibliothek "matplotlib" als "plt" herunterzuladen.Als ich Python benutzte, hatte from PIL import Image
ein Problem, weil es ein Chaos war , as
am Ende, aber from
vorne zu setzen. (Vielleicht nur ich)
Dies bedeutet, dass nur der Teil mit dem Namen "Image" aus der Bibliothek mit dem Namen "PIL" importiert wird. Kurz gesagt, das Bild ist, dass es ein Werkzeug namens "Image" in einer großen Box namens "PIL" gibt.
Damit der Computer das Teil abrufen kann, muss ** ein großes Feld vor dem Teilenamen ** angegeben werden. Ich denke, es wird in Zukunft schwieriger sein, einen Fehler zu machen. ――Schreiben Sie auch mit dem Pfadnamen zuerst den Ordnernamen und extrahieren Sie dann die darin enthaltene Datei.
** Über [np.asarray ()
] [Image.open ()
] **
img = np.asarray(Image.open('train/image/000.png'))
Das zuvor heruntergeladene Bild wird mit "Image" gelesen, mit "numpy" in das Array-Format konvertiert und in einer Variablen namens "img" gespeichert (zugewiesen).
** Über [plt.subplots ()
] **
fig, axes = plt.subplots(1, 2)
--Die Zuordnung des mit "plt" zu zeichnenden Graphen wird festgelegt. Für "plt.subplots (1, 2)" 1 in vertikaler Richtung und 2 in horizontaler Richtung. Das heißt, die beiden Bilder sind horizontal ausgerichtet. Im Gegenteil, wenn es sich um "plt.subplots (2, 1)" handelt, werden zwei Blätter vertikal ausgerichtet.** Über [.set_axis_off ()
] **
axes[0].set_axis_off()
――Die erste Achse, die nebeneinander ausgerichtet ist, wird gelöscht. Wenn Sie dies nicht tun, bleibt die Skala erhalten und wird angezeigt. Ich möchte nur das Bild anzeigen, aber es ist ärgerlich.
-Der Grund für [0] ist, dass der ** Python-Index bei 0 beginnt **.Lass uns stetig gehen.
.imshow ()
] **
axes[0].imshow(img, cmap='gray')
Schließlich wird es mit plt.show ()
angezeigt. Es ist überhaupt nicht schwierig.
Aus diesem Bereich kam nun ein Gefühl des tiefen Lernens hervor. geben wir unser Bestes.
import glob
from chainer import datasets
def create_dataset(img_filenames, label_filenames):
img = datasets.ImageDataset(img_filenames)
img = datasets.TransformDataset(img, lambda x: x / 255.) # 0-Normalisiert auf 1
label = datasets.ImageDataset(label_filenames, dtype=np.int32)
dataset = datasets.TupleDataset(img, label)
return dataset
** Über [glob
] **
――Diese Bibliothek ist eine Bibliothek, die einen Ordner usw. angibt und den Pfad der darin enthaltenen Dateien im Listenformat abruft. Ich benutze es die ganze Zeit.
Obwohl die Funktionsweise von Dateien und Ordnern bei einer Bibliothek namens os etwas anders ist, können Sie etwas Ähnliches tun.
** Über [datasets.ImageDataset ()
] **
―― Laut der offiziellen Website verhält es sich so, als ob die Bilder im Listenformat vorliegen. Es ist sehr praktisch. ** Wie erwartet ist es PFN. ** **.
――Bei Angabe des Bildes geben Sie, wenn Sie dies verwenden, einfach den Pfad an. Das an den Pfad angepasste Bild wird im Format np.array zurückgegeben.
** Über [datasets.TransformDataset (img, lambda x: x / 255.)
] **
Haben Sie übrigens gehört, dass viele Bilder (8-Bit-Bilder) durch 256 Abstufungen ** von ** [0-255] ** dargestellt werden? (RGB, Graustufen usw.).
Wenn Sie mit Deep Learning lernen, ist es nicht sehr einfach, mit [0-255] umzugehen. Es scheint, dass es überwältigend [0-1] ist, das einfach zu handhaben ist. ――So dividieren Sie mit der Lambda-Funktion die Werte aller Pixel im Bild durch 255, um den Bereich auf [0-1] auszurichten.
** [0-255] → [0-1] **, richtig?
** Über [datasets.TupleDataset (img, label)
] **
Dies ist eine Funktion, die Variablen in Form eines Tupels zurückgibt, das eine Eins-zu-Eins-Entsprechung zwischen img und label aufweist. Wie bei jedem ** überwachten Lernen ** müssen die Ein- und Ausgänge übereinstimmen. Das macht es. ――Zum Beispiel: Selbst wenn Sie ein kardiales MRT-Bild haben, können Sie in diesem Fall nicht lernen, welcher Teil des Modells der linke Ventrikel ist, wenn Sie nicht zuordnen, welcher Teil der linke Ventrikel ist. Dies bereitet das Modell darauf vor.
def create_datasets():
#Name der MRT-Bilddatei mit Python Standard Glob/Holen Sie sich eine Liste der Namen der Etikettenbilddateien
train_img_filenames = sorted(glob.glob('train/image/*.png'))
train_label_filenames = sorted(glob.glob('train/label/*.png'))
#Erstellen Sie einen Datensatzobjektzug und übergeben Sie eine Liste
train = create_dataset(train_img_filenames, train_label_filenames)
#Machen Sie dasselbe für Validierungsdaten
val_img_filenames = sorted(glob.glob('val/image/*.png'))
val_label_filenames = sorted(glob.glob('val/label/*.png'))
val = create_dataset(val_img_filenames, val_label_filenames)
return train, val
** Über [glob.glob (... / *. Png)
] **
--glob.glob
ist derjenige, der die Liste der Pfade erhält, wie ich bereits erwähnt habe. Zum Beispiel in glob.glob ('train / image / *. Png')
** "alles in dem Ordner mit dem Namen image in dem Ordner mit dem Namen train, der mit der Erweiterung .png endet" Es bedeutet, ** zu bekommen.
--*
wird als Platzhalter bezeichnet " alle Zeichenketten mit einer Länge von 0 oder mehr ". Es ist eine Art regulärer Ausdruck. Es ist nützlich, sich daran zu erinnern. Ich erinnere mich auch daran.
** Über [sortiert (...)
] **
Der Inhalt der Liste ist nach Namen sortiert. Sortieren heißt sortieren.
――Wenn die Reihenfolge der Pfade, die im Inhalt von train_img_filenames
und train_label_filenames
enthalten sind, nicht in Ordnung ist und sie nicht übereinstimmen, denke ich, dass Sie sie verwenden, weil Sie sie nicht lernen können.
train, val = create_datasets()
print('Dataset size:\n\ttrain:\t{}\n\tvalid:\t{}'.format(len(train), len(val)))
In diesem Teil wird die Anzahl der in Zug und Wert enthaltenen Bilder überprüft. Die Nummer ist bereits beim Herunterladen offensichtlich, aber bei der tatsächlichen Codierung wäre es einfacher, sie so zu überprüfen.
Die Rückgabewerte (von return zurückgegebene Werte) der zuvor definierten Funktion create_datasets ()
werden in den Variablen train und val gespeichert.
――Es kommt vor, dass die Namen diesmal gleich sind, aber die von der Funktion create_datasets ()
erstellten Objekte train und val werden den Variablen train und val zugewiesen.
** Ich denke, es ist in Ordnung, print ()
** zu verwenden, aber vielleicht sind Sie es nicht gewohnt, wie \ n
, \ t
oder .format ()
zu schreiben. Hmm. \ n
ist ein Zeilenvorschub, \ t
ist ein Tabulatorzeichen und .format ()
wird durch Eingabe von Werten in das von '' eingeschlossene {} angezeigt.
Es ist nicht sehr cool,
print('Dataset size:')
print('train: '+str(len(train)))
print('val: '+str(len(val)))
Selbst wenn Sie dies tun, wird es wahrscheinlich mit einem ähnlichen Gefühl ausgegeben. Es ist nicht cool (zweites Mal).
Es ist keine Übertreibung zu sagen, dass dieses Kapitel der größte Berg, der Kern und der wichtigste Teil des Lernnetzwerks ist.
import chainer
import chainer.functions as F
import chainer.links as L
class MultiLayerPerceptron(chainer.Chain):
def __init__(self, out_h, out_w):
super().__init__()
with self.init_scope():
self.l1 = L.Linear(None, 100)
self.l2 = L.Linear(100, 100)
self.l3 = L.Linear(100, out_h * out_w)
self.out_h = out_h
self.out_w = out_w
def forward(self, x):
h = F.relu(self.l1(x))
h = F.relu(self.l2(h))
h = self.l3(h)
n = x.shape[0]
return h.reshape((n, 1, self.out_h, self.out_w))
Erinnern Sie sich übrigens alle an die Klasse? Was ist Vererbung?
Ich werde in der Reihenfolge erklären.
** Über [class MultiLayer Perceptron (chainer.Chain):
] **
Dies macht es einfach, ein neu definiertes "MultiLayerPerceptron ()" unter Verwendung einer vorhandenen Klasse namens "chainer.Chain" zu erstellen. ――Es ist für normale Menschen unmöglich, ein Auto aus dem Nichts zu machen, aber es scheint, dass Sie es immer noch tun können, indem Sie einfach die Farbe des Autos ändern (ich denke, dass tatsächlich spezielle Technologie erforderlich ist). Kurz gesagt, es ist uns unmöglich, ein Auto von Grund auf neu zu bauen, aber ** wir machen es so, dass wir nur ein Teil ändern und es bewegen können **.
** Über [super () .__ init __ ()
] **
--Dies ruft den Teil init () aus der übergeordneten Klasse auf (chainer.Chain in diesem Beispiel).
** Über [with self.init_scope ():
] **
――Ich weiß es nicht im Detail, aber ist dieser Teil eine charakteristische Schreibweise beim Erstellen eines Netzwerks mit Chainer? Ich werde die Ebene, die zum Lernen verwendet wird, hier einfügen. Ich werde mir von nun an den Inhalt ansehen.
** Über [self.l1 = L.Linear (None, 100)
] **
-Dies bedeutet, dass es in einer Variablen namens "l1" gespeichert wird, die in dieser Klasse gespeichert ist. Diesmal ist es L.Linear ()
. Wie Sie sehen können, ist das "L" oben im Originalcode
import chainer.links as L
Ist geschrieben.
Linear ()
? Anscheinend ist es eine vollständig verbundene Schicht. (Genau genommen kann es etwas anders sein)def forward(self, x):
def forward(self, x):
]
――Die Definition hier ist ** vorwärts **, dh ** vorwärts Propagierung **. Beim Deep Learning werden Werte in Ebenen von vorne nach hinten übergeben, um Eingabe in Ausgabe umzuwandeln. Ich mache es.
――Relu ist eine Relu-Funktion, nicht wahr? Es ist eine der ** Aktivierungsfunktionen **. Da es ein sehr großes ist, können viele Leute damit vertraut sein.
―― Beim Deep Learning wird die Eingabe in Schichten berechnet und durch die Aktivierungsfunktion ** nacheinander nichtlinear **.h = F.relu(self.l1(x))
h = F.relu(self.l2(h))
h = self.l3(h)
――Dieser Prozess wird nur der Reihe nach zugewiesen. --X (Beispiel: Array von Bildern), das von self.l1 verarbeitet wird, wird von der Relu-Funktion verarbeitet und h zugewiesen.
In diesem Kapitel `` def create_trainer (Stapelgröße, Zug, Wert, Stopp, Gerät = -1):
`
Definiert das Training für das Modell.
model = MultiLayerPerceptron(out_h=256, out_w=256)
Damit wird das zuvor erstellte Netzwerk dem Modell zugeordnet. Da das Eingabebild von "out_h = 256", "out_w = 256" 256 × 256 ist, stimmt es damit überein.
train_model = L.Classifier(
model, lossfun=F.sigmoid_cross_entropy, accfun=F.binary_accuracy)
L.classifier
] **sigmoid_cross_entropy
für die Verlustfunktion und binary_accuracy
für die acc-Funktion.optimizer = optimizers.Adam()
optimizer.setup(train_model)
optimaizer
] **
――Machen Sie so etwas wie das Ändern der Parameter während des Trainings. Diesmal verwenden Sie "Adam ()". Außerdem ist sgd ()
auch berühmt.Für den Rest des Trainers können Sie wahrscheinlich sagen, was Sie tun, indem Sie die Kommentare lesen, die Zeile für Zeile hinzugefügt werden.
%%time
trainer = create_trainer(64, train, val, (20, 'epoch'), device=0)
trainer.run()
--``` def create_trainer (Stapelgröße, Zug, Wert, Stopp, Gerät = -1): `` `der vorherigen Funktion Sie können sehen, was jeder Wert darstellt, indem Sie mit vergleichen. --64 Chargen, Training für Trainingsdaten, Validierungswert, Epochenstopp bei 20 und GPU oder CPU.
preds = []
for img, label in val:
img = cuda.to_gpu(img[np.newaxis], device)
pred = model(img)
pred = cuda.to_cpu(pred.data[0, 0] > 0)
preds.append((pred, label[0]))
pred_labels, gt_labels = zip(*preds)
――Das nächste, was ein Problem zu sein scheint, ist hier in `def evaluieren (Trainer, Wert, Gerät = -1):`
. Der Songwriter kann `to_gpu``` oder`
to_cpu``` sein.
――In Chainer muss unterschieden werden, ob das, was Sie gerade tun (sogar Pytorch usw.), auf GPU oder CPU ausgeführt wird.
to_gpu
wird das Bild, das das Material zum Lernen des Modells mit gpu ist, von cpu an gpu übergeben. (Ich denke)
--to_cpu
übergibt das Ergebnis auf gpu an cpu. (Ich denke)Die Elemente danach werden in der Faltungsschicht implementiert, aber abgesehen vom Verständnis von ** Kernel **, ** Schritt **, ** Pad ** usw. ist die Hauptlinie die obige vollständig verbundene Schicht. Ist dasselbe. (Um diese Punkte zu verstehen, lesen Sie bitte die entsprechende Website oder lesen Sie das Super-Major-Buch "Deep Learning von Grund auf neu".)
Experimentieren Sie und werden Sie ein Multi-Omics-Talent in der medizinischen Welt!
** Alle Codes in diesem Artikel sind aus dem oben genannten Online-Kurscode der Medical AI Society zitiert. ** **. ――Es ist ein ** sehr informativer Kurs ** für diejenigen, die sich für tiefes Lernen in der medizinischen Versorgung sowie für das Thema des Datensatzes interessieren. Versuch es bitte.
Chainer-Dokument --Buch "Deep Learning von Grund auf neu"
Ich dachte, ich wäre vorsichtig, aber ich denke, dass es wahrscheinlich viele falsche Beschreibungen gibt. Daher wäre es hilfreich, wenn Sie auf Fehler im Artikel hinweisen könnten.
Da die Entwicklung von Chainer eingestellt wurde, denke ich darüber nach, den obigen Code mit Pytorch neu zu schreiben, aber ich weiß nicht, ob ich es tun werde. Ich weiß auch nicht, ob ich es tun werde, weil es ziemlich schwierig war, ein Kapitel für andere Kapitel zu erstellen.
Dieser Beitrag basiert auf der akademischen Philosophie, "Forschung und Ausbildung im Bereich der medizinischen KI zu fördern und zur Entwicklung der modernen Medizin in Japan beizutragen", und soll denjenigen helfen, die gerade mit dem Programmieren begonnen haben. Dies ist eine Zusammenfassung dessen, was ich aus der Sicht einer erfahrenen Person mit wenig Erfahrung für notwendig hielt. Wir beanspruchen keine Rechte. Wenn Sie urheberrechtliche Probleme mit der Medical AI Society haben, kontaktieren Sie uns bitte.
Recommended Posts