Files
reutlingen-university/1_data_science/simulationsstudie/yann_ahlgrim_simulationsstudie.ipynb
T
2025-06-11 10:55:17 +02:00

676 lines
56 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"cells": [
{
"cell_type": "markdown",
"id": "7ba05a39",
"metadata": {},
"source": [
"# Simulationsstudie: Diebstahlerkennung eines Autos in Echtzeit\n",
"\n",
"**Name:** Yann Ahlgrim \n",
"\n",
"In dieser Simulationsstudie wird ein Modell entwickelt, das anhand von Fahrverhaltensdaten erkennt, ob ein anderer Fahrer als üblich am Steuer sitzt. Ziel ist es, eine Wahrscheinlichkeit für einen Fahrerwechsel zu schätzen und bei hoher Wahrscheinlichkeit eine Diebstahlwarnung auszugeben. Die Studie umfasst die Generierung einer synthetischen Grundgesamtheit, die Simulation der Data Scientist Perspektive und die Analyse der Modellgüte."
]
},
{
"cell_type": "markdown",
"id": "f04292ef",
"metadata": {},
"source": [
"## Erzeugung der Grundgesamtheit"
]
},
{
"cell_type": "markdown",
"id": "a5fe9381",
"metadata": {},
"source": [
"### Datengrundlage\n",
"\n",
"#### Erklärende Variablen:\n",
"\n",
"1. **Durchschnittsgeschwindigkeit (metrisch):** \n",
" Die Werte verteilen sich natürlicherweise ungefähr normal um ca. 47km/h (29mph) mit großer Streuung. Aggressive Fahrer tendieren zu höheren Durchschnittsgeschwindigkeiten. Diese Variable ist erklärend, da ein anderer Fahrer oft abweichende Geschwindigkeitsprofile aufweist. \n",
" → Die Verteilung basiert auf: [NHTSA 100-Car Naturalistic Driving Study](https://www.nhtsa.gov/sites/nhtsa.gov/files/100carmain.pdf)\n",
"\n",
"2. **Schaltverhalten (ordinal):** \n",
" Charakteristisches Schaltmuster bei Handschaltgetrieben, insbesondere der Drehzahlbereich beim Hochschalten. Fahrer unterscheiden sich deutlich: \n",
" - *frueh* (ökonomisches Fahren), \n",
" - *normal*, \n",
" - *spaet* (sportliches/aggressives Fahren). \n",
" Diese Variable dürfte prädiktiv sein, da Schaltgewohnheiten fahrerspezifisch sind. Studien zeigen, dass sie zur Fahreridentifikation genutzt werden können. \n",
" → Quelle: [Driver Identification Based on Gear Shift Events and Attention-Based Bidirectional Long Short-Term Memory for Manual Transmission System)](https://ieeexplore.ieee.org/document/10034086)\n",
"\n",
"3. **Harte Bremsmanöver (metrisch):** \n",
" Anzahl starker Bremsvorgänge mit hoher Verzögerung (>0,3g). Modellierung z.B. als Poisson-verteilte Zufallsvariable mit geringem Mittelwert (wenige Ereignisse pro 100km). Harte Bremsmanöver korrelieren mit aggressiver Fahrweise und sind prädiktiv für Fahrerwechsel. \n",
" → Quelle: [Tesla Safety Score Definition](https://www.findmyelectric.com/blog/tesla-safety-score-beta-explained)\n",
"\n",
"4. **Geschwindigkeitsüberschreitungen (ordinal, 3 Kategorien):** \n",
" haeufigkeit bzw. Ausmaß, mit dem Tempolimits überschritten werden. Kategorisierung z.B. in: \n",
" - *selten*, \n",
" - *manchmal*, \n",
" - *haeufig* zu schnell. \n",
" Diese Variable ist prädiktiv, da ein fremder Fahrer oft ein anderes Risikoverhalten beim Speeding zeigt.\n",
" Laut einer AAA-Verkehrssicherheitsstudie geben nahezu 50% der Fahrer an, auf Autobahnen im letzten Monat ~15mph (~24km/h) über dem Tempolimit gefahren zu sein.\n",
" → Quelle: [87 Percent of Drivers Engage in Unsafe Behaviors While Behind the Wheel](https://newsroom.aaa.com/2016/02/87-percent-of-drivers-engage-in-unsafe-behaviors-while-behind-the-wheel/)\n",
"\n",
"---\n",
"\n",
"#### Nicht erklärende Variablen:\n",
"\n",
"\n",
"5. **Wetterbedingungen (nominal, 3 Kategorien):** \n",
" - *trocken* (~7075%) \n",
" - *nass* (~2025%) \n",
" - *winterlich* (<5%) \n",
" → Modelliert als Multinomial. Kontextvariable. \n",
" Die Einteilung basiert auf Daten des Statistischen Bundesamtes: Etwa 7075% aller Fahrten finden unter trockenen Bedingungen statt, 2025% bei Nässe und unter 5% bei Schnee oder Glätte.\n",
"\n",
"6. **Fahrstrecke (metrisch):** \n",
" Länge der Fahrt (z.B. lognormalverteilt um 12km). Kontextvariable, nicht direkt erklärend. \n",
" → Quelle: [Mobilität in Deutschland 2017 Ergebnisbericht](https://www.bmv.de/SharedDocs/DE/Anlage/G/mid-ergebnisbericht.pdf)\n",
"\n",
" \n",
"7. **Straßentyp (nominal, 3 Kategorien):** \n",
" - *Autobahn* (~3033%) \n",
" - *Außerorts* (~43%) \n",
" - *Innerorts* (~2427%) \n",
" → Modelliert als Multinomialverteilung. Kontextvariable ohne direkte Prädiktionswirkung. \n",
" → Quelle: [Klimaschutzinstrumente im Verkehr](https://openumwelt.de/server/api/core/bitstreams/07bd23f9-ff0a-41e5-b89b-8d7baf0a5c36/content)\n",
"\n",
"8. **Wochentag (nominal, 23 Kategorien):** \n",
" Z.B. *Werktag* vs *Wochenende* oder *MoFr*, *Sa*, *So*. Modellierung als kategorische Variable. Kontextvariable. \n",
" → Quelle: [Mobilität in Deutschland 2017 Ergebnisbericht](https://www.bmv.de/SharedDocs/DE/Anlage/G/mid-ergebnisbericht.pdf)\n"
]
},
{
"cell_type": "markdown",
"id": "1468207b",
"metadata": {},
"source": [
"### Bibliotheken Imports"
]
},
{
"cell_type": "code",
"execution_count": 68,
"id": "97ba29a9",
"metadata": {},
"outputs": [],
"source": [
"# Import der benötigten Bibliotheken\n",
"import numpy as np\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"import seaborn as sns\n",
"from scipy.stats import norm, multinomial, poisson, lognorm, bernoulli\n",
"import statsmodels.api as sm\n",
"from statsmodels.stats.outliers_influence import variance_inflation_factor\n",
"\n",
"np.random.seed(11)\n",
"N = 1_000_000"
]
},
{
"cell_type": "markdown",
"id": "27947656",
"metadata": {},
"source": [
"### Verteilungen der Variablen"
]
},
{
"cell_type": "code",
"execution_count": 69,
"id": "61247da5",
"metadata": {},
"outputs": [],
"source": [
"# 1. Durchschnittsgeschwindigkeit (metrisch, normalverteilt)\n",
"avg_speed = np.clip(np.random.normal(loc=47, scale=10, size=N), 10, 130)\n",
"\n",
"# 2. Schaltverhalten (ordinal, 3 Kategorien)\n",
"shift_behavior = np.random.choice(['frueh', 'normal', 'spaet'], size=N, p=[0.4, 0.4, 0.2])\n",
"\n",
"# 3. Harte Bremsmanöver (metrisch, Poisson)\n",
"hard_brakes = np.random.poisson(lam=2, size=N)\n",
"\n",
"# 4. Geschwindigkeitsüberschreitungen (ordinal, 3 Kategorien) Abhängigkeit von avg_speed\n",
"def softmax(x):\n",
" e_x = np.exp(x - np.max(x, axis=1, keepdims=True))\n",
" return e_x / e_x.sum(axis=1, keepdims=True)\n",
"\n",
"speed_scaled = (avg_speed - avg_speed.min()) / (avg_speed.max() - avg_speed.min())\n",
"strength = 0.18\n",
"logits = np.zeros((N, 3))\n",
"logits[:, 0] = 1 - strength * speed_scaled # selten\n",
"logits[:, 1] = 1 # manchmal\n",
"logits[:, 2] = 1 + strength * speed_scaled # haeufig\n",
"probs = softmax(logits)\n",
"speeding = [np.random.choice(['selten', 'manchmal', 'haeufig'], p=p) for p in probs]\n",
"\n",
"# 5. Wetterbedingungen (nominal, Kontext)\n",
"weather = np.random.choice(['trocken', 'nass', 'winterlich'], size=N, p=[0.75, 0.2, 0.05])\n",
"\n",
"# 6. Fahrstrecke (metrisch, lognormal)\n",
"mu, sigma = np.log(12), 0.7\n",
"trip_distance = np.random.lognormal(mean=mu, sigma=sigma, size=N)\n",
"\n",
"# 7. Straßentyp (nominal, Kontext) Abhängigkeit von trip_distance mit Softmax-Funktion\n",
"# Skaliere trip_distance auf [0, 1]\n",
"dist_scaled = (trip_distance - trip_distance.min()) / (trip_distance.max() - trip_distance.min())\n",
"road_strength = 0.18\n",
"road_logits = np.zeros((N, 3))\n",
"road_logits[:, 0] = 1 - road_strength * dist_scaled # Innerorts\n",
"road_logits[:, 1] = 1 # Außerorts\n",
"road_logits[:, 2] = 1 + road_strength * dist_scaled # Autobahn\n",
"road_probs = softmax(road_logits)\n",
"road_type = [np.random.choice(['Innerorts', 'Außerorts', 'Autobahn'], p=p) for p in road_probs]\n",
"\n",
"# 8. Wochentag (nominal, Kontext)\n",
"weekday = np.random.choice(['Mo-Fr', 'Sa', 'So'], size=N, p=[0.7, 0.15, 0.15])"
]
},
{
"cell_type": "markdown",
"id": "defebcc1",
"metadata": {},
"source": [
"### Zusammenführen der Daten in ein DataFrame"
]
},
{
"cell_type": "code",
"execution_count": 70,
"id": "f8e0efb0",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>avg_speed</th>\n",
" <th>shift_behavior</th>\n",
" <th>hard_brakes</th>\n",
" <th>speeding</th>\n",
" <th>weather</th>\n",
" <th>trip_distance</th>\n",
" <th>road_type</th>\n",
" <th>weekday</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>64.494547</td>\n",
" <td>frueh</td>\n",
" <td>2</td>\n",
" <td>manchmal</td>\n",
" <td>trocken</td>\n",
" <td>30.449962</td>\n",
" <td>Innerorts</td>\n",
" <td>Mo-Fr</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>44.139270</td>\n",
" <td>frueh</td>\n",
" <td>3</td>\n",
" <td>haeufig</td>\n",
" <td>trocken</td>\n",
" <td>11.911103</td>\n",
" <td>Autobahn</td>\n",
" <td>Mo-Fr</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>42.154349</td>\n",
" <td>spaet</td>\n",
" <td>2</td>\n",
" <td>selten</td>\n",
" <td>trocken</td>\n",
" <td>6.086055</td>\n",
" <td>Autobahn</td>\n",
" <td>Mo-Fr</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>20.466814</td>\n",
" <td>normal</td>\n",
" <td>5</td>\n",
" <td>haeufig</td>\n",
" <td>trocken</td>\n",
" <td>5.732684</td>\n",
" <td>Innerorts</td>\n",
" <td>Mo-Fr</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>46.917154</td>\n",
" <td>spaet</td>\n",
" <td>2</td>\n",
" <td>selten</td>\n",
" <td>trocken</td>\n",
" <td>7.256758</td>\n",
" <td>Außerorts</td>\n",
" <td>Mo-Fr</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" avg_speed shift_behavior hard_brakes speeding weather trip_distance \\\n",
"0 64.494547 frueh 2 manchmal trocken 30.449962 \n",
"1 44.139270 frueh 3 haeufig trocken 11.911103 \n",
"2 42.154349 spaet 2 selten trocken 6.086055 \n",
"3 20.466814 normal 5 haeufig trocken 5.732684 \n",
"4 46.917154 spaet 2 selten trocken 7.256758 \n",
"\n",
" road_type weekday \n",
"0 Innerorts Mo-Fr \n",
"1 Autobahn Mo-Fr \n",
"2 Autobahn Mo-Fr \n",
"3 Innerorts Mo-Fr \n",
"4 Außerorts Mo-Fr "
]
},
"execution_count": 70,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = pd.DataFrame({\n",
" 'avg_speed': avg_speed,\n",
" 'shift_behavior': shift_behavior,\n",
" 'hard_brakes': hard_brakes,\n",
" 'speeding': speeding,\n",
" 'weather': weather,\n",
" 'trip_distance': trip_distance,\n",
" 'road_type': road_type,\n",
" 'weekday': weekday\n",
"})\n",
"\n",
"df.head()\n"
]
},
{
"cell_type": "markdown",
"id": "f06e7c4d",
"metadata": {},
"source": [
"### VIF der Abhängigkeiten prüfen"
]
},
{
"cell_type": "code",
"execution_count": 71,
"id": "6bfb199a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"Variance Inflation Factor (VIF) für ausgewählte Variabeln:\n",
" features VIF Factor\n",
"0 avg_speed 2.570716\n",
"1 speeding_manchmal 1.819868\n",
"2 speeding_selten 1.750848\n"
]
}
],
"source": [
"vif = pd.DataFrame()\n",
"columns = ['avg_speed', 'speeding']\n",
"vif_df = pd.get_dummies(df[columns], drop_first=True)\n",
"vif_df = vif_df.astype(float)\n",
"vif['features'] = vif_df.columns\n",
"vif['VIF Factor'] = [variance_inflation_factor(vif_df.values, i) for i in range(vif_df.shape[1])]\n",
"vif = vif.sort_values('VIF Factor', ascending=False).reset_index(drop=True)\n",
"print(\"\\nVariance Inflation Factor (VIF) für ausgewählte Variabeln:\")\n",
"print(vif)"
]
},
{
"cell_type": "code",
"execution_count": 72,
"id": "1d3df64a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"Variance Inflation Factor (VIF) für ausgewählte Variabeln:\n",
" features VIF Factor\n",
"0 trip_distance 1.677148\n",
"1 road_type_Außerorts 1.342378\n",
"2 road_type_Innerorts 1.334770\n"
]
}
],
"source": [
"vif = pd.DataFrame()\n",
"columns = ['road_type', 'trip_distance']\n",
"vif_df = pd.get_dummies(df[columns], drop_first=True)\n",
"vif_df = vif_df.astype(float)\n",
"vif['features'] = vif_df.columns\n",
"vif['VIF Factor'] = [variance_inflation_factor(vif_df.values, i) for i in range(vif_df.shape[1])]\n",
"vif = vif.sort_values('VIF Factor', ascending=False).reset_index(drop=True)\n",
"print(\"\\nVariance Inflation Factor (VIF) für ausgewählte Variabeln:\")\n",
"print(vif)"
]
},
{
"cell_type": "code",
"execution_count": 73,
"id": "49045ee5",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>avg_speed</th>\n",
" <th>shift_behavior</th>\n",
" <th>hard_brakes</th>\n",
" <th>speeding</th>\n",
" <th>weather</th>\n",
" <th>trip_distance</th>\n",
" <th>road_type</th>\n",
" <th>weekday</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>64.494547</td>\n",
" <td>frueh</td>\n",
" <td>2</td>\n",
" <td>manchmal</td>\n",
" <td>trocken</td>\n",
" <td>30.449962</td>\n",
" <td>Innerorts</td>\n",
" <td>Mo-Fr</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>44.139270</td>\n",
" <td>frueh</td>\n",
" <td>3</td>\n",
" <td>haeufig</td>\n",
" <td>trocken</td>\n",
" <td>11.911103</td>\n",
" <td>Autobahn</td>\n",
" <td>Mo-Fr</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>42.154349</td>\n",
" <td>spaet</td>\n",
" <td>2</td>\n",
" <td>selten</td>\n",
" <td>trocken</td>\n",
" <td>6.086055</td>\n",
" <td>Autobahn</td>\n",
" <td>Mo-Fr</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>20.466814</td>\n",
" <td>normal</td>\n",
" <td>5</td>\n",
" <td>haeufig</td>\n",
" <td>trocken</td>\n",
" <td>5.732684</td>\n",
" <td>Innerorts</td>\n",
" <td>Mo-Fr</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>46.917154</td>\n",
" <td>spaet</td>\n",
" <td>2</td>\n",
" <td>selten</td>\n",
" <td>trocken</td>\n",
" <td>7.256758</td>\n",
" <td>Außerorts</td>\n",
" <td>Mo-Fr</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" avg_speed shift_behavior hard_brakes speeding weather trip_distance \\\n",
"0 64.494547 frueh 2 manchmal trocken 30.449962 \n",
"1 44.139270 frueh 3 haeufig trocken 11.911103 \n",
"2 42.154349 spaet 2 selten trocken 6.086055 \n",
"3 20.466814 normal 5 haeufig trocken 5.732684 \n",
"4 46.917154 spaet 2 selten trocken 7.256758 \n",
"\n",
" road_type weekday \n",
"0 Innerorts Mo-Fr \n",
"1 Autobahn Mo-Fr \n",
"2 Autobahn Mo-Fr \n",
"3 Innerorts Mo-Fr \n",
"4 Außerorts Mo-Fr "
]
},
"execution_count": 73,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.head()"
]
},
{
"cell_type": "markdown",
"id": "1f6ee727",
"metadata": {},
"source": [
"### Zielvariable erzeugen"
]
},
{
"cell_type": "code",
"execution_count": 74,
"id": "75318d77",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"C:\\Users\\yann\\AppData\\Local\\Temp\\ipykernel_7488\\2403674952.py:43: FutureWarning: \n",
"\n",
"Passing `palette` without assigning `hue` is deprecated and will be removed in v0.14.0. Assign the `x` variable to `hue` and set `legend=False` for the same effect.\n",
"\n",
" sns.countplot(x=target, palette='viridis')\n"
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAA20AAAIhCAYAAADdH1JpAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABZb0lEQVR4nO3dfVhUdf7/8deEMALChCLgKKuWZrJolm6GrmGpqImmZlokSRrrrpYR+LN1u1Pb8CZTS3et3JJSi7YUs1SCzJtcRYmVFDW7WU1NECsEdRUQzu+Pvpx1BBEM45TPx3XNdTXnvOec95xB8uXnM59jMwzDEAAAAADAkq6q7wYAAAAAABdGaAMAAAAACyO0AQAAAICFEdoAAAAAwMIIbQAAAABgYYQ2AAAAALAwQhsAAAAAWBihDQAAAAAsjNAGAAAAABZGaAPwsxsyZIg8PT11/PjxC9bcd999cnd319GjR3/y+Y4cOaIpU6YoOzv7ko+xYcMG2Ww2bdiwwdw2ZcoU2Wy2n9xffThw4IBsNpuSkpIu+7l69uwpm81W7aNnz54u9ec+r+25LvW1dcFms2nKlCm1fl3F5zF79uyL1iYlJclms+nAgQO1b7Aan3zyiex2u7755htz27mf3VVXXSUfHx+1adNGd999t959912Vl5dXOk6rVq0UExNzST3YbDY99NBDl/oWXKxZs+aSPotz9ezZU6GhoRet+6l/nuriMy0rK1NAQIDmzp17yce4mEv9+ZakW2+9VXFxcXXaD3AlaVDfDQC48owZM0YrV67Um2++qXHjxlXaX1hYqJSUFEVGRiowMPAnn+/IkSOaOnWqWrVqpU6dOl3SMW666SZt3bpVISEhP7mfK83f//53FRUVVblv+vTpWrVqlYYMGeJS/0u1detWtWjRor7bqDXDMBQXF6fY2Fi1bNnSZd8111yjZcuWSZJOnTql/fv3a+XKlbr77rvVo0cPvf/++3I4HGZ9SkqKfH19f9b+q7JmzRr97W9/+8nB7ecwYMAAbd26Vc2aNbvkY2zatEnHjh3T0KFD67AzVz/l5/uZZ55Rnz599Kc//Unt2rWr486AXz9CG4CfXf/+/eV0OvXaa69VGdreeustnT59WmPGjPlJ5ykrK9PZs2d/0jEq+Pr66pZbbqmTY/0anT59Wg0bNqxy5PFCQXfFihV6//33de+99+qRRx65aL1VGYahM2fOyNPT8xf7M5Kamqp///vfevPNNyvtq+p9Pfjgg1q8eLFGjx6tP/zhD3r77bfNfTfeeONl7/fXpmnTpmratOlPOsa7776rLl26VArddemn/HyHh4erXbt2ev755/XKK6/UYVfAlYHpkQB+dm5ubho1apSysrK0a9euSvsXL16sZs2aqX///pKkvLw8jR07Vi1atJCHh4dat26tqVOnugSyiulJs2bN0l//+le1bt1adrtd69ev1+9+9ztJ0gMPPGBO9Tr3X98//fRTDRo0SI0bN1bDhg1144036p///KdLT1VNj6zKhaYPnT9lrGI61Pr16/WnP/1J/v7+atKkiYYOHaojR464vLa4uFgJCQkKCgqSl5eXbr31VmVlZdV4GtqRI0c0fPhw+fj4yOFwaMSIEcrLy6uytibXoqL3tLQ0jR49Wk2bNpWXl5eKi4sv2kuFPXv2aNSoUerQoYP+8Y9/uOyraopjSUmJ/vrXv+r666+X3W5X06ZN9cADD+jYsWMXPEdpaakCAgIUHR1dad/x48fl6emp+Ph4SdKZM2eUkJCgTp06yeFwqHHjxgoLC9N7771X6bUVU/heeukltW/fXna7Xa+//rq579zP/9ixYxo3bpxCQkLUqFEjBQQE6Pbbb9cnn3xSZc/l5eV69tln9Zvf/EYNGzZUly5dtG7dugu+x3N99NFH6tWrl3x9feXl5aXu3bvX+LULFy7U7373u1qNgDzwwAO644479M4777hMqazq57KoqEgTJ05U69at5eHhoebNmysuLk6nTp2q8tgvv/yyrrvuOtntdoWEhCg5Odll/3//+1/zeA0bNlTjxo3VpUsXvfXWW5KkmJgY/e1vf5Mkl2m4FdMP//a3v+nWW29VQECAvL291aFDB82aNUulpaVV9pOZmakePXrIy8tL11xzjWbMmFHl1NBLVdX0yPT0dN15551q0aKFGjZsqDZt2mjs2LH67rvvKr3eMAylpKTorrvuMre1atVKkZGRSk1N1U033SRPT09df/31eu211yq9via/Y6XKP9+1+T0mSdHR0XrzzTd14sSJS7hKwJWN0AagXowePVo2m63SXyD27Nmj7du3a9SoUXJzc1NeXp5uvvlmffjhh3rqqae0du1ajRkzRtOnT1dsbGyl47744ov6+OOPNXv2bK1du1ZOp1OLFy+WJD3xxBPaunWrtm7dqgcffFCStH79enXv3l3Hjx/XSy+9pPfee0+dOnXSiBEjfpbvez344INyd3fXm2++qVmzZmnDhg0aOXKkS80DDzygefPm6YEHHtB7772nu+66S0OGDKn2O4EVTp8+rd69eystLU3Tp0/XO++8o6CgII0YMaJSbW2vxejRo+Xu7q4lS5bo3Xfflbu7e43ec2FhoYYMGaIGDRpoxYoV8vLyqra+vLxcd955p2bMmKGoqCitXr1aM2bMUHp6unr27KnTp09X+Tp3d3eNHDlSy5cvrzQ986233tKZM2f0wAMPSPoxGP/www+aOHGiVq5cqbfeeku///3vNXToUL3xxhuVjr1y5UotXLhQTz31lD788EP16NGjyh5++OEHSdLTTz+t1atXa/HixbrmmmvUs2fPKv8BYMGCBUpNTdW8efO0dOlSXXXVVerfv7+2bt1a7TVaunSpIiIi5Ovrq9dff13//Oc/1bhxY/Xt2/eiwa2kpEQfffSRbrvttmrrqjJo0CAZhnHBECr9GLDCw8P1+uuva8KECVq7dq0ee+wxJSUlma8/16pVq/Tiiy9q2rRpevfdd9WyZUvde++9evfdd82a+Ph4LVy4UBMmTFBqaqqWLFmiu+++W99//70k6cknn9SwYcMkyfwzf+70w6+//lpRUVFasmSJPvjgA40ZM0bPPfecxo4dW6n/vLw83XfffRo5cqRWrVql/v37a/LkyVq6dOlFr8/539esja+//lphYWFauHCh0tLS9NRTT2nbtm36/e9/XylcbtmyRbm5uS6hTZI+++wzJSQk6NFHH9V7772njh07asyYMdq0aZPL+6vN79iq1OT3mPTjP8icOnXqov/4BaAKBgDUk/DwcMPf398oKSkxtyUkJBiSjC+++MIwDMMYO3as0ahRI+Obb75xee3s2bMNScbu3bsNwzCM/fv3G5KMa6+91uV4hmEYmZmZhiRj8eLFlXq4/vrrjRtvvNEoLS112R4ZGWk0a9bMKCsrMwzDMNavX29IMtavX2/WPP3008b5v0YlGU8//XSl87Rs2dIYNWqU+Xzx4sWGJGPcuHEudbNmzTIkGbm5uYZhGMbu3bsNScZjjz3mUvfWW28ZklyOWZWFCxcakoz33nvPZXtsbGyla1LTa1HR+/3331/tuatSXl5uDBw40LjqqquM1atXV1kT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C5kyZYo6depUbU3Pnj0VFxf3s/QDAKg7hDYAwBUpJiZGNptNNptN7u7uCgwMVJ8+ffTaa6+pvLzcrMvNzVX//v1/1r7qI/QBAKyL0AYAuGL169dPubm5OnDggNauXavbbrtNjzzyiCIjI3X27FlJUlBQkOx2ez13CgC4khHaAABXLLvdrqCgIDVv3lw33XST/vKXv+i9997T2rVrlZSUJKny9Mhvv/1WI0aMkJ+fn5o0aaI777xTBw4cqHTsqVOnKiAgQL6+vho7dqxKSkrMfe+++646dOggT09PNWnSRL1799apU6c0ZcoUvf7663rvvffMUcANGzZIkh577DFdd9118vLy0jXXXKMnn3xSpaWllc67ZMkStWrVSg6HQ/fcc49OnDhRl5cMAFAPCG0AAJzj9ttv1w033KAVK1ZU2vff//5Xt912mxo1aqRNmzZp8+bNatSokfr16+cSytatW6e9e/dq/fr1euutt5SSkqKpU6dK+nG65b333qvRo0dr79692rBhg4YOHSrDMDRx4kQNHz7cHAHMzc1Vt27dJEk+Pj5KSkrSnj179MILL2jRokWaO3euS39ff/21Vq5cqQ8++EAffPCBNm7cqBkzZlzGqwUA+Dk0qO8GAACwmuuvv147d+6stD05OVlXXXWV/vGPf8hms0mSFi9erKuvvlobNmxQRESEJMnDw0OvvfaavLy89Nvf/lbTpk3T//t//0/PPPOMcnNzdfbsWQ0dOlQtW7aUJHXo0ME8h6enp4qLixUUFORy7ieeeML871atWikhIUFvv/22Jk2aZG4vLy9XUlKSfHx8JEnR0dFat26dnn322Tq6MgCA+kBoAwDgPIZhmKHsXFlZWfrqq6/MUFThzJkz+vrrr83nN9xwg7y8vMznYWFhOnnypA4dOqQbbrhBvXr1UocOHdS3b19FRERo2LBh8vPzq7and999V/PmzdNXX32lkydP6uzZs/L19XWpadWqlUtvzZo1U35+fq3eOwDAepgeCQDAefbu3avWrVtX2l5eXq7OnTsrOzvb5fHFF18oKirqose12Wxyc3NTenq61q5dq5CQEM2fP1/t2rXT/v37L/i6jIwM3XPPPerfv78++OAD7dixQ48//rjLlExJcnd3r3S+c1fCBAD8MhHaAAA4x8cff6xdu3bprrvuqrTvpptu0pdffqmAgAC1adPG5eFwOMy6zz77TKdPnzafZ2RkqFGjRmrRooWkH8NU9+7dNXXqVO3YsUMeHh5KSUmR9OPUyrKyMpfz/utf/1LLli31+OOPq0uXLmrbtq2++eaby/H2AQAWRGgDAFyxiouLlZeXp2+//Vb//ve/lZiYqDvvvFORkZG6//77K9Xfd9998vf315133qlPPvlE+/fv18aNG/XII4/o8OHDZl1JSYnGjBmjPXv2aO3atXr66af10EMP6aqrrtK2bduUmJioTz/9VAcPHtSKFSt07NgxtW/fXtKPUxx37typffv26bvvvlNpaanatGmjgwcPKjk5WV9//bVefPFFM+QBAH79+E4bAOCKlZqaqmbNmqlBgwby8/PTDTfcoBdffFGjRo3SVVdV/ndNLy8vbdq0SY899piGDh2qEydOqHnz5urVq5fL98t69eqltm3b6tZbb1VxcbHuueceTZkyRZLk6+urTZs2ad68eSoqKlLLli31/PPPmzfwjo2N1YYNG9SlSxedPHlS69ev15133qlHH31UDz30kIqLizVgwAA9+eST5jEBAL9uNsMwjPpuAgAAAABQNaZHAgAAAICFEdoAAAAAwMIIbQAAAABgYYQ2AAAAALAwQhsAAAAAWBihDQAAAAAsjNAGAAAAABZGaAMAAAAACyO0AQAAAICFEdoAAAAAwMIIbQAAAABgYf8f8UmzWaToYHoAAAAASUVORK5CYII=",
"text/plain": [
"<Figure size 1000x600 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"shift_dummies = pd.get_dummies(shift_behavior, prefix='shift')\n",
"speeding_dummies = pd.get_dummies(speeding, prefix='speeding')\n",
"weather_dummies = pd.get_dummies(weather, prefix='weather')\n",
"road_dummies = pd.get_dummies(road_type, prefix='road')\n",
"weekday_dummies = pd.get_dummies(weekday, prefix='weekday')\n",
"\n",
"X = pd.DataFrame({\n",
" 'avg_speed': avg_speed,\n",
" 'hard_brakes': hard_brakes,\n",
" 'trip_distance': trip_distance\n",
"})\n",
"X = pd.concat([X, shift_dummies, speeding_dummies, weather_dummies, road_dummies, weekday_dummies], axis=1)\n",
"\n",
"# Betas reduziert, damit die Zielvariable nicht zu häufig 1 ist\n",
"betas = np.array([\n",
" 0.015, # avg_speed\n",
" 0.1, # hard_brakes\n",
" 0., # trip_distance\n",
" 0.05, 0.075, # shift_dummies\n",
" 0.05, 0.075, # speeding_dummies\n",
" 0., 0., # weather_dummies\n",
" 0., 0., # road_dummies\n",
" 0., 0. # weekday_dummies\n",
"])\n",
"\n",
"# Sicherstellen, dass die Dimension passt\n",
"X_model = X.iloc[:, :len(betas)]\n",
"\n",
"X_model = X_model.astype(float)\n",
"rauschen = np.random.normal(0, 0.2, size=N)\n",
"\n",
"# Linearkombination + Rauschen + Offset (damit die Zielvariable nicht zu häufig 1 ist)\n",
"lin_comb = X_model.values @ betas + rauschen - 2\n",
"\n",
"# Logistische Funktion → Wahrscheinlichkeiten\n",
"pi = 1 / (1 + np.exp(-lin_comb))\n",
"\n",
"# Zielvariable simulieren\n",
"target = np.random.binomial(1, pi)\n",
"\n",
"# Visualisierung der Verteilung der Zielvariable\n",
"plt.figure(figsize=(10, 6))\n",
"sns.countplot(x=target, palette='viridis')\n",
"plt.title('Verteilung der Zielvariable (Diebstahl: ja/nein)')\n",
"plt.xlabel('Diebstahl')\n",
"plt.ylabel('Anzahl')\n",
"plt.xticks([0, 1], ['Nein', 'Ja'])\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "825cc812",
"metadata": {},
"source": [
"### Verteilungen der Variablen\n",
"\n",
"- **Durchschnittsgeschwindigkeit (`avg_speed`)**: normalverteilt mit Mittelwert 47 km/h und Standardabweichung 10, begrenzt auf den Bereich [10, 130].\n",
"- **Schaltverhalten (`shift_behavior`)**: ordinal skaliert mit 3 Kategorien, gezogen aus einer Multinomialverteilung (Wahrscheinlichkeiten: 40% früh, 40% normal, 20% spät).\n",
"- **Harte Bremsmanöver (`hard_brakes`)**: metrisch, modelliert mit einer Poisson-Verteilung (λ = 2).\n",
"- **Geschwindigkeitsüberschreitungen (`speeding`)**: ordinal skaliert mit 3 Stufen, abhängig von `avg_speed` über eine Softmax-basierte Wahrscheinlichkeitsverteilung.\n",
"- **Wetterbedingungen (`weather`)**: nominal skaliert, zufällig verteilt mit 75% trocken, 20% nass und 5% winterlich.\n",
"- **Fahrstrecke (`trip_distance`)**: lognormal verteilt mit μ = ln(12) und σ = 0.7.\n",
"- **Straßentyp (`road_type`)**: abhängig von `trip_distance`, mit kategorialer Softmax-Verteilung (Innerorts, Außerorts, Autobahn).\n",
"- **Wochentag (`weekday`)**: nominal mit festgelegter Verteilung (70% Werktage, je 15% Samstag und Sonntag).\n",
"\n",
"### Modellierte Abhängigkeiten\n",
"\n",
"- Die Variablen `speeding` und `road_type` wurden nicht rein zufällig erzeugt, sondern basieren auf skalierter Eingangsvariablen (`avg_speed` bzw. `trip_distance`) und einem gewichteten Softmax-Verfahren. Dies erlaubt realistischere Zusammenhänge.\n",
"\n",
"### Zielvariable und 𝑝ᵢ-Werte\n",
"\n",
"Die Zielvariable, die eine Diebstahlwahrscheinlichkeit beschreibt, wurde aus diesen Features modelliert. Die 𝑝ᵢ-Werte repräsentieren dabei individuelle Wahrscheinlichkeiten für Fahrerwechsel und wurden anhand von Beta-Verteilungen erzeugt.\n",
"\n",
"### Wahl und Begründung der Beta-Werte\n",
"\n",
"Die Beta-Gewichte wurden bewusst so gewählt, dass sie realistische Zusammenhänge zwischen den Merkmalen und dem Auftreten eines möglichen Diebstahls modellieren, ohne die Zielvariable künstlich zu verzerren. Das Ziel war ein realistischer, aber nicht übermäßig häufiger positiver Klassenanteil.\n",
"\n",
"- **`avg_speed (0.015)`**: Ein leicht positiver Zusammenhang, da ungewöhnliche Geschwindigkeit (insbesondere zu hohe) auf atypisches Fahrverhalten hindeuten kann.\n",
"- **`hard_brakes (0.1)`**: Ein höherer Beta-Wert, da aggressive Bremsmanöver oft stark mit ungewohnten Fahrstilen korrelieren.\n",
"- **`trip_distance (0)`**: Kein Einfluss, da die reine Strecke keine Aussagekraft hat.\n",
"- **`shift_behavior` (0.05, 0.075)**: Personen, die spät schalten, zeigen eher sportliches oder ineffizientes Verhalten potenziell abweichend vom üblichen Fahrerprofil.\n",
"- **`speeding` (0.05, 0.075)**: Häufige Geschwindigkeitsüberschreitungen deuten ebenfalls auf untypisches Fahrverhalten hin.\n",
"- **`weather` (0, 0)**: Wetterbedingungen spielen keine Rolle.\n",
"- **`road_type` (0, 0)**: Verschiedene Straßentypen implizieren ebenfalls kein Fahrerprofil\n",
"- **`weekday` (0, 0)**: Ebenfalls unbedeutend für den Fahrstil.\n",
"\n",
"Alle Beta-Werte wurden bewusst reduziert (unterhalb von 0.1), um eine Übergewichtung einzelner Faktoren zu vermeiden und die Zielvariable `Diebstahl` in einem realistischen Bereich (ca. 1012%) zu halten. Eine stärkere Gewichtung hätte zu einer zu häufigen Klassifikation als Diebstahl geführt.\n",
"\n",
"```visualisierung\n",
"Die grafische Darstellung zeigt, dass rund 11% der Fahrten als potenzielle Diebstähle klassifiziert wurden ein realistischer Wert, der ein geeignetes Trainingsverhältnis für ein Klassifikationsmodell ermöglicht.\n",
"```\n",
"\n"
]
},
{
"cell_type": "markdown",
"id": "adbc166b",
"metadata": {},
"source": [
"## Simulation der Perspektive des Data Scientist"
]
},
{
"cell_type": "markdown",
"id": "f8abd5f5",
"metadata": {},
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "hft_ml",
"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.11.10"
}
},
"nbformat": 4,
"nbformat_minor": 5
}