diff --git a/experiments/Experiments.ipynb b/experiments/Experiments.ipynb index 3abc441..f081563 100644 --- a/experiments/Experiments.ipynb +++ b/experiments/Experiments.ipynb @@ -3289,7 +3289,7 @@ } }, "source": [ - "Um mehr controlle über den Lernprozess zu haben werden drei Coallbacks verwendet. Der EarlyStopping callback verhindert vor allem das Verschwenden von Rechenzeit indem er den Lernvorgang abbricht wenn eine weile keine Verbesserung gefunden wurde. Verschlechtert sich die beobachtete Metric wird der Lernvorgang abgebrochen." + "Um mehr Kontrolle über den Lernprozess zu haben werden drei Callbacks verwendet. Der EarlyStopping Callback verhindert vor allem das Verschwenden von Rechenzeit, indem er den Lernvorgang abbricht, wenn eine weile keine Verbesserung gefunden wurde. Verschlechtert sich die beobachtete Metric wird der Lernvorgang abgebrochen. Zudem wird das beste Ergebnis wieder hergestellt was Oberfitting verhindert." ] }, { @@ -3305,7 +3305,7 @@ "early_stop = tf.keras.callbacks.EarlyStopping(\n", " monitor=\"mean_squared_error\",\n", " min_delta=0.00001,\n", - " patience=5,\n", + " patience=10,\n", " verbose=0,\n", " mode=\"auto\",\n", " restore_best_weights=True,\n", @@ -3388,22 +3388,29 @@ }, { "cell_type": "markdown", - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, "source": [ - "### Train Validate Test split\n", + "### Model Training\n", "\n", - "Der Datensatz wird in Trainingsdaten, Validationdaten und Testdaten unterteilt. Folgenden Anteile werden ausgewählt:\n", + "Das Oben erstellte Model muss nun trainiert werden. Leider war es mir nicht möglich mehr als ein Model auf einmal im Speicher zu haben was dazu geführt hat, das nicht alle Modelle in diesem Notebook aufgezeichnet werden konten.\n", "\n", - "* $60\\%$ Trainingsdataen\n", - "* $20\\%$ Validationdaten\n", - "* $20\\%$ Testdaten\n", + "Es wurde versucht das Modell mit den Fehler Function `MSE`, `MAE`, `Binary Crossentropy` wurden versucht. Die Ergebnisse waren sehr unterschiedlich.\n", + "* `MAE` Der *M*ean *A*verage *E*rror wird durch den Durchschnitt des absoluten Fehlers berechnet. Das Ergebniss war in diesem Fall annähernd 0 über die gesamten ergebnisse. Das Optimieren hat also überhaupt nicht funktioniert.\n", + "* `MSE` Der *M*ean *S*quare *E*rror bildet den Durchschnitt über die Quadrate der Fehlerfunktion. Die Dadurch verstärkten Ausreißer erlaubten ein wesentlich besseres Lernverhalten.\n", + "* `Binary Crossentropy` Die Binary Crossentropy ist eine Fehlerfunktion für Wahrscheinlichkeitsfunktionen. Da wir hier eine Wahrscheinlichkeitsfunktion als Bild darstellen ist es die Theoretisch am besten geeignete Funktion. Dies wurde Experimentell bestätigt.\n", "\n", - "Das Dataset von tensorflow ist theoretisch noch zu viel mehr im stande. Zum beispiel könnte man es nutzen um alle Datensätze zwei mal pro Epoche aufzurufen und einmal zu Vertikal zu Spiegeln. Dies würde die Datenmänge verdoppeln ohne den RAM zusätzlich zu belasten. Dies sprängt hier aber leider etwas den Rahmen." - ] + "Das Training wurde mit $20\\%$ der Daten als Validierungsdaten durchgeführt.\n", + "Experimentell hat sich gezeigt das die Ergebnisse schon mit der Standard Lernrate sehr gute Ergebnisse Liefern. Diese werden mit einer geringeren Lernrate etwas besser auch, wenn der Lernaufwand so um ein Vielfaches größer ist.\n", + "\n", + "Leider war es mir nicht möglich mehr als die Routen von 500 pickel Detain auf einmal mit meiner GPU zu trainieren. Es ist zu vermuten, dass ein besseres Ergebnis mit mehr Datensätzen erreicht werden kann. Ohne GPU war der Rechenaufwand dieses Trainings aber nicht praktikabel.\n", + "\n", + "Als Optimierer wurde RMSprop verwendet." + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%% md\n" + } + } }, { "cell_type": "markdown", @@ -3413,14 +3420,20 @@ } }, "source": [ - "Compiliert das model und initialisiert die Schichten." + "#### Training des Modells mit Routen als Linien\n", + "\n", + "Erstellt ein neues Model, Compiliert das Model und initialisiert die Schichten.\n", + "Danach wird direkt das Training begonnen." ] }, { "cell_type": "code", "execution_count": 50, "metadata": { - "scrolled": false + "scrolled": false, + "pycharm": { + "name": "#%%\n" + } }, "outputs": [ { @@ -3567,33 +3580,26 @@ } ], "source": [ + "# Delete the generator variable if allrady defined. Saves some gpu memory,\n", "if 'generator' in globals():\n", " print(\"Generator exists. Deleting for reset\")\n", " del generator\n", "\n", + "# creates the model\n", "generator = model_generator()\n", - "early_stop = tf.keras.callbacks.EarlyStopping(\n", - " monitor=\"val_loss\",\n", - " min_delta=0.00001,\n", - " patience=10,\n", - " verbose=2,\n", - " mode=\"auto\",\n", - " restore_best_weights=True,\n", - ")\n", "\n", + "# compiles the model\n", "generator.compile(\n", " optimizer=tf.keras.optimizers.RMSprop(learning_rate=0.00001), # \n", - " # Loss function to minimize\n", " loss=\"binary_crossentropy\",\n", - " # tf.keras.losses.SparseCategoricalCrossentropy(),\n", - " # List of metrics to monitor\n", " metrics=[\n", " \"binary_crossentropy\",\n", " \"mean_squared_error\",\n", " \"mean_absolute_error\",\n", - " ], # root_mean_squared_error\n", + " ],\n", ")\n", "\n", + "# starts the training\n", "history = generator.fit(\n", " collected_routes[:, :, :, :2],\n", " collected_routes[:, :, :, 2],\n", @@ -3628,43 +3634,92 @@ } ], "source": [ - "def plot_history(metrics: str | list):\n", + "def plot_history(history_data, metrics: str | list) -> None:\n", + " \"\"\"Plot some metrics from a training history.\n", + "\n", + " Args:\n", + " history_data: The history data to plot.\n", + " metrics: The metrics that should be ploted.\n", + "\n", + " Returns:\n", + " None\n", + " \"\"\"\n", " if isinstance(metrics, str):\n", " metrics = [metrics]\n", " for metric in metrics:\n", - " plt.plot(history.history[metric], label=metric)\n", - " plt.plot(history.history[f\"val_{metric}\"], label=f\"val_{metric}\")\n", + " plt.plot(history_data[metric], label=metric)\n", + " plt.plot(history_data[f\"val_{metric}\"], label=f\"val_{metric}\")\n", " if len(metrics) == 1:\n", " plt.ylabel('loss')\n", " plt.xlabel('epoch')\n", " plt.legend(loc='best')\n", "\n", - " \n", + "# Plots the training history in a single figure\n", "plt.figure(figsize=(20, 5))\n", + "\n", + "# plots the loss\n", "plt.subplot(1, 3, 1)\n", - "plot_history(\"loss\")\n", + "plot_history(history.history, \"loss\")\n", "plt.title('model loss')\n", + "\n", + "# plots the binary cross entropy <-> equal to loss\n", "plt.subplot(1, 3, 2)\n", - "plot_history(\"binary_crossentropy\")\n", + "plot_history(history.history, \"binary_crossentropy\")\n", "plt.title('binary crossentropy')\n", + "\n", + "# plots the other metrics\n", "plt.subplot(1, 3, 3)\n", - "plot_history([\"mean_absolute_error\", \"mean_squared_error\"])\n", + "plot_history(history.history, [\"mean_absolute_error\", \"mean_squared_error\"])\n", "plt.title('other metrics')\n", + "\n", "plt.show()" ] }, + { + "cell_type": "markdown", + "source": [ + "#### Betrachtung des trainierten Models mit Routen als Linien\n", + "\n", + "Die besten ergebnisse lagen bei einer `binary_crossentropy` von 0.0103 und einer `val_binary_crossentropy` von 0.0127 nach 51 Epochen.\n", + "Bei dieser Art von Problem ist jedoch eine Visuelle überprüfung der Prediction notwendig." + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%% md\n" + } + } + }, { "cell_type": "code", "execution_count": 53, - "metadata": {}, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, "outputs": [], "source": [ - "def plot_predicted_data(model: tf.keras.Model, data: np.ndarray, pos=0):\n", + "def plot_predicted_data(model: tf.keras.Model, data: np.ndarray, pos=0) -> None:\n", + " \"\"\"Plots a single dataset in three versions.\n", + "\n", + " - The labeled situation.\n", + " - The solution in context.\n", + " - The prediction as a heat map.\n", + "\n", + " Args:\n", + " model: The trained model that should be visualised.\n", + " data: The raw data that should be used as an example to visualise.\n", + " pos: The position of the dataset that should be shown. If negativ test data is shown else training data is shown.\n", + "\n", + " Returns:\n", + " None\n", + " \"\"\"\n", " plt.figure(figsize=(15, 5))\n", " tt = \"test\" if pos < 0 else \"train\"\n", " plt.title(f\" for {tt} Nr: {abs(pos)}\")\n", " data = data[pos, :, :, :]\n", - " predicted = generator.predict(\n", + " predicted = model.predict(\n", " np.expand_dims(\n", " data[:, : , :2], 0),\n", " verbose=\"0\",\n", @@ -3674,26 +3729,48 @@ " workers=1,\n", " use_multiprocessing=False,\n", " )[0]\n", + "\n", + " # Plots the original labeled data\n", " plt.subplot(1, 3, 1)\n", - " plt.imshow(data[:, :, 0] * 2 + data[:, :, 1] * 3 + data[:, :, 2], interpolation=\"nearest\")\n", " plt.title(\"Original map\")\n", + " plt.imshow(data[:, :, 0] * 2 + data[:, :, 1] * 3 + data[:, :, 2], interpolation=\"nearest\")\n", + "\n", + "\n", + " # Plots the prediction in context\n", " plt.subplot(1, 3, 2)\n", - " plt.imshow(data[:, :, 0] * 2 + predicted[:, :] / predicted[:, :].max() * 3, interpolation=\"nearest\")\n", " plt.title(\"Prediction in context\")\n", + " plt.imshow(data[:, :, 0] * 2 + predicted[:, :] / predicted[:, :].max() * 3, interpolation=\"nearest\")\n", + "\n", + " # Plots the predication as a pure heat map\n", " plt.subplot(1, 3, 3)\n", - " plt.imshow(predicted[ :, :], interpolation=\"nearest\")\n", " plt.title(\"Predicted head map\")\n", + " plt.imshow(predicted[ :, :], interpolation=\"nearest\")\n", " plt.colorbar()\n", " plt.suptitle(f'Plot of the {tt} scenario with the index {pos if pos >= 0 else -pos - 1}')\n", - " plt.show()\n", - " " + " plt.show()\n" ] }, + { + "cell_type": "markdown", + "source": [ + "Nachfolgend werden sowohl Vorhersagen mit Scenarios verglichen nebeneinander und gemeinsam dargestellt, um eine Abschätzung über die Vorhersagequalität zu machen.\n", + "Erst wurden die Vorhersagen von Trainingsdaten visualisiert. Danach von Validierungsdaten." + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%% md\n" + } + } + }, { "cell_type": "code", "execution_count": 54, "metadata": { - "scrolled": false + "scrolled": false, + "pycharm": { + "name": "#%%\n" + } }, "outputs": [ { @@ -3826,7 +3903,10 @@ "cell_type": "code", "execution_count": 55, "metadata": { - "scrolled": false + "scrolled": false, + "pycharm": { + "name": "#%%\n" + } }, "outputs": [ { @@ -3957,15 +4037,26 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, "source": [ - "### Training mit Punkt Daten" + "### Training mit routen als liste von Wendepunkten\n", + "\n", + "Analog wurde das gleiche Model mit einer Liste an Wendepunkten trainiert. Hier wurde mti einem neuen Modell gearbeitet.\n", + "Ein Weitertrainieren / verändern des Alten modells where vermutlich genauso gut möglich." ] }, { "cell_type": "code", "execution_count": 56, - "metadata": {}, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, "outputs": [ { "data": { @@ -3984,10 +4075,26 @@ "collected_routes.shape" ] }, + { + "cell_type": "markdown", + "source": [ + "Darstellung von Hindernissen, ziel und Label in der Darstellung der Route als Liste von Wendepunkten-" + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%% md\n" + } + } + }, { "cell_type": "code", "execution_count": 57, - "metadata": {}, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, "outputs": [ { "data": { @@ -4032,7 +4139,10 @@ "cell_type": "code", "execution_count": 58, "metadata": { - "scrolled": false + "scrolled": false, + "pycharm": { + "name": "#%%\n" + } }, "outputs": [ { @@ -4092,27 +4202,16 @@ " del generator\n", "\n", "generator = model_generator()\n", - "early_stop = tf.keras.callbacks.EarlyStopping(\n", - " monitor=\"val_loss\",\n", - " min_delta=0.00001,\n", - " patience=10,\n", - " verbose=2,\n", - " mode=\"auto\",\n", - " restore_best_weights=True,\n", - ")\n", "\n", "generator.compile(\n", " optimizer=tf.keras.optimizers.RMSprop(learning_rate=0.0001),\n", - " # Loss function to minimize\n", " loss=\"binary_crossentropy\",\n", - " # tf.keras.losses.SparseCategoricalCrossentropy(),\n", - " # List of metrics to monitor\n", " metrics=[\n", " \"binary_crossentropy\",\n", " \"mean_squared_error\",\n", " \"mean_absolute_error\",\n", " tf.keras.metrics.RootMeanSquaredError(),\n", - " ], # root_mean_squared_error\n", + " ],\n", ")\n", "\n", "history = generator.fit(\n", @@ -4129,7 +4228,11 @@ { "cell_type": "code", "execution_count": 59, - "metadata": {}, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, "outputs": [ { "data": { @@ -4158,11 +4261,38 @@ "plt.show()" ] }, + { + "cell_type": "markdown", + "source": [ + "Betrachtung des trainierten Models mit Routen als Liste von Kurswechselpositionen.\n", + "Die besten Ergebnisse wurden nach 20 Epochen erreicht und lagen bei einer binary_crossentropy von 0.0023 und einer val_binary_crossentropy von 0.0035. Bei dieser Art von Problem ist jedoch eine Visuelle überprüfung der Prediction notwendig." + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%% md\n" + } + }, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "invalid syntax (3138732072.py, line 1)", + "output_type": "error", + "traceback": [ + "\u001B[1;36m Input \u001B[1;32mIn [1]\u001B[1;36m\u001B[0m\n\u001B[1;33m Betrachtung des trainierten Models mit Routen als Linien\u001B[0m\n\u001B[1;37m ^\u001B[0m\n\u001B[1;31mSyntaxError\u001B[0m\u001B[1;31m:\u001B[0m invalid syntax\n" + ] + } + ], + "execution_count": 1 + }, { "cell_type": "code", "execution_count": 60, "metadata": { - "scrolled": false + "scrolled": false, + "pycharm": { + "name": "#%%\n" + } }, "outputs": [ { @@ -4295,7 +4425,10 @@ "cell_type": "code", "execution_count": 61, "metadata": { - "scrolled": false + "scrolled": false, + "pycharm": { + "name": "#%%\n" + } }, "outputs": [ { @@ -4424,32 +4557,28 @@ " plot_predicted_data(generator, collected_routes, -i - 1)" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, "source": [ "### Vergleich der Experimente" ] }, { - "cell_type": "code", - "execution_count": null, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [], + "cell_type": "markdown", "source": [ - "# tf.keras.utils.plot_model(generator)" - ] + "Wie sehr schnell deutlich wird Skalieren die Ergebnisse der Liniendarstellung viel besser als die Ergebnisse der Punktdarstellung. Der Fehler ist aber bei der Punktdarstellung viel geringer. Dies ist auf die wesentlich mehr Werte die mit Routenmarkierungen versehen wurden zurückzuführen. Welches der Beiden ergebnisse sich nachher besser für den Einsatzt" + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%% md\n" + } + } }, { "cell_type": "markdown", @@ -4564,4 +4693,4 @@ }, "nbformat": 4, "nbformat_minor": 1 -} +} \ No newline at end of file