Parcourir la source

Added GAN testing frame.

Kristian Schultz il y a 4 ans
Parent
commit
ae548878b6
4 fichiers modifiés avec 827 ajouts et 0 suppressions
  1. 622 0
      Example Exercise.ipynb
  2. 100 0
      library/dataset.py
  3. 70 0
      library/exercise.py
  4. 35 0
      library/interfaces.py

+ 622 - 0
Example Exercise.ipynb

@@ -0,0 +1,622 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "id": "dynamic-invitation",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from library.exercise import Exercise\n",
+    "from library.dataset import DataSet, TrainTestData\n",
+    "from library.interfaces import GanBaseClass, TesterNetworkBaseClass"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "id": "modern-battery",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import numpy as np"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "id": "absolute-fruit",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def createTesterNetwork():\n",
+    "    return TesterNetworkBaseClass()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "id": "seventh-flood",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def loadFailingDataset():\n",
+    "    data0 = np.array(range(100)).reshape((25,4))\n",
+    "    return DataSet(data0=np.concatenate((data0, [[0,0,0,0]])), data1=data0 * 2)\n",
+    "\n",
+    "def loadEqualDataset():\n",
+    "    data0 = np.array(range(100)).reshape((25,4))\n",
+    "    return DataSet(data0=data0, data1=data0 * 2)\n",
+    "\n",
+    "def loadDataset():\n",
+    "    data0 = np.array(range(100)).reshape((25,4))\n",
+    "    return DataSet(data0=data0[0:12], data1=data0 * 2)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "id": "fabulous-willow",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "exercise = Exercise(createTesterNetwork)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "id": "direct-vacuum",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "gan = GanBaseClass()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "id": "bored-flash",
+   "metadata": {
+    "scrolled": true
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "### Start exercise for synthetic point generator\n",
+      "\n",
+      "====== Step {shuffleStep + 1}/{self.numOfShuffles} =======\n",
+      "-> Spliting data to slices\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "====== Step {shuffleStep + 1}/{self.numOfShuffles} =======\n",
+      "-> Spliting data to slices\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "====== Step {shuffleStep + 1}/{self.numOfShuffles} =======\n",
+      "-> Spliting data to slices\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "====== Step {shuffleStep + 1}/{self.numOfShuffles} =======\n",
+      "-> Spliting data to slices\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "====== Step {shuffleStep + 1}/{self.numOfShuffles} =======\n",
+      "-> Spliting data to slices\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=20, |class 1|=20\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "### Exercise is done.\n"
+     ]
+    }
+   ],
+   "source": [
+    "exercise.run(gan, loadEqualDataset())"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "id": "described-bidder",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "### Start exercise for synthetic point generator\n",
+      "\n",
+      "====== Step {shuffleStep + 1}/{self.numOfShuffles} =======\n",
+      "-> Spliting data to slices\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=9, |class 1|=20\n",
+      "-> create 11 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=9, |class 1|=20\n",
+      "-> create 11 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=9, |class 1|=20\n",
+      "-> create 11 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=9, |class 1|=20\n",
+      "-> create 11 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=12, |class 1|=20\n",
+      "-> create 8 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "====== Step {shuffleStep + 1}/{self.numOfShuffles} =======\n",
+      "-> Spliting data to slices\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=9, |class 1|=20\n",
+      "-> create 11 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=9, |class 1|=20\n",
+      "-> create 11 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=9, |class 1|=20\n",
+      "-> create 11 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=9, |class 1|=20\n",
+      "-> create 11 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=12, |class 1|=20\n",
+      "-> create 8 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "====== Step {shuffleStep + 1}/{self.numOfShuffles} =======\n",
+      "-> Spliting data to slices\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=9, |class 1|=20\n",
+      "-> create 11 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=9, |class 1|=20\n",
+      "-> create 11 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=9, |class 1|=20\n",
+      "-> create 11 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=9, |class 1|=20\n",
+      "-> create 11 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=12, |class 1|=20\n",
+      "-> create 8 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "====== Step {shuffleStep + 1}/{self.numOfShuffles} =======\n",
+      "-> Spliting data to slices\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=9, |class 1|=20\n",
+      "-> create 11 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=9, |class 1|=20\n",
+      "-> create 11 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=9, |class 1|=20\n",
+      "-> create 11 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=9, |class 1|=20\n",
+      "-> create 11 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=12, |class 1|=20\n",
+      "-> create 8 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "====== Step {shuffleStep + 1}/{self.numOfShuffles} =======\n",
+      "-> Spliting data to slices\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=9, |class 1|=20\n",
+      "-> create 11 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=9, |class 1|=20\n",
+      "-> create 11 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=9, |class 1|=20\n",
+      "-> create 11 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=9, |class 1|=20\n",
+      "-> create 11 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "\n",
+      "------ Step {shuffleStep + 1}/{self.numOfShuffles}: Slice {sliceNr + 1}/{self.numOfSlices} -------\n",
+      "-> Train generator for synthetic samples\n",
+      "Train GAN with |class 0|=12, |class 1|=20\n",
+      "-> create 8 synthetic samples\n",
+      "-> create network\n",
+      "-> train network\n",
+      "-> test network\n",
+      "-> check results\n",
+      "### Exercise is done.\n"
+     ]
+    }
+   ],
+   "source": [
+    "exercise.run(gan, loadDataset())"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "id": "peaceful-distribution",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Expected class 0 to be the minority class but class 0 is bigger than class 1.\n"
+     ]
+    }
+   ],
+   "source": [
+    "try:\n",
+    "    exercise.run(gan, loadFailingDataset())\n",
+    "except AttributeError as e:\n",
+    "    print(e)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "finite-hamburg",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.8.5"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}

