Benutzer-Werkzeuge

Webseiten-Werkzeuge


ss25:vermoegenssimulation:technische_details

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen gezeigt.

Link zu dieser Vergleichsansicht

Nächste Überarbeitung
Vorhergehende Überarbeitung
ss25:vermoegenssimulation:technische_details [2025/07/02 15:13]
matteo06 angelegt
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.
  
-Dafür gibt es mehrere Lösungen. Wir haben uns entschieden wie bei linearer Regression vorzugehen, nur mit dem Ziel, das die Integrale im Bereich der Quantile $Q$ gleich dem Wert der Quantile sind und nicht möglichst viele Punkte getroffen werden sollen. Als Ergebnis erhält man eine Dichtefunktion,​ die angibt, wie viele Einkommen an eine Stelle liegt. Die Dichtefunktion $f$ ist dann wie folgt definiert+Dafür gibt es mehrere Lösungen. Wir haben uns entschieden wie bei linearer Regression vorzugehen, nur mit dem Ziel, das die Integrale im Bereich der Quantile $Q$ gleich dem Wert der Quantile sind und nicht möglichst viele Punkte getroffen werden sollen. Als Ergebnis erhält man eine Dichtefunktion,​ die angibt, wie viele Einkommen an eine Stelle liegt. Die Dichtefunktion $f$ ist dann wie folgt definiert
 + 
 +$$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. 
 + 
 +Also das: 
 +$$ Quantilwert \approx \int_{x_{von}}^{x_{bis}} f(x) \, dx $$ 
 + 
 +Dazu muss eine Loss-Funktion definiert werden, die für jede Eingabe an Parametern ausgibt, wie Groß der Abstand zwischen dem Wert des Integrals und dem gewühntschtem Wert im Qunatil $Q$ ist.  
 +Die Lossfunktion $l$ lässt sich definieren als: 
 + 
 +$$ l(\beta_0, \beta_1) = \sum_{i=1}^{n} \left( d[i] - \int_{\frac{i-1}{n}}^{\frac{i}{n}} \beta_0 + \beta_1 \cdot x^g \,dx \right)^2$$ 
 + 
 +wobei: 
 +  * $beta_0$: Y-Achsenabschnitt 
 +  * $beta_1$: Regressionskoeffizienz / Steigung der Parabell 
 +  * $d$: Liste mit allen Quartielwerten 
 +  * $n$: Anzahl an Quartilen $|d|$ 
 +  * $g$: Grad der Zielfunktion 
 + 
 +Alle Parameter, bis auf $\beta_0$ und $\beta_1$, müssen vorher gegeben sein! 
 + 
 +Da es sich um eine Polynomenfunktion handelt, kann das Integral symbolisch gelöst weren (Quelle ChatGPT). Dadurch gilt folgendes:​ 
 +\begin{align*} 
 +\int_{a}^{b} \beta_1 \cdot x^g + \beta_0 \, dx &= \beta^1 \cdot \int_{a}^{b} x^g \, dx \cdot \int_{a}^{b} 1 \, dx = \beta_1 \cdot \left[ \frac{x^{g+1}}{g+1} \right]^b_a + \beta_0 \cdot (b-a) \\ 
 +&= \beta_1 \cdot \left( \frac{b^{g+1} - a^{g+1}}{g+1} \right) + \beta_0 \cdot (b-a) 
 +\end{align*} 
 + 
 +Dadurch kann die Loss-Funktion wie folgt geschrieben werden: 
 +$$ 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 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>​
ss25/vermoegenssimulation/technische_details.1751462000.txt.gz · Zuletzt geändert: 2025/07/02 15:13 von matteo06