Hier werden die Unterschiede zwischen zwei Versionen gezeigt.
Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
ss25:vermoegenssimulation:technische_details [2025/07/02 15:13] matteo06 |
ss25:vermoegenssimulation:technische_details [2025/07/02 17:18] (aktuell) matteo06 |
||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
- | ==== Aus Quantilen eine Verteilung bestimmten ==== | + | ===== Technische Details ===== |
+ | Genauere Erklärung einiger Funktionen | ||
+ | |||
+ | ==== Aus Quantilen eine Verteilung bestimmten ==== | ||
**Problem:** Für eine gewisse Anzahl an Agenten relative Werte festlegen, wobei vorher definierte Quantiele mit relativen nicht-kumulierten Werten erfüllt sein müssen. | **Problem:** Für eine gewisse Anzahl an Agenten relative Werte festlegen, wobei vorher definierte Quantiele mit relativen nicht-kumulierten Werten erfüllt sein müssen. | ||
Zeile 7: | Zeile 10: | ||
$$f(x) = \beta_1 \cdot x^g + \beta_0 $$ | $$f(x) = \beta_1 \cdot x^g + \beta_0 $$ | ||
- | und hat folgende Parameter $\beta_1$ und $\beta_0$, die Verändert werden können. Der Grad der Funktion $g$ muss vorher gegeben sein. Für diese Parameter soll nun ein Wert gefunden werden, der ermöglicht, das die Integralle im Bereich der Quantile $Q$ der Funktion $d$ dem Wert der Quantile entspricht. Ein Bild um das zu Verstehen: [Noch Einfügen!] | + | und hat folgende Parameter $\beta_1$ und $\beta_0$, die Verändert werden können. Der Grad der Funktion $g$ muss vorher gegeben sein. Für diese Parameter soll nun ein Wert gefunden werden, der ermöglicht, das die Integralle im Bereich der Quantile $Q$ der Funktion $d$ dem Wert der Quantile entspricht. |
Also das: | Also das: | ||
Zeile 18: | Zeile 21: | ||
wobei: | wobei: | ||
- | - $beta_0$: Y-Achsenabschnitt | + | * $beta_0$: Y-Achsenabschnitt |
- | - $beta_1$: Regressionskoeffizienz / Steigung der Parabell | + | * $beta_1$: Regressionskoeffizienz / Steigung der Parabell |
- | - $d$: Liste mit allen Quartielwerten | + | * $d$: Liste mit allen Quartielwerten |
- | - $n$: Anzahl an Quartilen $|d|$ | + | * $n$: Anzahl an Quartilen $|d|$ |
- | - $g$: Grad der Zielfunktion | + | * $g$: Grad der Zielfunktion |
Alle Parameter, bis auf $\beta_0$ und $\beta_1$, müssen vorher gegeben sein! | Alle Parameter, bis auf $\beta_0$ und $\beta_1$, müssen vorher gegeben sein! | ||
Zeile 35: | Zeile 38: | ||
$$ l(\beta_0, \beta_1) = \sum_{i=1}^{n} \left(d[i] - \left[ \beta_1 \cdot \left( \frac{ \left(\frac{i}{n}\right)^{g+1} - \left(\frac{i-1}{n}\right)^{g+1}}{g+1} \right) + \beta_0 \cdot \frac{1}{n} \right] \right)^2 $$ | $$ l(\beta_0, \beta_1) = \sum_{i=1}^{n} \left(d[i] - \left[ \beta_1 \cdot \left( \frac{ \left(\frac{i}{n}\right)^{g+1} - \left(\frac{i-1}{n}\right)^{g+1}}{g+1} \right) + \beta_0 \cdot \frac{1}{n} \right] \right)^2 $$ | ||
- | Nun kann mit der Funktion `minimize` aus `scipy.optimize` das Problem, die besten Werte für $\beta_0$ und $\beta_1$ zu finden, gelöst werden. Wie genau weiß ich auch nicht. | + | Nun kann mit der Funktion ''minimize'' aus ''scipy.optimize'' das Problem, die besten Werte für $\beta_0$ und $\beta_1$ zu finden, gelöst werden. Wie genau die Lösungsalgorithmen funktionieren weiß ich auch nicht. |
+ | |||
+ | <code python> | ||
+ | import matplotlib.pyplot as plt | ||
+ | import numpy as np | ||
+ | from scipy.optimize import minimize | ||
+ | |||
+ | # Quantile - Hier Dezile als Beispiel | ||
+ | quantile = np.array([3,5,6,7,8,9,10,12,15,25])/100 | ||
+ | # Grad der Funktion | ||
+ | g = 2 | ||
+ | |||
+ | # Weitere Variablen, die berechnet werden | ||
+ | n = len(quantile) | ||
+ | b_0 = 0 | ||
+ | b_1 = 0 | ||
+ | |||
+ | def l(xy): | ||
+ | b_0, b_1 = xy | ||
+ | error = 0 | ||
+ | |||
+ | for i, element in enumerate(quantile): | ||
+ | integral = (b_1 * (((((i+1) / n)**(g+1)) - (((i)/n)**(g+1)))/(g+1)) + b_0 * (1/n)) | ||
+ | error += (element - integral)**2 | ||
+ | return error | ||
+ | |||
+ | def f(x): | ||
+ | return b_1 * (x**g) + b_0 | ||
+ | |||
+ | res = minimize(l, (1,1), method='L-BFGS-B') # (1,1) ist der Startwert | ||
+ | b_0, b_1 = res.x | ||
+ | |||
+ | print(f'Die Funktion lautet: f(x) = {b_1} * x^{g} + {b_0}') | ||
+ | print(f'Der Fehlerwert ist : {l(res.x)}') | ||
+ | |||
+ | # Darstellung der Werte | ||
+ | x = np.linspace(0, 1, 10) | ||
+ | x_quantile = np.linspace(0.05, 0.95, len(quantile)) | ||
+ | plt.figure() | ||
+ | plt.bar(x_quantile, quantile, width=0.1, alpha=0.6, label='Dezile', color='orange', edgecolor='black') | ||
+ | plt.plot(x, f(x), label='f(x)') | ||
+ | plt.title(rf"$f(x) = {b_1}\, \cdot x^{g} + {b_0}$") | ||
+ | plt.legend() | ||
+ | plt.show() | ||
+ | </code> | ||
+ | |||
+ | Aus der Dichtefunktion lassen sich aber noch keine relativen Werte für die Agenten berechnen. Erstmal kann mit der Dichtefunktion $f$ nur ein absoluter Wert für jeden Agenten berechnet werden. Dazu braucht man einen konstanten Wert, der mit dem Funktoinswert von $f$ multipliziert wird. | ||
+ | |||
+ | Also für das absolute Einkommen des Agenten ergibt sich: | ||
+ | $$ Einkommen = f(x) + C $$ | ||
+ | Dabei ist $x$ die realtive Position des Agenten. Wenn der Agent die Position $i$ hat ist $x = \frac{i}{n}$, wobei $n$ die Anzahl von Agenten ist. $C$ ist eine Konstante, die z.B. das durchschnittliche Einkommen pro Person sein könnte. | ||
+ | |||
+ | Um nun das relative Einkommen zu erhalten, muss nur das absolute Einkommen durch das Gesamteinkommen gerechnet werden. Dadruch ergibt sich das Einkommen der Agenten aus: | ||
+ | |||
+ | $$ Einkommen_i = \frac{Absolutes Einkommen}{Gesamteinkommen} = \frac{f(x_i) + C}{\sum_{i=0}^{n} f(x_j) +C } = \frac{f(x_i)}{\sum_{i=0}^{n} f(x_j)} $$ | ||
+ | |||
+ | Das lässt sich sehr einfach mit ''numpy.arrays'' umsetzen. Die gesamte Funktion sieht nun so aus | ||
+ | |||
+ | <code python> | ||
+ | def g(n, Q) -> np.ndarray: | ||
+ | """Die Funktion berechnet für eine Anzalh an Agenten n und Quantilen Q die passende Verteilung | ||
+ | und gibt als Rückgabewert einen Array mit den relativen Werten für jeden Agenten | ||
+ | |||
+ | :param n: Anzahl an Agenten bzw. Werten, die Zurückgegeben werden sollen | ||
+ | :type n: int | ||
+ | :param Q: Liste mit realtiven nicht-kumulierten Quantilwerten | ||
+ | :type Q: list | ||
+ | :return: Liste mit relativen Werten für jeden Agenten bzw. mit Länge n | ||
+ | :rtype: array | ||
+ | """ | ||
+ | |||
+ | array = np.linspace(0.5/n, 1 - 0.5/n, n) # relative Positionen von jedem Agenten | ||
+ | # Variablen zuschreiben | ||
+ | g = 2 | ||
+ | quantile = np.array(Q)/100 | ||
+ | n = len(quantile) | ||
+ | b_0 = 0 | ||
+ | b_1 = 0 | ||
+ | |||
+ | # ALTER CODE - VON OBEN KOPIERT | ||
+ | def l(xy): | ||
+ | b_0, b_1 = xy | ||
+ | error = 0 | ||
+ | |||
+ | for i, element in enumerate(quantile): | ||
+ | integral = (b_1 * (((((i+1) / n)**(g+1)) - (((i)/n)**(g+1)))/(g+1)) + b_0 * (1/n)) | ||
+ | error += (element - integral)**2 | ||
+ | return error | ||
+ | def f(x): | ||
+ | return b_1 * (x**g) + b_0 | ||
+ | |||
+ | # Dichtefunktion f erstellen | ||
+ | res = minimize(l, (1,1), method='L-BFGS-B') # (1,1) ist der Startwert | ||
+ | b_0, b_1 = res.x | ||
+ | |||
+ | print(f'Die Funktion lautet: f(x) = {b_1} * x^{g} + {b_0}') | ||
+ | print(f'Der Fehlerwert ist : {l(res.x)}') | ||
+ | |||
+ | # NEUER CODE | ||
+ | # relative Werte für jeden Agenten Ermitteln | ||
+ | array = f(array) # Für jedes ELement im Array wird die Funktion angewendet | ||
+ | array = array/np.sum(array) # relative Werte erghalten | ||
+ | |||
+ | return array | ||
+ | |||
+ | </code> |