+ 100 - 0
library/dataset.py

@@ -0,0 +1,100 @@
+import math
+import numpy as np
+
+class DataSet:
+    """
+    Stores data and Labels.
+    """
+    def __init__(self, data0=None, data1=None):
+        self.data0 = data0
+        self.data1 = data1
+        self.size0 = len(data0) if data0 is not None else 0
+        self.size1 = len(data1) if data1 is not None else 0
+
+        if data0 is not None and data1 is not None:
+            self.data = np.concatenate( [data1, data0] )
+            self.labels = np.concatenate( [self.labels1(), self.labels0()] )
+        elif data0 is None:
+            self.data = data1
+            self.labels = self.labels1()
+        elif data1 is None:
+            self.data = data0
+            self.labels = self.labels0()
+        else:
+            raise AttributeError("Expected data, data0 or data1 to be a numpy.array")
+
+    def shuffleWith(self, shuffleFn):
+        if self.data0 is not None:
+            self.data0 = shuffleFn(self.data0)
+
+        if self.data1 is not None:
+            self.data1 = shuffleFn(self.data1)
+
+        if self.data0 is None:
+            self.data = self.data1
+        elif self.data1 is None:
+            self.data = self.data0
+        else:
+            self.data = np.concatenate((self.data1, self.data0))
+
+    def labels0(self):
+        return np.zeros(self.size0)
+
+    def labels1(self):
+        return np.zeros(self.size0) + 1
+
+
+class TrainTestData:
+    """
+    Stores features, data and labels for class 0 and class 1.
+    """
+
+    def __init__(self, train, test):
+        self.train = train
+        self.test = test
+
+    @staticmethod
+    def splitUpData(data, trainFactor=0.9):
+        size = len(data)
+        trainSize = math.ceil(size * trainFactor)
+        trn = data[list(range(0, trainSize))]
+        tst = data[list(range(trainSize, size))]
+        return trn, tst
+
+    @classmethod
+    def splitDataByFactor(cls, features0, features1, trainFactor=0.9):
+        features_0_trn, features_0_tst = cls.splitUpData(features0, trainFactor)
+        features_1_trn, features_1_tst = cls.splitUpData(features1, trainFactor)
+
+        return cls(
+            test=DataSet(data1=features_1_tst, data0=features_0_tst),
+            train=DataSet(data1=features_1_trn, data0=features_0_trn)
+            )
+
+    @classmethod
+    def splitDataToSlices(cls, bigData, numOfSlices=5):
+        data0slices = cls._arrayToSlices(bigData.data0, numOfSlices)
+        data1slices = cls._arrayToSlices(bigData.data1, numOfSlices)
+
+        for n in range(numOfSlices):
+            data0 = np.concatenate([data0slices[k] for k in range(numOfSlices) if n != k])
+            data1 = np.concatenate([data1slices[k] for k in range(numOfSlices) if n != k])
+            train = DataSet(data0=data0, data1=data1)
+            test = DataSet(data0=data0slices[n], data1=data1slices[n])
+            yield cls(train=train, test=test)
+
+    @staticmethod
+    def _arrayToSlices(data, numOfSlices):
+        size = len(data)
+        if size < numOfSlices:
+            raise AttributeError(
+                f"Expected data set to contain at least {numOfSlices} points"
+                + f" but got {size} points."
+                )
+
+        sliceSize = (size // numOfSlices) + (0 if size % numOfSlices == 0 else 1)
+
+        return [
+            data[n * sliceSize : min(size, (n+1) * sliceSize)]
+            for n in range(numOfSlices)
+            ]

+ 70 - 0
library/exercise.py

@@ -0,0 +1,70 @@
+import numpy as np
+
+from library.dataset import DataSet, TrainTestData
+
+
+class Exercise:
+    """
+    Exercising a test for a minority class extension class.
+    """
+
+    def __init__(self, createNetworkFunction, shuffleFunction=None, numOfSlices=5, numOfShuffles=5):
+        self.numOfSlices = numOfSlices
+        self.numOfShuffles = numOfShuffles
+        self.createNetworkFunction = createNetworkFunction
+        self.shuffleFunction = shuffleFunction
+        self.debug = print
+
+    def run(self, gan, dataset):
+        if len(dataset.data0) > len(dataset.data1):
+            raise AttributeError("Expected class 0 to be the minority class but class 0 is bigger than class 1.")
+
+        self.debug("### Start exercise for synthetic point generator")
+        for shuffleStep in range(self.numOfShuffles):
+            stepTitle = "Step {shuffleStep + 1}/{self.numOfShuffles}"
+            self.debug(f"\n====== {stepTitle} =======")
+
+            if self.shuffleFunction is not None:
+                self.debug("-> Shuffling data")
+                dataset.shuffleWith(self.shuffleFunction)
+
+            self.debug("-> Spliting data to slices")
+            dataSlices = TrainTestData.splitDataToSlices(dataset, self.numOfSlices)
+
+            for (sliceNr, sliceData) in enumerate(dataSlices):
+                sliceTitle = "Slice {sliceNr + 1}/{self.numOfSlices}"
+                self.debug(f"\n------ {stepTitle}: {sliceTitle} -------")
+                self._exerciseWithDataSlice(gan, sliceData)
+        self.debug("### Exercise is done.")
+
+    def _exerciseWithDataSlice(self, gan, dataSlice):
+        self.debug("-> Train generator for synthetic samples")
+        gan.train(dataSlice.train)
+
+        numOfNeededSamples = dataSlice.train.size1 - dataSlice.train.size0
+
+        if numOfNeededSamples > 0:
+            self.debug(f"-> create {numOfNeededSamples} synthetic samples")
+            newSamples = np.asarray([gan.generateData() for _ in range(numOfNeededSamples)])
+            train = DataSet(
+                data0=np.concatenate((dataSlice.train.data0, newSamples)),
+                data1=dataSlice.train.data1
+                )
+        else:
+            train = dataSlice.train
+
+
+        self.debug("-> create network")
+        testNetwork = self.createNetworkFunction()
+
+        self.debug("-> train network")
+        testNetwork.train(train.data, train.labels)
+
+        self.debug("-> test network")
+        results = testNetwork.predict(dataSlice.test.data)
+
+        self.debug("-> check results")
+        self._checkResults(results, dataSlice.test.labels)
+
+    def _checkResults(self, results, expectedLabels):
+        pass

+ 35 - 0
library/interfaces.py

@@ -0,0 +1,35 @@
+import numpy as np
+
+class GanBaseClass:
+    def __init__(self):
+        self.isTrained = False
+        self.exampleItem = None
+        pass
+
+    def train(self, dataSet):
+        if dataSet.data0.shape[0] <= 0:
+            raise AttributeError("Train GAN: Expected data class 0 to contain at least one point.")
+
+        print(
+            "Train GAN with |class 0|=%d, |class 1|=%d"
+            % (dataSet.data0.shape[0], dataSet.data1.shape[0])
+            )
+        self.isTrained = True
+        self.exampleItem = dataSet.data0[0].copy()
+
+    def generateData(self):
+        if not self.isTrained:
+            raise ValueError("Try to generate data with untrained GAN.")
+
+        return self.exampleItem
+
+
+class TesterNetworkBaseClass:
+    def __init__(self):
+        pass
+
+    def train(self, data, labels):
+        pass
+
+    def predict(self, data):
+        return np.zeros(data.shape[0])