{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"# Computergestützte Datenauswertung\n",
"**Institut für Experimentelle Teilchenphysik (ETP)**
\n",
"**Institut für Theorie der Kondensierten Materie (TKM)**
\n",
"Prof. Dr. Ulrich Husemann (ETP)
\n",
"Dr. Thorsten Chwalek (ETP), Dr. Andreas Poenicke (TKM)
\n",
"[ILIAS-Seite zum Kurs](https://ilias.studium.kit.edu/ilias.php?baseClass=ilrepositorygui&ref_id=2627198)
\n",
"Sommersemester 2025 – Blatt 05
\n",
"Abgabe: Montag, 2.06.2025, oder Dienstag, 3.06.2025\n",
"\n",
"---"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# Wichtig: Anmeldung im Campussystem\n",
"Um die Übung als erfolgreich bestanden anerkannt zu bekommen, müssen Sie sich bis zur Abgabe des letzten Blattes im [Campussytem](https://campus.studium.kit.edu/exams/registration.php) für die Leistung anmelden!\n",
"Die Voraussetzung zum Bestehen ist das erfolgreiche Bearbeiten von mindestens einer Aufgabe in vier der fünf Übungsblätter 1-5 und das erfolgreiche Testat von Übungsblatt 6.
\n",
"Anmeldebeginn:\t26.05.25 08:00
\n",
"Anmeldeschluss:\t13.06.25 14:00
\n",
"Abmeldungen möglich bis 20.06.25 14:00\n",
"\n",
"---\n",
"\n",
"Werbung: Die Reihe 'It's not rocket science' wird fortgesetzt. Hier der Link zum nächsten Vortrag [Link](https://mentoring.physik.kit.edu/kalender.php/event/57577#calendar_top).
\n",
"\n",
"---\n",
"- Die [erste Aufgabe](#Aufgabe1) zeigt Ihnen an einem ausführlichen Beispiel, wie Sie das Werkzeug [`kafe2`](https://kafe2.readthedocs.io) verwenden können, um die Anpassung verlässlich und ohne viel Aufwand durchzuführen. \n",
"Dabei wird Ihnen die Paramaterschätzung einmal \"vorgeführt\" und anschließen haben Sie die Möglichkeit, das Ergebnis aus der Aufgabe vom letzten Übungsblatt zu reproduzieren.\n",
"- In der [zweiten Aufgabe](#Aufgabe2) beschäftigen Sie sich mit einer typischen Herausforderung, die Ihnen bereits in der Vorlesung vorgestellt wurde: Korrelationen zwischen Anpassungsparametern.\n",
"In dieser Aufgabe werden Sie die Korrelationen visualisieren und einen Ansatz zum Umgang mit Korrelationen ausarbeiten."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"# Aufgabe 1: Anpassung von Modellen an Daten mit `kafe2` \n",
"---\n",
"Obwohl sich viele Anpassungsprobleme auch analytisch lösen lassen, werden in der Praxis Software-Werkzeuge eingesetzt, die die Verwaltung von Daten, Modellen und das Durchführen der eigentlichen Anpassung mit numerischen Methoden bewerkstelligen.\n",
"Ein solches Werkzeug ist [`kafe2`](http://kafe2.readthedocs.io). \n",
"Dieses Werkzeug ist am KIT entworfen worden und wird hier ständig weiter entwickelt.\n",
"Mit der Zeit wurde zu `kafe2` einiges an Funktionalität hinzugefügt. Damit bietet `kafe2` ein breites Spektrum von Methoden für die Parameterschätzung an, auch über den Bedarf des physikalischen Praktikums hinaus.\n",
"Lassen Sie sich jedoch noch nicht durch das Paket abschrecken, sondern üben Sie sich in der Anwendung der wichtigsten Funktionen durch das Beispiel in dieser Aufgabe.\n",
"Bei Gelegenheit können Sie gerne durch die [Online-Dokumentation](https://kafe2.readthedocs.io/en/latest/parts/beginners_guide.html) stöbern und sich einen Überblick über die Funktionalität von `kafe2` verschaffen.\n",
"\n",
"Ziel dieser Aufgabe ist, dass Sie anhand des Beispiels und wenigen Veränderungen des Beispielcodes die Parameterschätzung aus dem letzten Übungsblatt wiederholen können. "
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"**Beispiel:**
\n",
"1. `kafe2` bietet eine Struktur, die auf Python-Klassen beruht. Diese Struktur ermöglicht es Ihnen an vielen Stellen die Parameterschätzung (ab hier *Fit* genannt) zu beeinflussen. In der Vorlesung haben Sie die \"Wrapper-Funktionen\" `kafe2.xy_fit()` und `kafe2.plot()` kennengelernt. Hier werden Sie direkt mit den zugrundeliegen Klassen `kafe2.XYFit` und `kafe2.Plot` und deren Methoden arbeiten."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"from kafe2 import XYFit, Plot"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"2. An erster Stelle steht immer das Einlesen Ihrer gemessenen Daten. \n",
"In diesem Beispiel gehen Sie den kurzen Weg und tragen \"Messpunkte\" direkt in die Sequenzen `x` und `y` ein.\n",
"In der Anwendung in physikalischen Praktikum werden Sie hier `NumPy`, `PhyPraKit` oder Ähnliches verwenden, um die Daten direkt aus einer Datei auszulesen, die Ihr Messcomputer ausgibt.\n",
"Im Beispiel nehmen Sie an, dass `x` mit unendlicher Genauigkeit gemessen wurde und nicht mit einer Unsicherheit behaftet ist.\n",
"Auf `y` nehmen Sie die Unsicherheiten in `yerr` an.\n",
"Die Sequenzen `x`, `y` und `yerr` können Sie praktisch in jeder Form (Liste, *Numpy*-Array, ...) angeben oder ein `kafe2.XYContainer`-Objekt verwenden.\n",
"Mehr dazu finden Sie in der Dokumentation von `kafe2`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# \"Einlesen\" der Daten\n",
"x = [.05, 0.36, 0.68, 0.80, 1.09, 1.46, 1.71, 1.83, 2.44, 2.09, 3.72, 4.36, 4.60]\n",
"y = [0.35, 0.26, 0.52, 0.44, 0.48, 0.55, 0.66, 0.48, 0.75, 0.70, 0.75, 0.80, 0.90]\n",
"yerr = [0.06, 0.07, 0.05, 0.05, 0.07, 0.07, 0.09, 0.1, 0.11, 0.1, 0.11, 0.12, 0.1]"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"3. Das Modell, welches Sie an die Daten anpassen (oder *fitten*) wollen, können Sie selbstständig als Funktion definieren.\n",
"Es bietet sich an, dass das erste Argument den $x$-Werten entspricht, die Sie vorgeben und fitten wollen.\n",
"Alle weiteren Argumente der Funktionen sind die freien Parameter, die Sie fitten.\n",
"In diesem Beispiel passen Sie den vorgegebenen Daten ein Polynom zweiten Grades an, welches Sie in der Funktion `poly2()` definieren.\n",
"Alternativ bietet `kafe2` selbst einige einfache Funktionen (wie Polynome), die im nächsten Schritt übergeben können.\n",
"Zur besseren Veranschaulichung definieren Sie hier jedoch die Funktion selbst."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Definition des anzupassenden Modells\n",
"def poly2(x, a=1.0, b=0.0, c=0.0):\n",
" return a * x**2 + b * x + c"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"4. Jetzt können Sie den Fit selbst zusammenstellen, indem Sie ein `XYFit`-Objekt erzeugen, welches auf jeden Fall zwei Argumente benötigt.\n",
" - Sie müssen dem Argument `xy_data` die Daten, die Sie fitten wollen, übergeben. Ein Objekt der Klasse `kafe2.XYContainer` könnten Sie hier direkt verwenden. Sie überspringen diesen Schritt und übergeben die Daten direkt als verschachtelte Liste in der Reihenfolge $x$, $y$.\n",
" - Dem Argument `model_function` übergeben Sie die Funktion (ohne Argumente), die das Modell beschreibt, welches gefittet werden soll.\n",
"\n",
" Sie erzeugen ein Objekt der Klasse `XYFit` mit dem Namen `fit`, auf die Sie im folgenden noch zugreifen werden und woran Sie noch weitere Anpassungen vornehmen werden."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Definition des Fits\n",
"fit = XYFit(xy_data=[x, y], model_function=poly2)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"5. An dieser Stelle können Sie nun die Unsicherheiten der Messungen an das Objekt `fit` übergeben.\n",
"Dazu können Sie die Methode `add_error()` der Klasse `XYFit` verwenden.\n",
"(Anmerkung: Sie hätten diesen Schritt auch direkt mit dem `XYContainer` durchführen können.)\n",
"Die Methode `add_error()` übernimmt mit dem Argument `axis` die Achse, an der die Unsicherheiten angenommen werden.\n",
"Sie können also `x` (oder 0) oder `y` (oder 1) angeben.\n",
"Dem Argument `err_val` übergeben Sie den Wert der Unsicherheit.\n",
"Sie können hier entweder eine Zahl angeben, wenn Sie davon ausgehen, dass für jeden Messwert die gleiche Unsicherheit vorliegt, oder eine Sequenz mit der gleichen Länge wie die Achse, an der die Unsicherheit anliegt.\n",
"Weitere praktische Argumente an dieser Stelle sind auch `correlation` (Zahl) und `relative` (`True` oder `False`).\n",
"Im physikalischen Praktikum werden Sie häufiger die Situation vorfinden, dass an Geräten ein relativer Fehler angegeben wird (z. B. 10%). In diesem Fall würden Sie `err_val=0.1, relative=True` setzen. Es könnte auch eine Korrelation zwischen beispielsweise Strom- und Spannungsmessung angegeben werden.\n",
"(Anmerkung: Sie können einer Achse auch mehrere Unsicherheiten aus unterschiedlichen Quellen mit `add_error()` hinzufügen.)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Hinzufügen der Unsicherheiten\n",
"fit.add_error(axis='y', err_val=yerr)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"6. Der nächste Schritt im Beispiel ist rein optional und setzt einen schönen Ausdruck für die Darstellung der Modellfunktion im späteren Plot."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Optional: LaTeX Ausdrücke für den Plot festlegen\n",
"fit.assign_parameter_latex_names(a='A', b='B', c=\"C\")\n",
"fit.assign_model_function_latex_expression(r\"{a}\\,x^2 + {b}\\,x+{c}\")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"7. Mit der Methode `XYFit.do_fit()` führen Sie nun den Fit selbst durch.\n",
"Sie müssen sich an dieser Stelle keine Gedanken über den Minimierungsprozess des Maßes oder der Berechnung und Propagation der Unsicherheiten machen.\n",
"Diese Schritte werden für Sie im Hintergrund erledigt."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Fit ausführen\n",
"fit.do_fit()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"8. Die Methode `XYFit.report()` gibt Ihnen ausführliche Informationen darüber, wie der Fit durchgelaufen ist. \n",
"Dieser Schritt ist optional, aber sehr hilfreich, wenn Sie herausfinden wollen, warum Ihr Fit gerade nicht funktioniert hat."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Optional: Ausführlicher Bericht über den Fit\n",
"fit.report()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"9. Der letzte Schritt ist das Darstellen des Ergebnisses und ist ebenfalls optional.\n",
"Sie erzeugen hier ein Objekt der Klasse `Plot` und übergeben den erfolgreich durchgeführten Fit. \n",
"Mit der Methode `Plot.plot()` führen Sie die Darstellung des Ergebnisses aus.\n",
"An dieser Stelle können Sie viele Optionen zur Visualisierung übergeben, lesen Sie dazu auch gerne in der Dokumentation weiter."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Optional: Darstellung des Fits im kafe2-Stil\n",
"plot = Plot(fit)\n",
"plot.y_label = \"$y$\"\n",
"plot.x_label = \"$x$\"\n",
"plot.plot()\n",
"\n",
"plt.show()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"**Wiederholung: Güte der Anpassung:**
\n",
"In der grafischen Darstellung von `kafe2` und in der Ausgabe von `XYFit.do_fit()` finden Sie die Begriffe $\\chi^2/\\mathrm{ndf}$ und $\\chi^2\\ \\mathrm{probability}$.\n",
"Diese Größen sind ein Maß für die Qualität des Fit. Sie geben auch Hinweise darauf wie einfach Sie den Fit mit einem anderen Datensatz aus der gleichen Grundmenge wiederholen könnten.\n",
"Dabei gelten folgende Faustregeln:\n",
"- Werte von $\\chi^2/\\mathrm{ndf}\\approx 1$ bzw. $\\chi^2\\ \\mathrm{probability}\\sim 0.4$ zeigen einen sehr guten Fit.\n",
"- Werte von $\\chi^2/\\mathrm{ndf}\\ll 1$ bzw. $\\chi^2\\ \\mathrm{probability}\\to 1$ deuten darauf hin, dass das Modell sich sehr stark an die gegebenen Daten angepasst hat und \"zu gut passt\". Würden Sie andere Daten aus derselben Grundmenge fitten, wird dieser Fit voraussichtlich kein gutes Ergebnis erzielen können. Mögliche Lösungen:\n",
" - Vielleicht haben Sie die Unsicherheit zu groß geschätzt - Überprüfen Sie nochmal Ihre Berechnungen.\n",
" - Das Modell hat zu viele Freiheitsgrade und kann sich einzelnen Abweichungen anpassen. Wählen Sie ein einfacheres Modell.\n",
"- Für Werte von $\\chi^2/\\mathrm{ndf}\\gg 1$ bzw. $\\chi^2\\ \\mathrm{probability}\\to 0$) kann das Modell die Daten nicht genügend gut beschreiben. Mit diesem Modell werden Sie kaum eine statistisch sinnvolle Aussage über die Daten treffen können. Mögliche Lösungen:\n",
" - Vielleicht haben Sie die Unsicherheit zu klein geschätzt - Überprüfen Sie nochmal Ihre Berechnungen.\n",
" - Das Modell hat zu wenige Freiheitsgrade und kann sich den Daten nur schlecht anpassen. Wählen Sie ein anderes Modell."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"**Arbeitsanweisung:**
\n",
"Führen Sie die Parameterschätzung der Dämpfungskonstante $D$ der gemessenen Resonanzkurve aus [Aufgabe 1](#Aufgabe1) hier nochmal durch.\n",
"Verwenden Sie hierfür `kafe2`, indem Sie das Beispiel von oben an wenigen Stellen anpassen."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Resonanzfunktion\n",
"def resonance(eta, D):\n",
" return 1/np.sqrt((1 - eta*eta)**2 + (2*eta*D)**2)\n",
"\n",
"# Gemesse Datenpunkt\n",
"etam = np.array([0.10, 0.30, 0.50, 0.70, 0.90, 1.10, 1.30, 1.50, 1.70, 1.90, 2.10])\n",
"Am = np.array([0.97, 0.92, 1.12, 1.09, 1.36, 1.17, 0.76, 0.54, 0.47, 0.41, 0.36])\n",
"\n",
"# Absolute Unsicherheit auf die gemessene Amplitude\n",
"Aerr = 0.1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Definition des Fits\n",
"\n",
"# Hinzufügen der Unsicherheiten\n",
"\n",
"# Fit ausführen\n",
"\n",
"# Optional: Ausführlicher Bericht über den Fit\n",
"\n",
"# Darstellung des Fits im kafe20Stil\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"# Aufgabe 2: Korrelation von Fit-Parametern \n",
"---\n",
"\n",
"In der Vorlesung haben Sie analytisch die Parameterschätzung für eine Ausgleichsgerade $\\lambda(x;\\mathbf{a})=a_0+a_1 x$ ausgerechnet.\n",
"Im letzten Schritt ist Ihnen dabei aufgefallen, dass die Parameter $a_0$ und $a_1$ stark antikorreliert sind.\n",
"Sie können sich das veranschaulichen, indem Sie sich vorstellen, dass Sie die Gerade, die bei $x=0$ beginnt und zu positiven $x$-Werten läuft, an der Stelle $x=0$ festhalten und wie einen Stab bewegen können.\n",
"Wenn Sie nun die Steigung anpassen (den Stab also kippen), bewegt sich auch gleichzeitig der Ordinatenabschnitt (Ihre Hand), wenn Sie dieselben Datenpunkte durchlaufen möchten.\n",
"\n",
"\n",
"\n",
"Um dies näher zu studieren, schauen Sie sich in dieser Aufgabe eine grafische Darstellung der Korrelationen in Form von Kovarianz-Ellipsen an."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"**Arbeitsanweisung:**
\n",
"Lesen Sie Daten aus der Datei `data.txt` ein und fitten Sie eine Gerade der Form $\\lambda(x;\\mathbf{a})=a_0+a_1 x$ an die Daten.\n",
"Beachten Sie dabei die Angabe der Unsicherheit der Messwerte in der Datei.\n",
"Stellen Sie die Kovarianz-Ellipse mithilfe von `kafe2` grafisch dar.\n",
"\n",
"**Hinweis:**
\n",
"Sie können zur Darstellung der Kovarianz-Ellipse die Klasse `kafe2.ContoursProfiler` nutzen. Diese benötigt als Parameter ein Objekt der Klasse `XYFit` von `kafe2`.\n",
"`ContoursProfiler`-Objekte besitzen die Methode `plot_profiles_contours_matrix()`, mit der Sie das Ergebnis grafisch darstellen können."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"from kafe2 import XYContainer, XYFit, Plot,ContoursProfiler"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Definition des einfachen linearen Modells\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Einlesen der Daten\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Durchführung des Fits\n",
"\n",
"\n",
"# Darstellen des Ergebnisses\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"In der Vorlesung wurde Ihnen auch direkt verraten, wie Sie diese Korrelation vermeiden können: Sie verschieben die $x$-Werte um ihren (gewichteten) Mittelwert: $\\epsilon(x;\\mathbf{s})=s_0+s_1 (x-\\overline{x})$.\n",
"\n",
"**Arbeitsanweisung:**
\n",
"Führen Sie obigen Geradenfit noch einmal durch, verwenden Sie jedoch $\\epsilon(x;\\mathbf{s})=s_0+s_1 (x-\\overline{x})$ als lineares Modell.\n",
"Betrachten Sie erneut die Kovarianz-Ellipse der freien Fitparameter.\n",
"Welche Korrelation der Parameter $s_0$ und $s_1$ beobachten Sie und warum?\n",
"\n",
"**Hinweis:**
\n",
"Argumentieren Sie z. B. mit der oben eingeführten Analogie mit dem Stab in der Hand."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Definition des neuen linearen Modells\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Durchführung des Fits\n",
"\n",
"\n",
"# Darstellen des Ergebnisses\n"
]
}
],
"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.12.3"
},
"orig_nbformat": 4
},
"nbformat": 4,
"nbformat_minor": 2
}