{
"cells": [
{
"cell_type": "markdown",
"id": "3c1607f6",
"metadata": {},
"source": [
"## Fehlerfortpflanzung"
]
},
{
"cell_type": "markdown",
"id": "d659c985",
"metadata": {},
"source": [
"*Notebook erstellt am 04.09.2022 von C. Rockstuhl, überarbeitet von Y. Augenstein*"
]
},
{
"cell_type": "markdown",
"id": "ca9a2a12",
"metadata": {},
"source": [
"### Allgemeine Betrachtungen zur Berechnung der Standardabweichung"
]
},
{
"cell_type": "markdown",
"id": "6057e8f2",
"metadata": {},
"source": [
"In diesem Notebook werden eine einfache Fehlerrechnung durchführen und werden vor allem sehen, dass zur korrekten Berechnung der Standardabweichung es wichtig ist, die Unsicherheit in der Streckenmesseung und der Zeitmessung explizt zu berücksichtigen. Als Daten verwenden wir Messungen von Ort und Zeit, die in einer Datei abgelegt sind."
]
},
{
"cell_type": "markdown",
"id": "0eaf645e",
"metadata": {},
"source": [
"Als erstes lesen wir die Daten ein. In dieser Datei `Geschwindigkeit.csv` gibt es zwei Spalten. Eine mit der entsprechenden Ortsmessung und eine mit der entsprechenden Zeitmessung. Die Geschwindigkeit ist dann einfach definiert als das Verhältniss von Ort und Zeit \n",
"$$ v(x,t)=\\frac{x}{t} .$$ \n",
"Beachten Sie bitte, eine solche Messung bzw. die Zuordnung einer solchen Geschwindigkeit macht nur dann Sinn, wenn wir davon ausgehen, dass es sich um eine gleichförmige, also eine konstante, Geschwindigekit handelt."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "e6a9323d",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" Zeit Ort\n",
"0 1.00280 0.88743\n",
"1 1.08520 1.07940\n",
"2 1.03320 1.18190\n",
"3 0.92458 0.67745\n",
"4 0.86262 1.37430\n"
]
}
],
"source": [
"import pandas as pd # Das Einlesen der Daten erfolgt wieder vergleichbar zu dem Vorgehen bei \n",
" # der Betrachtung der Mittelwerte und der Standardabweichung.\n",
"import matplotlib.pyplot as plt\n",
"\n",
"df = pd.read_csv(\"Geschwindigkeit.csv\", sep=\",\")\n",
"print(df.head())\n",
"\n",
"zeit = df['Zeit']\n",
"ort = df['Ort']\n",
"\n",
"geschwindigkeit = ort / zeit"
]
},
{
"cell_type": "markdown",
"id": "f0013321",
"metadata": {},
"source": [
"Ohne diese Daten hier jetzt extra visualisieren zu wollen, rechnen wir zunächst den Mittelwert und die Standardabweichung jeder einzelnen Größe aus. Wir berechnen auch die Geschwindikgkeit aus jedem der einzelnen Wertepaare und können diesen Mittelwert und Standardabweichung in einem ersten (falschen) Ansatz berechnen. "
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "c049afc9",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Das abschliessende Ergebniss unserer Ortsmessung beträgt (0.999 ± 0.202) m\n",
"Das abschliessende Ergebniss unserer Zeitmessung beträgt (1.0 ± 0.099) s\n"
]
}
],
"source": [
"import numpy as np\n",
"\n",
"sigma_x = np.std(ort, ddof = 1)\n",
"mean_x = np.mean(ort)\n",
"sigma_t = np.std(zeit, ddof = 1)\n",
"mean_t = np.mean(zeit)\n",
"print(f\"Das abschliessende Ergebniss unserer Ortsmessung beträgt ({round(mean_x, 3)} \\u00B1 {round(sigma_x, 3)}) m\")\n",
"print(f\"Das abschliessende Ergebniss unserer Zeitmessung beträgt ({round(mean_t, 3)} \\u00B1 {round(sigma_t, 3)}) s\")"
]
},