---
# System prepended metadata

title: Deep Learning Lab 2021

---

# Deep Learning Lab 2021
[Klick: Zu Teil 2](https://hackmd.io/p0NxhdZ-Rnity_KXcGRYEA)
[Klick: Zur Challenge-Seite](https://hackmd.io/RFPQ4pUFTiGKkJH1Rb0Pbw)
### Teil 3: CNN
#### Q27
Submit two jobs on the GPU cluster by executing the commands ​sbatch main.sh -m FFN​ and ​sbatch main.sh -m CNN​ to train a model on MNIST.
FFN:
![](https://i.imgur.com/D7rLVQf.png)

CNN:
![](https://i.imgur.com/gxkPnqK.png)





#### Q28
Why are convolutional neural networks better suited for images than plain feed forward networks?

Weil hier das Prinzip des Weight Tying bereits mit implementiert ist. Egal, ob sich das zu erkennende Objekt an einer wechselnden x- oder y-Position befindet (z.B. gleiches Bild, aber mit Cropping), es soll jedes Mal erkannt werden.
Bei Bildern ist es weiterhin so, dass die Informationen zeilen- oder spaltenweise durch das Weight Tying in vom Netz verarbeitet werden (können). Es müssen also nicht $b \cdot h$ Weights im ersten Layer positioniert und trainiert werden, sondern nur $b$ bzw. $h$.
Pooling-Layer bringen die Essenz des Bildes zum Vorschein, was zur Reduktion von Parametern beitragen kann. Ein FFN kommt eher ins Overfitting als ein CNN.

#### T29
Uncomment (%) all the lines which are related to the CIFAR10 dataset and comment (%) all the lines related to the MNIST dataset.

![](https://i.imgur.com/cSkb8Jx.png)




#### Q30

Due to the bigger input size of 32×32×3 you have to change the model code in models/simple_models.py for FFN and CNN. For this, inspect again the model architecture and search for layers which rely on the input size information. Change those layers in the FFN class (one) and in the CNN class (two) accordingly.
After this is done train both models on the CIFAR10 dataset.

Bei **FFN**: Ändern von 28 x 28 auf 32 x 32 x 3
![](https://i.imgur.com/spwqrHX.png)


![](https://i.imgur.com/oA6HiqU.png)


Dimensionsanalyse für das CNN:
![](https://i.imgur.com/tavlxJt.png)
Das Flatten Layer `flatten` hat die Dimension [1,1024]. Daher muss das Linear Layer `fc1` 1024 Eingänge haben.

:::spoiler
```

# https://stackoverflow.com/questions/55875279/how-to-get-an-output-dimension-for-each-layer-of-the-neural-network-in-pytorch

import torch
import torch.nn as nn

num_classes = 10

class Model(nn.Module):
  def __init__(self):
    super(Model, self).__init__()
    self.net = nn.Sequential(
        nn.Conv2d(3, 32, 5, padding=2),
        nn.ReLU(),
        nn.MaxPool2d(3, stride=2),
        nn.Conv2d(32, 48, 3),
        nn.ReLU(),
        nn.MaxPool2d(3, stride=2),
        nn.Conv2d(48, 64, 3),
        nn.ReLU(),
        nn.Flatten(),
        nn.Linear(1024, 96),
        nn.ReLU(),
        nn.Linear(96, num_classes))

  def forward(self, x):
    for layer in self.net:
        x = layer(x)
        print(x.size())
    return x

model = Model()
x = torch.randn(1,3,32,32)
# print('Using Data: \n', x)

# Let's print it
model(x)
```
:::


Bei **CNN**: conv1 = nn.Conv2d(3, 32, 5, padding=2) 
        fc1 = nn.Linear(1024, 96) 
        ![](https://i.imgur.com/gFGwCrZ.png)
        ![](https://i.imgur.com/0mc2W4g.png)

## Part 3.1 Hyperparameter tuning

#### T31
Train the CNN with a batch size of 128, 256 and 512. Choose the batch size resulting in the best performance for the next tasks.

*Eingabe (hardcoded) über die main.sh oder beim Aufruf mithilfe der execution Arguments / Parser. Beispiel in der Konsole: `sbatch main.sh -m CNN -b 256`*

Batch Size 128: 
![](https://i.imgur.com/0mc2W4g.png)

Batch Size 256:
![](https://i.imgur.com/lGW0kXH.png)

Batch Size 512:
![](https://i.imgur.com/V50KYyb.png)

--> Wahl der Batch Size 512


#### T32
Train the CNN with different weight decay values (0.005, 0.01, 0.05, 0.1). Choose the weight decay value resulting in the best performance for the next tasks.

*Beispiel in der Konsole: `sbatch main.sh -m CNN -b 512 -w 0.005`*

0.005: 
![](https://i.imgur.com/6gPlXnt.png)

0.01:
![](https://i.imgur.com/ymauJsA.png)

0.05:
![](https://i.imgur.com/cb7ooxB.png)

0.1:
![](https://i.imgur.com/kuYdDxP.png)

#### Q33 
Explain how the weight decay changes the learning rule.

Gegeben sind die Lernrate $\mu$ und der Weight Decay $\varepsilon$.
Nach jedem Backpropagation-Schritt werden die Gewichte (nicht für die Biases)  um $\mu \cdot \varepsilon$ reduziert. Dies hat den Vorteil, dass das Netz besser generalisiert. Kleine Gewichte sorgen für linearere Netze.
Hinweis: Bei PyTorch ist die Lernrate oft als $\eta$ bezeichnet!

#### T34
Implement one of the following learning rate schedulers from `torch.optim.lr_scheduler`. To understand its interface, please take a look at the official PyTorch documentation.

Die Wahl fällt auf `MultiStepLR`, da das entsprechende Modul zum einen bereits importiert ist, auf der anderen Seite nicht ganz klar ist, wie vorteilhaft die sich cosinus-förmig verhaltende Lernrate darstellt. Ggf. werden außerhalb dieser Doku Erfahrungen mit `CosineAnnealingLR` gesammelt.

Dazu muss nach dem `args.optimizer` der Scheduler eingerichtet werden. Dieser ist so eingestellt, dass er sich dynamisch an die maximale Epochenzahl anpasst (falls später Anpassungen nötig werden sollten):
![](https://i.imgur.com/uV6oSSq.png)
Am Ende der for-Schleife über alle Epochen wird der Step aufgerufen:
![](https://i.imgur.com/Aip0SCs.png)


#### T35
What does a learning rate scheduler actually do?

Entsprechend der von uns gewählten Optionen wird die Lernrate $\mu$ um einen bestimmten Wert bzw. Faktor reduziert. Dies geschieht je nach gewähltem Scheduler nach jeder Epoche (z.B. `CosineAnnealingLR`) oder wie bei unserem Beispiel nach mithilfe des `MultiStepLR`-Schedulers nach der Hälfte und Dreivierteln der maximalen Epochenzahl.
Dies hat den Vorteil, dass das Netz zunächst schnell, später immer langsamer und dafür präziser lernt.

#### T36

Train the CNN with your chosen learning rate scheduler. You can also try out all three schedulers if you want to.

Wahl: `MultiStepLR`-Scheduler
Es ergibt sich, gemeinsam mit den anderen Trainingsparametern:
![](https://i.imgur.com/tA0T7Xu.png)
**VORSCHLAG: Fein-Tuning des Reduktionsfaktors, da die Error Rate höher ist als bei den vorherigen Versuchen?**

#### T37
Train the model with different (starting) learning rates (0.005, 0.01, 0.05, 0.1). Use the best value for all coming tasks.

Lernrate 0.005:
![](https://i.imgur.com/88nnaAC.png)

Lernrate 0.01:
![](https://i.imgur.com/4v5Pgz7.png)

Lernrate 0.05: **Eigenartiger Verlauf:**
![](https://i.imgur.com/CxRHd18.png)

Lernrate 0.1:
![](https://i.imgur.com/sGdVjR4.png)

#### Q38
What are your best hyperparameters? Write down the final result on the test set.

| Scheduler   | Minibatch Size | Weight Decay | Start-Lernrate |
| ----------- | -------------- | ------------ | -------------- |
| MultistepLR | 512            | 0.005        | 0.01           |

## Part 3.2 Augmentations

#### Q39

Add at least two of the following augmentations to the training transforms. Feel free to test multiple combinations:
    Random horizontal and vertical translation by a value of 4 pixels for CIFAR10 with RandomAffine
    Random rotation by a value of 15 degrees using RandomAffine
    Random contrast by a value of 80% to 120% using ColorJitter
    Random brightness by a value of 80% to 120% using ColorJitter
    Random horizontal flip using a probability of 50% and RandomHorizontalFlip
    
    
![](https://i.imgur.com/2TnMPZ1.jpg)

#### Q40

Train the network after you implemented the augmentations at the right place. Write down the final result on the test set.

CNN mit 512 und 0.005 LR= 0.01 + contrast zwischen 80 und 120

![](https://i.imgur.com/E8EuLaV.png)



## Part 3.3 Model architecture improvements

#### Q41

First add batch normalization layer (torch.nn.BatchNorm2d) after every convolution layer. Use the marked area for this and train the model with ​-m CNN\_BN​ afterwards.

![](https://i.imgur.com/lDhpvqx.png)

#### Q42

How does the error curve from the dll_report change?

![](https://i.imgur.com/4x1WQaT.jpg)

#### Q43

Name and explain the learned parameters within a batch normalization layer. You can also use the paper for this.

Bei der Batch Normalization werden Input-Daten jedes Layers erst normalisiert, indem sie mittelwerts- und varianzfrei gemacht werden. Dies wird gemacht, da sonst die Inputs zu sehr varirieren, da nach jedem Update die vorherigen Schichten durch neue Gewichte die Daten anders ändern. Hier durch wird die Lernfähigkeit beeinträchtigt (auf gut deutsch: wenn jedes mal was anderes hineinkommt ist es schwierig die richtigen Parameter zu finden). Allerdings ist es durch die Normalisierung an sich nicht getan, da so bespielweise die Inputdaten immer im gleichen Bereich sind, kann es dazu kommen, dass der eigentliche Zweck der Schicht nicht mehr erfüllt wird. (Beispiel Sigmoidfunktion: man will den linearen und nichtlinearen Bereich ausschöpfen). Deshalb werden die normalisierten Daten vor Eingang in die jeweilige Schicht nochmals skaliert und verschoben. Diese Skalierungs- und Verschiebungsparameter müssen während dem Backpropagationalgorithmus zusätzlich gelernt werden.

#### Q44

Implement the forward pass of the ResNetUnit in models/resnet.py using figure 3.13. Train your model afterwards.

![](https://i.imgur.com/yCRc2br.jpg)


CNN mit 512 und 0.005 LR= 0.01 + contrast zwischen 80 und 120 und Brightness 80/120 mit norm batch+Resnet 50 epochen
(Habe keine LR scheduler benutzt, da sich das bei meinen vorherigen Tests eher negativ ausgewirkt hat.


![](https://i.imgur.com/KsJZkbp.png)


#### Q45

Take a look at the ResNet class and describe the basic structure of ResNet([3,3,3]).

Wie aus dem Skript zu entnehmen ist, definiert das Tupel [3,3,3] die Layer-Anordnung der Resnetstruktur. Die einzelnen "3en" bedeuten hier, dass es zum einen 3 Resnetblöche gibt die aus jeweils 3 einzelnen Layern bestehen. Zusätzlich wird noch die Angabe gemacht, dass die für Resnet typische Direktverbindung 3 Layers umfasst. 

#### Q46

The ground-breaking novelty of ResNets lies in the residual connection. Explain the effect of the residual connection by using the paper references or other resources.

Durch die Shortcut-Verbindungen wird das Tranieren von sehr tiefen Netzen möglich gemacht. Der Grundgedanke hierbei ist, dass durch die Direkt Verbindung das Netz die Möglichkeit hat, in diesem Bereich "nichts" zu lernen, da der hineingegangen Input auch am Punkt der Zurückführung zur Verfügung gestellt wird. Hierdurch wird der Übersättigung des Lernens durch den immer kleiner werdenden Gradienten mit steigender Anzahl der Schichten im Gradientenlernverfahen erflogreich entgegengewirkt. Es wird sicher gestellt, dass das Netz mindestens so gut performen kann, wie sein äquivalent ohne Shortcuts aber mit weniger Schichten. Es hat sich aber herausgestellt, dass die tiefen Resnets meist deutlich besser performen können, da ihnen die Möglichkeit gegeben wird, zusätzlich im Vergleich der flachen Netzen zu lernen. Hierbei wird der Shortcut in dem Sinne genutz, dass er eine Referenz an der Zusammenkunft liefert und somit im Resnet ein sinnvoller Unterschied zum Input erlernt werden kann. Diese "Relative Lernmethode" hat sich als sehr erfolgreich bewiesen und ist vor allem in Computer Vision Aufgaben standardmäßig verstreten.

#### Q47

To complete this exercise train the ResNet with all modifications (e.g., learning rate scheduler, augmentations, ...) and the best hyperparameters from the previous tasks for 150 epochs. Write down the final result on the test set

Ich glaube Toms durchlauf war deutlich besser, lieber seine Parameter nehmen

CNN mit 512 und 0.005 LR= 0.01 + contrast zwischen 80 und 120  mit norm Batch + Resnet 150 epochen

![](https://i.imgur.com/p42HyP5.png)
![](https://i.imgur.com/4hqU7XW.jpg)



## Part 3.4: Generative Adversial Networks

#### Q48

Go to the folder ​part3/pix2pix​ . Here you can get an overview of the parameters for the bash script with the following command:
​./start_pix2pix.sh -h

![](https://i.imgur.com/bJ4DC5H.png)

#### Q49

Submit a GAN training with 10 images per batch running for 50 epochs and without the ​use_discriminator​ flag ​-d​ . In the jobs folder, images from the test set are stored after each epoch for each job run. Have a look at the pictures of each epoch. After how many epochs do you get at least semi-reasonable results coming out of the generator?

Schwierig zu sagen ab welcher Epoche gute Bilder entstehen, ich habe mal Nr. 15 gewählt: 

![](https://i.imgur.com/jwCbCrh.png)

#### Q50

Train the discriminator on the real and the facade image with valid as the label. Than train on the generated image (fakeA) and the facade image with fake as the label. Also save the average loss of both in d_loss for logging purposes.

![](https://i.imgur.com/ZKYIYJy.png)

#### Q51

Train the combined model out of generator and discriminator on the real and the facade image with the valid and img_A as label. Save the loss as g_loss.

![](https://i.imgur.com/e0Scol6.png)

#### Q52

Submit a GAN training with 10 images per batch running for 50 epochs and use the discriminator with ​-d​ . After how many epochs do you get at least semi-reasonable results? Is there a qualitative difference between the method with and without discriminator?

Wieder schwierig zu sagen, ich habe Nr.6 gewählt, ich würde sagen, die Qualität der Bilder steigt durch diese Methode.

![](https://i.imgur.com/FgeYLXb.png)

#### Q53

The structure of the discriminator and the generator are stored as D.png and G.png for each run. The structure of the discriminator is relatively simple. Can you improve the results of the GAN with simple methods?

Einfügen von Dropout layers.

![](https://i.imgur.com/prE947T.png)


Altes Schema: 

![](https://i.imgur.com/7vqjifT.png)

Neues Schema: 

![](https://i.imgur.com/LODq0Id.png)


Zum Vergleich zum oberen Bild hier Bild Nr.6 mi Dropout Layers:

![](https://i.imgur.com/NFjP6Sg.png)

## Part 3.5: Speech Enhancement 

**Nomenklatur**

| Bezeichnung | Bedeutung                                  |
| ----------- | ------------------------------------------ |
| *clean*     | ursprüngliche Sounddatei                   |
| *mixed*     | veränderte Sounddatei: Rauschen überlagert |
| *enhanced*  | Sounddatei nach Durchlauf durch das Netz   |


#### Q54
Take a look at the overall structure for this task in Figure 3.15. What are the inputs, outputs and subcomponents of each block (semantic meaning, number of dimensions, ...)? How many connections are between the encoder and the decoder? What differences can you see compared to the computer vision tasks from before?

![](https://i.imgur.com/nZMTgA2.png)

Als Ein- und Ausgang sind jeweils Daten im Zeitbereich zu identifizieren. Die zu untersuchende (und später bereinigt auszugebende) Tonspur besteht aus Amplituden und Zeitschritten. Dadurch ist die Dimension zwei: Amplitude und Zeit
Das Signal im Zeitbereich wird in den Frequenzbereich transformiert. Dazu wird die **STFT (short-time Fourier transform)** genutzt. Hierdurch werden zeitliche Änderungen des Frequenzspektrums des ursprünglichen Signals darstellbar. Es entstehen hier nun $n$ zweidimensionale Layer, mit der Anzahl $n$ der untersuchten Frequenzspektren (durch STFT).
Es gibt eine Verbindung zwischen Encoder und Decoder. Real- und Imaginärteil des im Frequenzbereich vorliegenden Signals werden gesondert betrachtet.
Zum Schluss wird die durch das Netz ermittelte Maske auf das Eingangssignal angewendet, die inverse Transformation durchgeführt und das Signal wieder im Zeitbereich existierenden Form abgelegt.

Tiefergehende Informationen im [Paper](https://openreview.net/pdf?id=SkeRTsAcYm) zum Deep Complex U-Net!
![](https://i.imgur.com/9XFxVdn.png)

Ein großer Unterschied ist, dass hier nicht so viel gefaltet wird und die Daten nicht in so hochdimensionalen Formen vorliegen. Die "Auffächerung" ist nicht so ausgeprägt wie bie den computer vision - Aufgaben zuvor.

#### Q55 / T56
Create a plot containing spectograms of noisy, clean and enhanced speech for a randomly selected sample. Next, create a plot containing spectograms of the enhanced speech for epoch 3 and 6 as well as for the last epoch. Save these plots to the output folder or add them to the labreport. Test your implementation by running the training with the bash script for one epoch (sbatch train.sh -e 1). Point out the differences between the clean and noisy speech spectrogram.

Run a training of the DCUnet for 10 epochs and compare the results in the output folder. The training should take about 2 hours. You can proceed with the next question and Part 3.6 in the mean time. If you have enough time you can also train the DCUnet for 20 epochs or even 25 epochs to see if the overall speech enhancement is improved.

![](https://i.imgur.com/m7V7Ly4.png)
![](https://i.imgur.com/paQ0ADp.png)
![](https://i.imgur.com/3hJdKHS.png)
![](https://i.imgur.com/24oSiMk.png)
![](https://i.imgur.com/owcoMAG.png)

In dem "mixed"-Sample ist das breitbandige Rauschen erkennbar, dass auch deutlich zu hören ist. Mit zunehmenden Epochen wird dieses Rauschen immer weniger, sodass es am Schluss kaum mehr zu hören ist und sich im Grund wie das "clean"-Sample anhört.

Erstellung der Spektogramme in den
:::spoiler
```
#https://pythontic.com/visualization/signals/spectrogram

# import the pyplot and wavfile modules

import matplotlib.pyplot as plot
import matplotlib
matplotlib.use('TkAgg')
from scipy.io import wavfile

import numpy as np
from scipy import signal
import math
# Read the wav file (mono)

samplingFrequency, signalData = wavfile.read('sample0_clean.wav')

# Plot the signal read from wav file

plot.subplot(211)
time=signalData.shape[0]/samplingFrequency
timestep=time/signalData.shape[0]
print(signalData)
print('Gesamtzeit in Sekunden:', time)
print('Abtastung alle',timestep,'Sekunden')
maxAmp = max(signalData)
vMaxVal=10000000
print('Maximale Amplitude:', maxAmp)
f, t, Zxx = signal.stft(signalData, samplingFrequency, nperseg=1000)

print('Zxx:', Zxx)
plot.title('Spektogramme sample0_clean.wav')

plot.pcolormesh(t, f, np.abs(Zxx),  vmin=0 , vmax=vMaxVal, shading='auto')
plot.ylabel('Frequenz [Hz]')
plot.xlabel('Zeit [s]')

plot.subplot(212)
plot.tight_layout(pad=1.5)
plot.specgram(signalData, Fs=samplingFrequency)
plot.xlabel('Zeit [s]')
plot.ylabel('Frequenz [Hz]')
plot.savefig('SpektogrammeClean.png', pad_inches=1)
plot.show()

```
:::


#### Q57 / Q58
Now you should process the noisy speech files in the test folder. Begin by creating a new
python file and a copy of the train bash script. First load the wave files and the model. Then
take a look at the procedure in train.py and identify the parts you need for this task. Just
keep in mind then the only thing you need to do is process the noisy speech by the trained
the DCUnet. At the end save your enhanced speech files in a new folder. Keep the basename of
the wave files to identify the pairs of noisy and enhanced speech later. Adapt the bash script
so that it runs your new created python file correctly. If your final model is still training, you
can test your implementation by just using the current best model (best_model.pth) from
the output folder. After you generated the enhanced speech files go to your output folder and
find a pair for which the speech enhancement worked quite well and one where the trained
model struggles to perform a good speech enhancement.

Das Script muss folgende Struktur aufweisen
1. Imports
2. Laden des Test-Sets aus SpeechEnhancement/test
3. Laden des besten Modells aus dem Training aus SpeechEnhancement/Robert/343045/best_model.pth
4. Inferenz Test-Sets -> Bestes Modell -> Output .wav-File
5. Spektogramm vorher zu nachher

Ansatz Netz richtig laden:
:::spoiler
Laden des Netzes am Beispiel:
https://github.com/chanil1218/DCUnet.pytorch
genauer:
https://github.com/chanil1218/DCUnet.pytorch/blob/master/train.py
:::

![](https://i.imgur.com/tFHVTp6.png)
![](https://i.imgur.com/oTWJVSw.png)

Beobachtung: Das Rauschen wurde signifikant reduziert, wie man in den Spektogrammen klar erkennen kann. Gehört ein Rauschen oder Schaben zum "Nutzsignal", wird dieses allerdings auch stark bedämpft.


[Klick: Zur Challenge-Seite](https://hackmd.io/RFPQ4pUFTiGKkJH1Rb0Pbw)