forked from wieerwill/Informatik
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPraktikum BMT - Deep Learning in der Biomedizintechnik.tex
696 lines (579 loc) · 31.9 KB
/
Praktikum BMT - Deep Learning in der Biomedizintechnik.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
\documentclass[a4paper,10pt,titlepage]{scrartcl}
\usepackage[sc]{mathpazo} % Schrift - wie Funcky und in PDF zu Fonts beschrieben
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[a-1b]{pdfx}
\usepackage[ngerman]{babel}
\usepackage[amssymb]{SIunits}
\usepackage{graphicx}
\usepackage{subfigure}
\usepackage{float}
\usepackage[iso,german]{isodate} %his package provides commands to switch between different date formats
\usepackage{hyperref}
\usepackage[left=2cm,top=1cm,right=2cm]{geometry}
\usepackage{listings}
\lstset{
basicstyle=\tiny, %or \small
literate=
{Ö}{{\"O}}1
{Ä}{{\"A}}1
{Ü}{{\"U}}1
{ß}{{\ss}}1
{ü}{{\"u}}1
{ä}{{\"a}}1
{ö}{{\"o}}1
}
\usepackage{fancyhdr}
\renewcommand{\headrulewidth}{0.5pt}
\renewcommand{\footrulewidth}{0.5pt}
%Abstand zwischen Absätzen, Zeilenabstände
\voffset26pt
\parskip6pt
%\parindent1cm %Rückt erste Zeile eines neuen Absatzes ein
\usepackage{setspace}
\onehalfspacing
\begin{document}
\pagenumbering{roman}
\titlehead
{
\small
{
Technische Universität Ilmenau\\
Fakultät für Informatik und Automatisierung\\
Institut für Biomedizinische Technik und Informatik\\
Laborpraktikum BMT\\
WS 2021/22}
}
\title {Versuch: Deep Learning in der Biomedizintechnik}
\subtitle{Praktikumsbetreuer: Thomas Jochmann}
\author{Teilnehmer: Robert Jeutter \& Armèle Nya}
\date{
Datum Versuchsdurchführung: \quad 16.12.21\\
Datum Protokollabgabe: \quad 18.12.21
}
\maketitle
%Einstellungen zur Kopf- und Fußzeile
\pagestyle{fancy}
\fancyhead[R]{Deep Learning}
\pagenumbering{arabic}
\newpage
\section{Kontrollfragen}
\begin{enumerate}
\item Erklären Sie die Rechenschritte in einem neuronalen Netz.
\begin{itemize}
\item Signaleingang über Axon an Eingang des Neurons
\item Summe aller Eingänge mti Aktivierungsfunktion (Soma) verrechnen
\item Ausgabe der Aktivierungsfunktion mit Ausgabefunktion (Axonhügel) berechnen
\item Ergebnis der Ausgabefunktion auf Ausgang legen
\end{itemize}
\item Nennen Sie drei Aktivierungsfunktionen von neuronalen Netzen.
\begin{itemize}
\item Skalarprodukt $\sum_{j=1}^n w_{ij} * x_J$
\item Sigma-Pi $\sum_{j=1}^n (w_{ij} * \prod_{w=1}^p x_{jw})$
\item Manhatten $\sum_{j=1}^n |x_j-w_{ji}|$
\item Euklidische Distanz $\sqrt{\sum_{j=1}^n (x_j-w_{ji})^2}$
\item Mahalanobis $\sqrt{(x-w_i)^T *C_i^{-1} * (x-w_i)}$ mit $C_i=\frac{1}{n} \sum_{p=1}^N (x^p-w_i)*(x^p-w_i)^T$
\item Maximum-Distanz: $max_{1\leq j\leq n} |x_j-w_{ij}|$
\item Minimum-Distanz: $min_{1\leq j\leq n} |x_j-w_{ij}|$
\end{itemize}
\item Nennen Sie verschiedene Arten von Layern in neuronalen Netzen.
\begin{itemize}
\item Input-Layer: Neuronen, die von der Aussenwelt Signale empfangen
\item Hidden-Layer: Neuronen, die sich im inneren des neuronalen Netzes befinden und eine interne Repräsentation der Aussenwelt enthalten
\item Output-Layer: Neuronen, die Signale an die Aussenwelt abgeben
\end{itemize}
\item Warum ist es nicht sinnvoll eine lineare Funktion $(y=\alpha x+b)$ als Aktivierungsfunktion in den verdeckten Schichten eines neuronalen Netzes zu verwenden?
\item Was verstehen Sie unter Backpropagation?
\begin{itemize}
\item Im Wesentlichen ist Backpropagation ein Algorithmus, der zur schnellen Berechnung von Ableitungen verwendet wird
\item auch Fehlerrückführung oder Rückwärtspropagierung
\item um einen Gradientenabstieg in Bezug auf Gewichtungen zu berechnen
\item gewünschte Ausgaben werden mit erreichten Systemausgaben verglichen, und dann werden die Systeme durch Anpassung der Verbindungsgewichte so eingestellt, dass der Unterschied zwischen den beiden so gering wie möglich ist
\item der Algorithmus hat seinen Namen daher, dass die Gewichtungen rückwärts aktualisiert werden, von der Ausgabe zur Eingabe
\end{itemize}
\item Warum ist eine Stufenfunktion (Rosenblatt-Perceptron) ungünstig für den Backpropagation-Algorithmus?
\begin{itemize}
\item Anpassung schlecht möglich
\end{itemize}
\item Was ist die Learning Rate? Was passiert, wenn sie zu hoch oder niedrig gewählt wird?
\begin{itemize}
\item Sein Wert bestimmt, wie schnell das Neuronale Netz zu Minima konvergieren würde
\item wenn er zu niedrig ist, ist der Konvergenzprozess sehr langsam
\item wenn er zu hoch ist, ist die Konvergenz schnell, aber es besteht die Möglichkeit, dass der Verlust überschreitet
\end{itemize}
\item Was verstehen Sie unter Augmentation? Nennen Sie Beispiele für Augmentation.
\begin{itemize}
\item mit Hilfe von verschiedenen Prozessen die Originalbilddaten verändern
\item Beispielsweise kann ein Bild gedreht werden oder es ist möglich einen Filter über das Bild zu legen
\end{itemize}
\item Warum ist es bei neuronalen Netzen besonders wichtig, die Testdaten beim Training außen vor zu lassen?
\begin{itemize}
\item Um einen korrekten Vergleich mit anderen Netzen und unabhängigkeit vom Training nachzuweisen
\end{itemize}
\item Wie können Sie die Güte eines neuronalen Netzes bewerten?
\begin{itemize}
\item Durch Vergleich der Ausgabe der verifizierten Testdaten mit realen Ergebnissen um den Unterschied zwischen Richtigen, Falsch-Richtigen, Falschen und Falsch-Richtigen Ergebnissen zu einem Wert, der Güte, zusammenzufassen
\end{itemize}
\item Warum ist es potentiell kritisch, wenn mit einem neuronalen Netz ein unscharfes Bild scharf und hochaufgelöst gemacht wird?
\begin{itemize}
\item kleine fehlerhafte oder ungenaue Bild-Sektionen können zu größeren Fehlern und Abweichungen von dem Original führen die durch die Hochauflösung überdeckt oder verschoben werden
\end{itemize}
\end{enumerate}
\newpage
\section{Versuchsdurchführung}
\subsection{Notebook 1: Grundkenntnisse zur Anwendung von Deep Learning}
\subsubsection{Aufgabe 1a) Erstellen eines einfachen neuronalen Netzes}
Gegeben ist ein neuronales Netz (NN). Berechne von Hand mit den gegebenen Gewichten den Output des Netzes für die Inputs $x = -1, 1$ und $2$. Die Aktivierungsfunktion aller Neuronen sei 'ReLu'.
\begin{itemize}
\item Skalarproduktaktivierung: $z_i(x_i, w_i, b)=w_i *x_i+b$
\item ReLU: $y_i (z_i)=max(0,z_i)$
\item Neuron $y(x,w,b)=max(0,\sum w_i*x_i+b)$
\item $x=[-1,1,2]$
\item $w=[3,2,1,1,-5]$
\item $b=[0,0,-5,0]$
\item $y_0=max(0, w_0*x_0+b_0 + w_1*x_1+b_0 + w_2*x_2+b_0) = max(0, 3*(-1)+0 +3*1+0 + 3*2+0) = max(0,-3+3+6)=6$
\item $y_1=max(0, 2*6+0)=12$
\item $y_2=max(0, 1*6-5)=1$
\item $y_3=max(0, 1*12 + (-5)*1)=max(0, 12-5)=7$
\end{itemize}
Im Folgenden soll die eben gelöste Aufgabe erneut mit der Bibliothek ,,keras'' gelöst werden. Erzeuge mit Hilfe der Befehle aus der Vorbereitung das NN. Dazu werden zunächst die benötigten Bibliotheken geladen. Neue Schichten können mit dem Befehl `model.add()` hinzugefügt werden.
\begin{lstlisting}[language=python]
# Import der benötigten Bibliotheken
exec(open(r"../data/notebook1_code.py").read())
%matplotlib inline
# Laden eines Modelltyps für das neuronale Netz
model=tf.keras.models.Sequential()
# TODO: Füge die drei benötigten Schichten zum Netz hinzu
# Hinweis: Vergessen Sie nicht im ersten Layer die Inputdimension anzugeben
model.add(tf.keras.layers.Dense(1, input_shape=(1,), activation='relu'))
model.add(tf.keras.layers.Dense(2, input_shape=(2,), activation='relu'))
model.add(tf.keras.layers.Dense(1, input_shape=(2,), activation='relu'))
# Erzeugen des NN nach der oben festgelegten Struktur
model.compile(optimizer="adam",
loss="mean_squared_error",
metrics=["accuracy"])
\end{lstlisting}
Das Netz enthält in dieser Form zufällig initialisierte Gewichte. Setze die Gewichte und Bias.
\begin{lstlisting}[language=python]
# TODO: Wähle die Werte der Gewichte und des Bias
w01 = 3
w11 = 2
w21 = 1
w12 = 1
w22 = -5
b1 = 0
b2 = 0
b3 = -5
b4 = 0
# Gewichte werden in das von keras geforderte Datenformat gebracht und in weight_list gespeichert
weight_list = [np.array([[w01]]),np.array([b1]),np.array([[w11, w21]]),np.array([b2, b3]),np.array([[w12], [w22]]),
np.array([b4])]
# TODO: Übergebe die Gewichtsmatrizen (weight_list)
model.set_weights(weight_list)
\end{lstlisting}
Nutze nun die predict-Funktion, um die handschriftlichen Rechnungen zu überprüfen.
\begin{lstlisting}[language=python]
# TODO: Führe eine Prediction für drei Werte [-1, 1, 2] durch.
model.predict([-1, 1, 2])
\end{lstlisting}
Ausgabe:
\begin{lstlisting}[language=python]
array([[0.], [6.], [7.]], dtype=float32)
\end{lstlisting}
\textbf{Antwort:} Der Rechenweg und das Neuronale Netzwerk liefern dasselbe Ergebnis.
\subsubsection{Aufgabe 1b) Neuronales Netz zur Funktionsapproximation}
Statt nur einzelne Punkte zu predicten können auch größere Bereiche auf dem Zahlenstrahl abgetastet werden. Gebe dazu 50 Werte von -5 bis 5 in die predict-Funktion.
\begin{lstlisting}[language=python]
# Importieren der Bibliothek für die Darstellung der Kurve
from matplotlib import pyplot as plt
# TODO: Gebe die Werte -5 bis 5 in 50 Schritten auf die predict-Funktion und speicher die Ausgabe in der Variable result
result = model.predict(np.linspace(-5, 5, 50))
# Ausgabe der approximierten Funktion
plt.plot(np.linspace(-5,5),result)
\end{lstlisting}
Gebe das Diagramm im Protokoll an:
\begin{center}
\includegraphics[width=.5\linewidth]{Assets/prakBMT-DeepLearning-01.png}
\end{center}
Mit diesem Netz soll die R-Zacke eines QRS-Komplexes approximiert werden. Lade dazu mit der folgenden Funktion ein Widget. Mit diesem kann der Einfluss einzelner Parameter des Netzes aus Aufgabe 1 a) auf die approximierte Funktion untersucht werden. Versuche die Form der blauen Kurve möglichst der roten anzupassen. Die rote Kurve stellt einen realen QRS-Komplex dar. Die blaue Kurve zeigt die Funktion, welche Ihr Netz mit den aktuell eingestellten Parametern realisiert.
\begin{lstlisting}[language=python]
# Lade das Widget
weight_widget_relu()
\end{lstlisting}
\textbf{Kommentar:} Die Einstellung ist nur mit Maus schwer umzusetzten und liefert nur ungenaue Ergebnisse. Eine Veränderung des Ausschnittrahmens wäre ebenfalls hilfreich.
Die vom Netz realisierte Funktion besitzt eine einfache Form. Mit NN lassen sich Funktionen beliebiger Form approximieren. Je komplexer die Form der zu approximierenden Funktion, desto mehr Neuronen werden benötigt.
In der Praxis ist das Vorgehen aus dem vorherigen Aufgabenteil zu aufwändig. Daher können NN in keras automatisch optimiert werden.
Dazu werden Trainingsdaten benötigt. Im Folgenden soll das obige Netz mit 10 QRS-Komplexen trainiert werden. Dabei lernt es automatisch die Gewichte zur Approximation der QRS-Komplexe. Die folgende Zelle zeigt die verwendeten QRS-Komplexe, lädt die Daten und verarbeitet sie vor.
\begin{lstlisting}[language=python]
# Lesen der Daten von CSV-Datei
dataset = pd.read_csv("../data/data_ekg.csv")
# Plotten der Daten
plot_EKG_data(dataset)
\end{lstlisting}
Das Netz wird nun mit diesen Daten trainiert. Führe die folgende Zelle aus, um das Training zu starten.
\begin{lstlisting}[language=python]
# Trainieren eines NN
model3.fit(x ,y, batch_size = 128 , epochs = 100, callbacks = [QRS()],verbose=0)
\end{lstlisting}
\subsubsection{Aufgabe 1c) Neuronales Netz zur Erkennung handschriftlicher Ziffern}
Im Folgenden wird sich mit der Bilddatenklassifikation beschäftigt. Dabei wird der MNIST-Datensatz verwendet. Dieser enthält Bilder handschriftlicher Ziffern. Die korrekte Klassifikation solcher könnte die Digitalisierung von Patientenakten vereinfachen.
Lade zunächst die Daten. Nehme anschließend das Netz aus Aufgabenteil 1 und erweitere es so, dass eine Verarbeitung der Bilddaten und ihrer Label möglich ist. Die x-Variable enthält jeweils die Bilddaten und die y-Variable die Label.
\begin{lstlisting}[language=python]
# Laden der Daten. Hier ist nichts zu tun.
x_train, y_train, x_test, y_test=load_and_show_data()
x_test = x_test[0:4]
x_train = x_train[0:10000]
y_train = y_train[0:10000]
# Kontrolle der Eingangs/Ausgangsgrößen
x_train.shape
y_train.shape
# TODO: Vervollständigen Sie das unten stehende neuronale Netz sinnvoll.
model = tf.keras.models.Sequential()
# input
model.add(tf.keras.layers.Flatten())
# hidden layer
# 28*28 Pixel = 784 Neuronen für jedes Pixel
model.add(tf.keras.layers.Dense(784, activation='relu'))
# output
model.add(tf.keras.layers.Dense(10, activation="softmax"))
# Erzeugen des NN nach der oben festgelegten Struktur
model.compile(optimizer='adam',
loss="categorical_crossentropy",
metrics=["accuracy"])
\end{lstlisting}
In der nächsten Zelle hat sich ein logischer Fehler eingeschlichen. Versuche Schritt für Schritt den Code nachzuvollziehen und korrigiere den Fehler.
\begin{lstlisting}[language=python]
# TODO
# Training des NN
history = model.fit(x_train, y_train, batch_size=1, epochs=10, verbose=1)
# Klassifizierung der Bilder mit Hilfe des NN
result = model.predict(x_test)
# Anzeigen der Ergebnisse (Index der wahrscheinlichsten Klasse)
print("Bild0 = "+str(np.argmax(result[0])))
print("Bild1 = "+str(np.argmax(result[1])))
print("Bild2 = "+str(np.argmax(result[2])))
print("Bild3 = "+str(np.argmax(result[3])))
'''
Folgenden Code nicht ändern
'''
model=tf.keras.models.Sequential()
\end{lstlisting}
Spiele mit den Hyperparametern des Netzes, also der Anzahl der Hidden Layer und der Neuronen. Vergleiche die erreichte Accuracy im Training bei zwei verschiedenen Konfigurationen. Was wäre ein Beispiel für ein zu kleines Netz?
\textbf{Antwort:} Zu kleine Netze sind Netze die nicht den Bildraum der Eingabebilder abdecken, so z.B. bei 28x28 Pixeln eine Hidden-Layer Größe von 10x10 Neuronen. Ein solch kleines Netz wird größere Schwierigkeiten und Fehler liefern als das Netz das eine Größe entsprechend der Eingangspixel enthält.
Nun wird das NN trainiert und eine Klassifikation der obigen Bilder vorgenommen. Stimmt etwas mit den Klassifikationsergebnissen nicht? Erkläre anhand der folgenden Bilder, warum ein NN bei dieser Aufgabenstellung nie 100\% Accuracy erreichen kann.
\textbf{Antwort:} Sehr große Ähnlichkeit zwischen einzelnen Bildern/Buchstaben und Zahlen, Klassifikation nicht auf Zahlen sondern Buchstaben, ein anderer Datensatz wird verwendet als er für die Bilder notwenig wäre.
\subsection{Notebook 2: Anwendung von Deep Learning in der Biomedizintechnik}
\subsubsection{Aufgabe 2a: Data Sanitization mit Hilfe von Pandas}
Im Folgenden wurde ein Patientendatenblatt und das dazugehörige pandas-DataFrame zur Verfügung gestellt.
Im Rahmen eines fiktiven Machine Learning-Projektes wurden diese Daten über Umwege (Excel, etc.) in eine csv-Datei übertragen. Dabei ist es zu Konvertierungsfehlern gekommen. Die csv-Datei kann mit pandas eingelesen werden.
\begin{lstlisting}[language=python]
# Import der benötigten Bibliotheken
import pandas as pd
exec(open(r"../data/notebook2_code.py").read())
# Einlesen des Datenblattes in ein pandas-DataFrame
data = pd.read_csv(r"../data/datenblatt.csv", sep=";", encoding="latin1")
# Ausgabe des DataFrames
data
\end{lstlisting}
\begin{tabular}{c|l|c|c|c|c}
0 & Laboride & Bezeichnung & Einheit & Normalwert & 31.08.2017 \\\hline
1 & AAGE & Alter & Jahre & <115 & 21 \\
2 & CA & Calcium i.S. & mmol/l & 2.25-2.65 & Feb 43 \\
3 & CHOL & Cholesterin & mmol/l & 3.1-5.2 & 05. Jul \\
4 & ERY & Erythrozyten & Tpt/l & 4.1-5.4 & Apr 28 \\
5 & GGT & Gamma-GT & µmol/l* & <0.65 & zu groß \\
6 & ...
\end{tabular}
Ein NN soll mit diesen Daten trainiert werden. Es soll bestimmt werden, ob der Patient einem gesundheitlichen Risiko unterliegt. Dazu werden die Blutwerte der Nummerierung in pandas entsprechend auf das NN gegeben. Der Prozess der Data Sanitization ist meist nicht so einfach wie oben angegeben.
TODO: Korrigiere mögliche Fehler in den Daten.
\begin{lstlisting}[language=python]
# Einlesen des Datenblattes in ein pandas-DataFrame
data = pd.read_csv(r"../data/datenblatt.csv", sep=";", encoding="latin1")
# TODO: Modifizieren Sie die Daten im pandas-Dataframe
data= data.replace(" ","")
data= data.replace("Feb 43","2.43")
data= data.replace("05. Jul","5.06")
data= data.replace("Apr 28","4.28")
data= data.replace("zu groß","0.28")
data= data.replace(" ok","0.3")
data= data.replace("07. Jun","7.6")
data= data.replace("Feb 35","2.35")
data= data.replace("04. Jul","4.07")
data= data.replace("02. Aug","2.08")
data= data.replace("04. Sep","4.09")
data= data.replace("Jan 76","1.76")
data= data.replace("20. Mrz","20.3")
data= data.replace("NaN","321")
data= data.replace("Jan 15","1.15")
data= data.replace("Mrz 22","3.22")
data = data.drop([22])
# Ausgabe des DataFrames
data
\end{lstlisting}
\begin{tabular}{c|l|c|c|c|c}
0 & Laboride & Bezeichnung & Einheit & Normalwert & 31.08.2017 \\\hline
1 & AAGE & Alter & Jahre & <115 & 21 \\
2 & CA & Calcium i.S. & mmol/l & 2.25-2.65 & 2.43 \\
3 & CHOL & Cholesterin & mmol/l & 3.1-5.2 & 5.06 \\
4 & ERY & Erythrozyten & Tpt/l & 4.1-5.4 & 4.28 \\
5 & GGT & Gamma-GT & µmol/l* & <0.65 & 0.28 \\
6 & GLFR & eGFR & ml/min/ & >65 & 115 \\
7 & GLUC & Glucose i.S. & mmol/l & 4.2-6.1 & 4.0 \\
8 & GOT & GOT (ASAT) & µmol/l* & <0.60 & 0.3 \\
9 & GPT & GPT (ALAT) & µmol/l* & <0.60 & 0.30 \\
10 & HB & Haemoglobin & mmol/l & 7.4-10.5 & 7.6 \\
11 & HDL & HDL-Cholesterin & mmol/l & >1.55 & 2.35 \\
12 & HKT & Haematokrit & kA & 0.37-0.47 & 0.37 \\
13 & HS & Harnsaeure & µmol/l & 150-350 & 190 \\
14 & K & Kalium i.S. & mmol/l & 3.8-5.5 & 4.07 \\
15 & KREA & Kreatinin i.S. & µmol/l & <97 & 66 \\
16 & LDLC & LDL-Chol.(direkt) & mmol/l & <4.1 & 2.08 \\
17 & LEUK & Leukozyten & Gpt/l & 4.0-9.8 & 4.09 \\
18 & MCH & MCH & fmol & 1.70-2.05 & 1.76 \\
19 & MCHC & MCHC & mmol/l & 20.0-22.5 & 20.3 \\
20 & MCV & MCV & fl & 80-96 & 87.0 \\
21 & NaN & Natrium i.S. & mmol/l & 136-152 & 141 \\
23 & TRI & Triglyzeride & mmol/l & <1.71 & 1.15 \\
24 & TSHB & TSH basal & µlU/ml & 0.30-4.20 & 3.22 \\
\end{tabular}
Führe nun die untere Codezelle aus und beobachte, ob das Training gelingt.
\begin{lstlisting}[language=python]
# Bauen des NN
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(23, activation = "relu"))
model.add(tf.keras.layers.Dense(100, activation = "relu"))
model.add(tf.keras.layers.Dense(2, activation = "softmax"))
# Erzeugen des NN nach der oben festgelegten Struktur
model.compile(optimizer="adam",
loss="categorical_crossentropy",
metrics=["accuracy"])
# Erzeugen des Input-Arrays aus DataFrame
try:
inp = tf.constant(data["Unnamed: 4"][1:].astype(float))
label = tf.constant(np.ones_like(inp))
except:
inp = "hallo"
label = 5
print("Bitte verwenden Sie einen einheitlichen Datentyp")
# Trainingsversuch
try:
model.fit(inp,label)
print("Das Training konnte mit den gegebenen Daten erfolgreich durchgeführt werden!")
except:
print("Das Training konnte mit den gegebenen Daten nicht erfolgreich durchgeführt werden!")
\end{lstlisting}
Ergebnis:
\begin{lstlisting}[language=python]
Train on 23 samples
23/23 [==============================] - 0s 13ms/sample - loss: 2.4125 - accuracy: 0.0000e+00
Das Training konnte mit den gegebenen Daten erfolgreich durchgeführt werden!
\end{lstlisting}
\subsubsection{Aufgabe 2b: Neuronales Netz zur Klassifikation von OCT-Aufnahmen}
Im Folgenden sollen OCT-Aufnahmen klassifiziert werden. Diese zeigen Querschnittsaufnahmen der Netzhaut. Im Datensatz sind Bilder von gesunden Probanden vorhanden. Außerdem gibt es solche mit \hyperref{https://en.wikipedia.org/wiki/Choroidal_neovascularization}{choroidaler Neovaskularisation} (CNV), \hyperref{https://en.wikipedia.org/wiki/Macular_edema}{Makulaödem} (DME) und \hyperref{https://en.wikipedia.org/wiki/Drusen}{Drusen} (DRUSEN). Es werden vier Bilder gegeben.
Stelle anhand der Bilder eine Diagnose für den jeweiligen Patienten und notiere diese. Eine grobe Einschätzung ist hierbei ausreichend.
\begin{itemize}
\item Bild 1: DRUSEN
\item Bild 2: DME
\item Bild 3: CNV
\item Bild 4: NORMAL
\end{itemize}
Lade das Netz 'oct.hp5' mit dem entsprechenden keras-Befehl.
\begin{lstlisting}[language=python]
# TODO: Laden Sie das vortrainierte Netz mit tf.keras.models.load_model() vom Pfad "../data/oct.hp5".
model = tf.keras.models.load_model(r"../data/oct.hp5")
\end{lstlisting}
Nutze das Netz, um die vier Bilder zu klassifizieren. (Klasse1=CNV , Klasse2=DME, Klasse3=NORMAL, Klasse4=DRUSEN)
\begin{lstlisting}[language=python]
# Laden und Vorverarbeiten der Bilder (img_data enthält Bild 1-4)
img_data=load_oct()
# TODO: Machen Sie eine Prediction für die Bilder (alle mit einem Mal)
result = model.predict(img_data[0:4])
# Anzeigen der Ergebnisse (Index der wahrscheinlichsten Klasse)
print("Bild1 = Klasse 4 <=> "+str(np.argmax(result[0])))
print("Bild2 = Klasse 2 <=> "+str(np.argmax(result[1])))
print("Bild3 = Klasse 1 <=> "+str(np.argmax(result[2])))
print("Bild4 = Klasse 3 <=> "+str(np.argmax(result[3])))
\end{lstlisting}
Ergebnis:
\begin{lstlisting}[language=python]
Bild1 = Klasse 4 <=> 1
Bild2 = Klasse 2 <=> 0
Bild3 = Klasse 1 <=> 0
Bild4 = Klasse 3 <=> 2
\end{lstlisting}
Welche Bilder wurden richtig klassifiziert? Erkläre die Entscheidung des Netzes anhand seiner Ausgabe (Hinweis: Es wird ein Softmax-Output verwendet, der Klassenwahrscheinlichkeiten repräsentiert. Eine Outputzeile entspricht dem Output für ein Bild).
\textbf{Antwort:} Kein Bild wurde richtig klassifiziert. Nur mit vier Bildern lässt sich die Unterscheidung schlecht erklären, insbesondere da CNV und DME optisch (für Menschen) leicht unterscheidbar sind, das NN es aber für CNV hält. Grund ist wahrscheinlich ein sehr kleiner Datensatz und wenige konkrete Unterscheidungspunkte zwischen den Bildern.
Das oben verwendete Netz erreicht auf einem Testdatensatz 69\% Accuracy. Dieses Ergebnis kann verbessert werden, indem ein größerer Trainingsdatensatz verwendet wird. Durch Data Augmentation kann der Trainingsdatensatz vergrößert werden, ohne dass neue Daten erhoben werden müssen.
Das heißt, es sollen veränderte Bilder erzeugt werden, die dieselben Informationen enthalten wie das Original. Dazu stehen verschiedene Möglichkeiten zur Verfügung. Im Folgenden werden einige Beispiele aufgelistet.
\begin{itemize}
\item np.flipud(img) = Spiegeln an der horizontalen Achse
\item np.fliplr(img) = Spiegeln an der vertikalen Achse
\item tf.keras.preprocessing.image.apply\_affine\_transform(img,theta= 10) = Rotieren des Bildes, um den Winkel theta
\item keras.preprocessing.image.apply\_brightness\_shift(img, brightness) = Ändern der Bildhelligkeit
\item add\_noise(noise\_typ,img[:,:,0]) = Verrauschen des Bildes(Rauscharten= 's\&p', 'gauss', 'poisson', 'speckle')
\end{itemize}
Wähle aus den gegebenen Transformationen drei aus, die für die gegebene Anwendung geeignet sind. Führe diese an einem Beispielbild durch und speichere die manipulierten Bilder. Stelle das Ergebnisse im Protokoll dar. Begründe im Protokoll den Ausschluss der nicht gewählten Operationen.
\begin{lstlisting}[language=python]
# Laden des Testbildes
img = tf.keras.preprocessing.image.load_img(r"../data/oct_drusen.jpeg", target_size=(224, 224))
img = tf.keras.preprocessing.image.img_to_array(img)
img = np.mean(img, axis=2)
img = np.expand_dims(img, axis=2)
# TODO: Transformieren Sie das Bild sinnvoll
# Spiegeln an vertikalen Achse -> Symmetrie in Mitte
img_trans2 = np.fliplr(img)
# Rotation -> Winkel nicht Diagnoserelevant
img_trans3 = tf.keras.preprocessing.image.apply_affine_transform(img,theta= 15)
# Ausgabe des neuen Bildes
plt.figure(4)
plt.imshow(img[:,:,0],"gray")
plt.figure(0)
plt.imshow(img_trans2[:,:,0],"gray")
plt.figure(1)
plt.imshow(img_trans3[:,:,0],"gray")
\end{lstlisting}
\begin{center}
\includegraphics[width=0.2\linewidth]{Assets/prakBMT-DeepLearning-02.png}
\includegraphics[width=0.2\linewidth]{Assets/prakBMT-DeepLearning-03.png}
\includegraphics[width=0.2\linewidth]{Assets/prakBMT-DeepLearning-04.png}
\end{center}
\textbf{Antwort:} Spiegelungen und Rotationen können zur Augmentation genutzt werden, da diese keinen Einfluss auf die Diagnose haben. Eine Veränderung der Bilder durch Rauschen oder Helligkeit kann Informationen und Details für das Neuronale Netzwerk unkenntlich machen oder verfälschen.
\subsection{Notebook 3: Grenzen von Deep Learning}
Im Bereich der Medizin spielt Vertrauen in die Technik eine große Rolle. Für das Vertrauen ist es wichtig zu wissen, auf welcher Grundlage die Entscheidungen für eine Klasse getroffen werden. Bisher wurden NN angewendet und sich auf deren Ausgaben verlassen. Die Entscheidungskriterien waren unbekannt. Da NN als ,,Black-Box'' betrachtet werden können, ist dies mit vielen Gefahren verbunden. Diese sollen im Folgenden verdeutlicht werden.
\begin{lstlisting}[language=python]
# Import der benötigten Bibliotheken
exec(open(r"../data/notebook3_code.py").read())
\end{lstlisting}
Es ist ein NN gegeben. Dieses wurde auf einem Datensatz von MRT-Scans trainiert. Diese sehen z.B. wie folgt aus:
\begin{lstlisting}[language=python]
show_mri_example()
\end{lstlisting}
\begin{center}
\includegraphics[width=.3\linewidth]{Assets/prakBMT-DeepLearning-05.png}
\end{center}
Je nach Herkunft können die Bilder mit Datumsstempeln oder Wasserzeichen versehen sein. Diese können bei der Anwendung des Netzes später zu Problemen führen.
Die Daten haben die Klassen ,,gesund'' (Klasse 1) und ,,abnormal'' (Klasse 2). Ein Großteil der als ,,abnormal'' gelabelten Daten stammt von einer (fiktiven) Studie der TU Ilmenau.
Es sind zwei als ,,abnormal'' gelabelte Bilder gegeben.
\begin{lstlisting}[language=python]
# Laden der zwei Bilder
bild1 = []
bild2 = []
path1 = r"../data/mrt_tuil/train/sagittal/0002.npy"
path2 = r"../data/mrt_blank/0008.npy"
#17
a = np.load(path1)
bild1.append(a[int(a.shape[0] / 2)])
b = np.load(path2)
bild2.append(b[int(b.shape[0] / 2)])
bild1 = np.array(bild1, dtype = "float32").reshape(256,256,1)
bild2 = np.array(bild2, dtype = "float32").reshape(256,256,1)
# Speichern der Bilder in einem Array (Praktisch für die Übergabe an keras-Funktionen)
# Array für keras-Funktionen
im_array = np.array([bild1,bild2])
\end{lstlisting}
Die Bilder der als krank diagnostizierten Knie sehen wie folgt aus:
\begin{lstlisting}[language=python]
#Anzeigen der Bilder
plt.figure(1)
plt.title('Bild 1')
plt.axis('off')
plt.imshow(bild1[:,:,0],cmap='jet')
plt.figure(2)
plt.title('Bild 2')
plt.axis('off')
plt.imshow(bild2[:,:,0],cmap='jet')
\end{lstlisting}
\begin{center}
\includegraphics[width=.2\linewidth]{Assets/prakBMT-DeepLearning-06.png}
\includegraphics[width=.2\linewidth]{Assets/prakBMT-DeepLearning-07.png}
\end{center}
Nun wird das oben erwähnte NN geladen.
\begin{lstlisting}[language=python]
model= tf.keras.models.load_model(r"../data/mrt.h5")
\end{lstlisting}
Führe nun eine Klassifikation der obigen Bilder durch. Das NN verwendet einen Softmax-Output.
\begin{lstlisting}[language=python]
# TODO: Führen Sie die Klassifikation durch
result = model.predict(im_array)
print("Bild0 = "+str(np.argmax(result[0])))
print("Bild1 = "+str(np.argmax(result[1])))
\end{lstlisting}
Ergebnis:
\begin{lstlisting}[language=python]
Bild0 = 1
Bild1 = 0
\end{lstlisting}
Bei diesem Ergebnis ist Skepsis geboten! Interpretiere das Ergebnis.
\textbf{Antwort:} beide Knie sind abnormal. Das NN klassifiziert jedoch eines als Normal. Problematisch wird der unterschiedliche Ausschnitt sein, sowie weniger/mehr rot-gekennzeichnete Zonen.
Im Folgenden soll untersucht werden, worauf das NN seine Entscheidung stützt. Dazu wird der Class Activation Map (CAM)-Algorithmus verwendet. Dieser ordnet einem Bild eine Heatmap zu, welche die Wichtigkeiten der Pixel für die Klassifikationsentscheidung angibt.
Nutze dafür die im Praktikum zur Verfügung gestellte visualize\_class\_activation\_map-Funktion. Diese gibt die zu einem Inputbild gehörende Heatmap der Wichtigkeiten aus.
\begin{lstlisting}[language=python]
# Berechnen der Heatmaps für die zwei Bilder
Map1 = visualize_class_activation_map(model,im_array, img_num=0,klasse=1)
Map2 = visualize_class_activation_map(model,im_array, img_num=1,klasse=0)
# Visualisieren Sie die Heatmaps
plt.figure(1)
plt.title('Bild 1')
plt.axis('off')
plt.imshow(bild1[:,:,0], cmap = "gray")
plt.imshow(Map1, cmap="jet", alpha = 0.4)
plt.figure(2)
plt.title('Bild 2')
plt.axis('off')
plt.imshow(bild2[:,:,0], cmap = "gray")
plt.imshow(Map2 ,cmap="jet", alpha = 0.4)
\end{lstlisting}
\begin{center}
\includegraphics[width=.2\linewidth]{Assets/prakBMT-DeepLearning-08.png}
\includegraphics[width=.2\linewidth]{Assets/prakBMT-DeepLearning-09.png}
\end{center}
Was fällt an den beiden Bildern auf? Geben im Protokoll an, auf welches Problem die erste Heatmap hinweist.
\textbf{Antwort:} In Bild 1 ist das Knie nicht betrachtungspunkt des NN. In Bild 2 wird das Knie, besonders der untere Knochen und der vordere Teil, in die Betrachtung mit einbezogen. D.h. bei Bild 1 wird eine völlig falsche Stelle untersucht und für die Diagnose verwendet. Möglicherweise sind Bilddaten falsch interpretiert oder Präperiert worden.
Häufig lassen sich problematische Sachverhalte durch simplere Methoden aufklären.
Die Verwendung einer anderen Colormap kann weitere Informationen ersichtlich machen. Führe den oben verwendeten plt.imshow-Befehl dazu mit anderen Colormaps aus. Können mit einer anderen Colormap das Problem, welches bei diesem NN vorliegt, besser verdeutlicht werden? Erzeuge einen Screenshot für die Colormaps ,,summer'', ,,flag'' und ,,rainbow''.
\begin{lstlisting}[language=python]
# TODO: Untersuchen Sie andere Colormaps
# Führen Sie die Zelle zunächst wie vorgegeben aus und ändern Sie dann die Colormap
plt.figure(1)
plt.title('Bild 1')
plt.axis('off')
plt.imshow(im_array[0,:,:,0],cmap="summer")
plt.figure(2)
plt.title('Bild 2')
plt.axis('off')
plt.imshow(im_array[1,:,:,0],cmap="summer")
\end{lstlisting}
\begin{center}
\includegraphics[width=.2\linewidth]{Assets/prakBMT-DeepLearning-10.png}
\includegraphics[width=.2\linewidth]{Assets/prakBMT-DeepLearning-11.png}
\end{center}
\begin{lstlisting}[language=python]
plt.figure(1)
plt.title('Bild 1')
plt.axis('off')
plt.imshow(im_array[0,:,:,0],cmap="flag")
plt.figure(2)
plt.title('Bild 2')
plt.axis('off')
plt.imshow(im_array[1,:,:,0],cmap="flag")
\end{lstlisting}
\begin{center}
\includegraphics[width=.2\linewidth]{Assets/prakBMT-DeepLearning-12.png}
\includegraphics[width=.2\linewidth]{Assets/prakBMT-DeepLearning-13.png}
\end{center}
\begin{lstlisting}[language=python]
plt.figure(1)
plt.title('Bild 1')
plt.axis('off')
plt.imshow(im_array[0,:,:,0],cmap="rainbow")
plt.figure(2)
plt.title('Bild 2')
plt.axis('off')
plt.imshow(im_array[1,:,:,0],cmap="rainbow")
\end{lstlisting}
\begin{center}
\includegraphics[width=.2\linewidth]{Assets/prakBMT-DeepLearning-14.png}
\includegraphics[width=.2\linewidth]{Assets/prakBMT-DeepLearning-15.png}
\end{center}
Lösung: Die TU Ilmenau hat die Daten mit einem Schriftzug unten links versehen. Das Netz hat gelernt, im Falle kranker Knie auf diese zu achten.
\end{document}