
{
"cell_type": "markdown",
"id": "ca7f7621",
"metadata": {},
"source": [
"Wir wollen jetzt die Standardabweichung korrekt ausrechnen. In der Vorlesung habe wir diese berechnet mittels Fehlerfortplflanzung als\n",
"$$\n",
"\\sigma_v=\\sqrt{\\left(\\frac{\\partial v(x,t)}{\\partial x}\\right)^2\\sigma_x^2+\\left(\\frac{\\partial v(x,t)}{\\partial t}\\right)^2\\sigma_t^2}\n",
"$$\n",
"Im einfachen Fall können wir die partiellen Ableitungen natürlich direkt ausrechnen und wir erhalten\n",
"$$\n",
"\\sigma_v=\\sqrt{\\frac{1}{t^2}\\sigma_x^2+\\frac{x^2}{t^4}\\sigma_t^2}\n",
"$$.\n",
"\n",
"Zur Berechnung der Standardabweichung können wir natürlich für diese einfache Gleichung die analytische Lösung der Ableitung benutzen und diese evaluieren."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "db9449ad",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Unsere gemessene Geschwindigkeit beträgt (0.999 ± 0.225) m/s\n"
]
}
],
"source": [
"mean_v = np.mean(ort) / np.mean(zeit)\n",
"sigma_v = np.sqrt((1 / mean_t * sigma_x) ** 2 + (mean_x / mean_t**2 * sigma_t) ** 2)\n",
"print(f\"Unsere gemessene Geschwindigkeit beträgt ({mean_v:.3f} \\u00B1 {sigma_v:.3f}) m/s\")"
]
},
{
"cell_type": "markdown",
"id": "fee03a41",
"metadata": {},
"source": [
"Wenn wir die Standardabweichungen der Geschwindigkeit einfach aus den einzelnen Wertepaare berechnen, kommen wir nicht auf das richtige Ergebnis. Der Unterschied ist in unserem Fall nicht ganz so dramatisch, aber Sie werden in Ihrem Studium sicherlich Fälle beobachten, in denen der Unterschied signifikant werden wird."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "77459839",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Unsere gemessene Geschwindigkeit mit der falsch berechneten Standardabweichung beträgt (1.009 ± 0.229) m/s\n"
]
}
],
"source": [
"sigma_v_falsch = np.std(geschwindigkeit, ddof = 1)\n",
"mean_v_falsch = np.mean(geschwindigkeit)\n",
"print(f\"Unsere gemessene Geschwindigkeit mit der falsch berechneten Standardabweichung beträgt ({mean_v_falsch:.3f} \\u00B1 {sigma_v_falsch:.3f}) m/s\")"
]
},
{
"cell_type": "markdown",
"id": "c6cc545a",
"metadata": {},
"source": [
"### Symbolische Berechnung der Ableitungen"
]
},
{
"cell_type": "markdown",
"id": "5a33cd8a",
"metadata": {},
"source": [
"Technisch haben wir das Ziel dieses Notebooks erreicht. Praktisch möchten wir hier aber noch einen Schritt weitergehen und jegliche Rechnung den Computer überlassen. Insbesondere die Berechnung der pariellen Ableitungen kann unter Umständen so komplex sein, dass wir dies nicht mehr ohne größere Probleme analytisch auf dem Papier durchführen können. Stattdessen möchten Sie einen Computer verwenden, der diese Aufgabe für Sie übernimmt. Diese Rechnung soll in diesem Teil des Notebooks durchgeführt werden. Hierfür verwenden wir die Bibliothek zum Symbolischen Rechnen. "
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "3dfe79c9",
"metadata": {},
"outputs": [],
"source": [
"import sympy\n",
"from sympy.abc import x, t"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "4db4c7b9",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Die partielle Ableitung der Geschwindigkeit nach der Zeit lautet -x/t**2\n",
"Die partielle Ableitung der Geschwindigkeit nach dem Ort lautet 1/t\n"
]
}
],
"source": [
"v = x / t\n",
"Ableitung_t = sympy.diff(v, t)\n",
"Ableitung_x = sympy.diff(v, x)\n",
"print(f\"Die partielle Ableitung der Geschwindigkeit nach der Zeit lautet {Ableitung_t}\")\n",
"print(f\"Die partielle Ableitung der Geschwindigkeit nach dem Ort lautet {Ableitung_x}\")"
]
},
{
"cell_type": "markdown",
"id": "dc865219",
"metadata": {},
"source": [
"Die Ableitungen lassen sich auch entsprechend evaluieren bei konkreten Funktionswerten. Zur Berechnung der Fehler sei gesagt, dass diese partiellen Ableitungen beim Mittelwert evaluiert werden. "
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "2f38af15",
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle 1.0$"
],
"text/plain": [
"1.00000000000000"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"round(Ableitung_x.evalf(subs={x: mean_x, t: mean_t}), 3)"
]
},
{
"cell_type": "markdown",
"id": "f8955caa",
"metadata": {},
"source": [
"Wir können dann die Standardabweichung mit der oben angegebenen Formel\n",
"$$\n",
"\\sigma_v=\\sqrt{\\left(\\frac{\\partial v(x,t)}{\\partial x}\\right)^2\\sigma_x^2+\\left(\\frac{\\partial v(x,t)}{\\partial t}\\right)^2\\sigma_t^2}\n",
"$$\n",
"ganz automatisiert berechnen."
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "7157f147",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Unsere gemessene Geschwindigkeit beträgt (0.999 ± 0.225) m/s\n"
]
}
],
"source": [
"sigma_v2 = sympy.sqrt( \n",
" (Ableitung_x.evalf(subs={x: mean_x, t: mean_t}) * sigma_x) ** 2\n",
" + (Ableitung_t.evalf(subs={x: mean_x, t: mean_t}) * sigma_t) ** 2\n",
")\n",
"print(f\"Unsere gemessene Geschwindigkeit beträgt ({mean_v:.3f} \\u00B1 {sigma_v2:.3f}) m/s\")\n",
" # Beachten Sie bitte als kleine Abweichung, dass wir hier den Wurzelbefehl in\n",
" # SciPy verwenden müssen und nicht den aus NumPy."
]
},
{
"cell_type": "markdown",
"id": "6597c859",
"metadata": {},
"source": [
"Als Letztes sei noch gesagt, dass wenn eine Funktion das Produkt oder der Quotient zweier physikalischer Größen ist, dann ist der relative Fehler dieser Größe gerade die Wurzel der Summe der relativen Fehler der beiden physikalischen Größen. In unserem Fall wäre das also \n",
"$$\n",
"\\frac{\\sigma_v}{\\bar{v}}=\\sqrt{\\left(\\frac{\\sigma_x}{\\bar{x}}\\right)^2+\\left(\\frac{\\sigma_t}{\\bar{t}}\\right)^2}\n",
"$$"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "2f2a41ce",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Der direkt berechnete relative Fehler (einmal hier mit allen Nachkommastellen) 0.22524160087399744\n",
"Der indirelt berechnete relative Fehler (einmal hier mit allen Nachkommastellen) 0.22524160087399742\n"
]
}
],
"source": [
"relativer_fehler_1 = sigma_v / mean_v\n",
"relativer_fehler_2 = np.sqrt((sigma_x / mean_x) ** 2 + (sigma_t / mean_t) ** 2)\n",
"print(f\"Der direkt berechnete relative Fehler (einmal hier mit allen Nachkommastellen) {relativer_fehler_1}\")\n",
"print(f\"Der indirelt berechnete relative Fehler (einmal hier mit allen Nachkommastellen) {relativer_fehler_2}\")"
]
},
{
"cell_type": "markdown",
"id": "1219ea3e",
"metadata": {},
"source": [
"Beachten Sie hier eine kleine Abweichung in der 16'ten Nachkommastelle. Dieser Fehler ist gerade remineszent zu unserer numerischen Diskretisierung der Funktionsevaluation, die in double-precission erfolgt. Hier werden gerade 16 Nachkommastellen mit berücksichtigt."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.9.12"
},
"vscode": {
"interpreter": {
"hash": "77c156d20ad9e0a33269d50c8fafe7044ce4815250dfaf90496dfc42f56ab107"
}
}
},
"nbformat": 4,
"nbformat_minor": 5
}