{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Jupyter Notebook\n", "Wie bereits erkennbar besteht ein Jupyternotebook aus Zellen. In der Regel kann eine Zelle entweder einen beschreibenenden Text beihnalten welcher mittels Markdown Syntax editiert wird oder Code in einer dezidierten Programmiersprache, wie Python, beinhaltet.\n", "\n", "Jupyter Notebooks sind grundsätzlich Web-Applikationen welche als Dokument geteilt und versendet werden können. In der Regel beinhaltet ein Notebook Code-Zeilen, Gleichungen, Visualisierungen und Texte. Besonder eignen sich Jupyter Notebooks dazu Datenanalysenschritte aufzuzeigen, diese zu beschreiben und entpsrechende Visualisierungen einzubetten. Dadurch haben sich Jupyter Notebooks besonder im Data Science Bereich als unerlässliches Werkzeug etableirt.\n", "\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dies ist eine Markdown Zelle und erlaubt das formattiern von Text in der entsprechenden Syntax\n", "\n", "'Hello Jupyter!'\n", "\n", "**'Hello Jupyter!'**\n", "\n", "_'Hello Jupyter!'_" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Durch klicken auf das Pfeil Symbol auf der linken Seite dieser Zelle, wird der Code in dieser Zell ausgeführt\n", "print('Hello Jupyter!')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 1. Python Pakete laden\n", "---\n", "Wie in einem Python Script werden entsprechende Module geladen. Wichtig hier ist das man entsprechende Zellen nicht unbedingt in Reihenfolge ausführen muss.\n", "\n", "Pandas\n", "* Ist eine Software for Daten Manipulation und Analyse\n", "* Wird oft als `pd` geladen um entpsrechend Code-Text zu kürzen.\n", "\n", "Plotly-express\n", "* Ist ein Software Paket welche es erlaubt komplexe Visualisierungen zu erstellen" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import plotly.express as px\n", "import sklearn" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 2. Datensatz laden\n", "---\n", "Der Datensatz ist als .csv Datei gespeichert. Pandas erlaubt es diese Datei direkt in ein Dataframe zu lesen. Dieses Dataframe kann dann einfach manipuliert, inspiziert und analysiert werden. \n", "\n", "Der Variablen Namen des Dataframes wird oft als `df` abgekürzt." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "try:\n", " df = pd.read_csv('heart.csv')\n", "except:\n", " df = pd.read_csv('/kaggle/input/heart-attack-analysis-prediction-dataset/heart.csv')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Der nun im dataframe \"df\" gespeicherte Datensatz ist ein Trainings und Benchmark Datensatz welcher auf Kaggle.com veröffentlicht wurde. Kaggle ist eine Organisation von Data Science Wettbewerben. Dabei werden mehrere Tausend Datenstätze bereitgestellt mit welche Datengestützte Modelle für Prediktive Analysen trainiert werden können. Dabei können entsprechende Modelle unter der Community verglichen werden was den Wettbewerbsaspekt der Platform bildet.\n", "\n", "[https://www.kaggle.com/rashikrahmanpritom/heart-attack-analysis-prediction-dataset](https://www.kaggle.com/rashikrahmanpritom/heart-attack-analysis-prediction-dataset)\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "## Kontrollaufgabe 1\n", "Die heart.csv Datei wurde mittel pandas ausgelesen und als Dataframe abgespeicher. Umgekehrt kann man natürlich auch wieder ein Dataframe als Datei speichern.\n", "\n", "* Schreiben Sie unten in die entsprechende code Zeile die Funktion um das Dataframe `df` als excel Datei zu speichern, dabei soll der Dateiname `excel.xlsx` sein. Ist die Datei exportiert können Sie diese anschliessen mit Excel öffnen und inspizieren.\n", "\n", "**Hinweis**: Unter [https://pandas.pydata.org/docs/reference/frame.html](https://pandas.pydata.org/docs/reference/frame.html) Finden Sie alle Funktionen um ein Dataframe manipulieren zu können" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Hier den Code schreiben\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "---\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 3. Datensatz inspizieren\n", "---\n", "Nach dem der Datensatz geladen ist wird dieser auf dessen Inhalt und Vollständigkeit überprüft. Dabei spielen die folgenden Aspekte die wichtigsten Punkte wenn es um das Überprüfen der Daten geht:\n", "* Lücken einer Serie (Bsp. fehlende Daten in einer Kolonne in einem Dataframe)\n", "* Typ der Daten (Bsp. Integer, Float, Strin, etc.)\n", "* Duplikate (Bsp. Kolonne doppelt erfasst)\n", "* Integrität (Bsp.\"na\" anstatt 0)\n", "\n", "### 3.1 Überblick \n", "\n", "Um einen Überblick zu erhalten werden die obersten Datenreihen im Dataframe inspiziert. Hierzu wird der Befehl `head()` an das Dataframe angefügt. Die Zahl in der Klammer im `head()` Befehlt beschreibt die anzahl der obersten angezeigten Reihen (Hier noch eine Erinnerung das Python anfängt bei 0 zu zählen)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.head(5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Was mann bereits erkennt ist das das Dataframe aus 14 Kolonnen und einer Vielzahl an Zeilen besteht. Die erste Kolonne welche keinen Namen hat (also diese vor `age`) is der Index des Dataframes, also eine Nummerierung jeder Zeile. Ebenfalls sieht mann hier das jede Zeile einen Patienten beschreibt und jeder Kolonnen-Parameter einen Physiologischen Wert des Patienten.\n", "\n", "Parameter:\n", "* **Alter** -> age : Age of the patient\n", "* **Geschlecht** -> sex : Sex of the patient\n", "* **Angina** -> exang: exercise induced angina (1 = yes; 0 = no)\n", "* **Anzahl Hauptvessel** -> ca: number of major vessels (0-3)\n", "* **Brustschmerzen** -> cp : (1: typical angina, 2: atypical angina, 3: non-anginal pain, 4: asymptomatic)\n", "* **Ruheblutdruck** -> trtbps : resting blood pressure (in mm Hg)\n", "* **Cholesterol** -> chol : cholestoral in mg/dl fetched via BMI sensor\n", "* **Nüchternblutzucker** -> fbs : (fasting blood sugar > 120 mg/dl) (1 = true; 0 = false)\n", "* **Elektrokardiographische Ergebnisse im Ruhezustand** -> rest_ecg : resting electrocardiographic results (0: normal, 1: having ST-T wave abnormality, 2: left ventricular hypertrophy)\n", "* **erreichte maximale Herzfrequenz** -> thalach : maximum heart rate achieved\n", "* **Ausgabe** -> Output : (0 = less chance of heart attack 1= more chance of heart attack)\n", "\n", "\n", "Hier noch einige wichtige Punkte zu den Parametern:\n", "* Was mann in dieser Beschreibung ebenfalls sieht ist das einige der Parameter **codiert** sind, heisst anstatt einen Wert, wie beim Alter, ist nur eine Zahl angegeben, wie beispielsweise beim Parameter \"Angina\" wo einen 1 Ja und eine 0 Nein bedeutet. Grundsätzlich möchte man Kategorische Variablen (Ja/Nein, Gut/Schlecht, etc.) als Zahlenwerte abbilden weshalb diese codiert werden!\n", "* Der Parameter **Ausgabe** ist ein besonders wichtiger Teil dieses Datensets, denn dieser beschreibt die Wahrscheinlichkeit auf eine Herzattacke des Patienten. Dieses Datenset hat also eine Reihen an Physiologischen Paramters und die zugehörige Wahrscheinlichkeit auf eine Herzattacke. Mit statistischen Methoden kann man ein Model entwickeln welche es erlaubt genau diesen **Ausgabe** Parameter aufgrund der anderen Werte vorasuzusagen!\n", "\n", "### 3.2 Werte anzeigen\n", "Bezüglich der Inspektion des Dataframes kann man sich auch bestimmte Zeilen anschauen. Hierzu wir der gesuchte Index mittels des `.loc[Zeile, Kolonne]` Befehls and das Dataframe angefügt. Hierzu noch einige Beispiele:\n", "* `df.iloc[1,2]` zeigt den Wert der zweiten Zeile und dritten Kolonne (Python zählt bei 0!)\n", "* `df.ilog[0:4,2]` zeigt Werte von 5 Zeilen und der dritten Kolonne\n", "* `df.iloc[1,:]` zeigt alle Werte der zweiten Zeile and (\":\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.iloc[99,0:3]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`df.iloc[99,0:3]` zeigt also Werte der Parameter `age`, `sex` und `cp` des Patienten mit dem Index 99" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Kontrollaufgabe 2\n", "Beschreiben Sie welche Werte in der nächste Zelle angzeigt werden (Beschreibung in der darunterliegenden Markdown Zelle)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.iloc[97:99,0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Beschreibung:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.loc[2,:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Beschreibung:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 3.3 Dataframe Info\n", "\n", "Nun gibt es weitere Befehle welche den Inhalt eines Dataframes beschreiben. So gibt der `.info()` Befehlt einen überblick über das Dataframe. Besonders wichtig hier ist der Dtype welcher beschreibt im welchem Datentyp die jeweiligen Kolonnen erfasst sind." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.info()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 3.4 Leere Zellen\n", "\n", "Ebenfalls wichtig ist es zu schauen ob eventuell leere Zellen im Dataframe vorhanden sind. Also Zellen in welche keine Werte geschrieben sind (Die Zahl null wäre ein Wert). Um dies schnell zu überprüfen wird der Befehl `.isnull()` angewendet, dieser Zeigt dan im ganzen Dataframe eine leere Zelle vorhanden ist (False = Wert ist vorhanden, True = hier fehlt ein Wert und Zelle ist leer)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.isnull()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Natürlich möchte mann nun icht das ganze Dataframe nach `True` durchschen und somit wendet man einen weiteren Befehl an. Mit dem `.sum()` Befehl können die Anzahl an `True` gezählt werden und dieser kann einfach an den vorherigen Befehl angehängt werden" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.isnull().sum()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Somit hat es keine leeren Zellen im Dataframe\n", "\n", "### 3.5 Schnelle statistische Auswertung\n", "\n", "Der Befehl `.describe()` generiert eine einfache statistische Auwertung über jede Kolonne. Dies erlaubt es eine Überblick über die Integrität der Daten zu erhalten." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.describe()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Hier sieht man Beispielsweise das das Durchschnittsalter (mean in der Kolonne `age`) 54 Jahre ist oder das der jüngste Patien 29 Jahre und er älteste 77 Jahre alt ist.\n", "\n", "---\n", "---\n", "## Kontrollaufgabe 3\n", "Mann kann eine Kolonne eines Dataframes direkt erfassen in dem man folgende Struktur nutzt `df[\"Kolonnennamen]` und auch gleich einen entsprechenden Befehl auf diese Kolonne ausführen. Beispielsweise kann man mit `df[\"age\"].sum()` das Alter aller Patienten summieren.\n", "\n", "* Schreiben Sie den Code um den Durchschnitt der Kolonne `chol` zu berechnen.\n", "* Schreiben Sie den Code um das maximale Alter aus der Kolonne `age` zu berechnen\n", "\n", "**Hinweis**: Überlegen Sie sich die entsprechenden Englishen Begriffe und such nach der entsprechenden Funktion unter [https://pandas.pydata.org/docs/reference/frame.html](https://pandas.pydata.org/docs/reference/frame.html)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Hier den Code schreiben\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "### 3.6 Dublikate\n", "Nun möchte man noch überprüfen obe enventuell ein Patient doppel, also als Dublikat erfasst wurde. Ähnlich zum `.isnull()` Befehlt wird hierzu der `.duplicated()` und `.sum()` Befehl in Kombination angewendet" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.duplicated().sum()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Somit hat es dein Dublikat im Datensatz vorhanden.\n", "\n", "Nun möchte man dieses natürlich löschen um die entsprechende Zeile zu finden wird der `.duplicated()` Befehl als index verwendet." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.duplicated()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In einer Zeile ist also der Wert \"True\" vorhanden, um die bestimmte Zeile zu finden wird dieser Index mit dem Befehl `.loc[Index]` kombiniert." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.loc[df.duplicated()]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Somit ist die Zeile mit dem Index 164 ein Duplikat. Wobei die Zeile mit dem Index 163 sehr wahrscheinlich der erste Original eintrag ist" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.iloc[163:165,:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Nun könnnen wir also die Zeile mit dem Index 164 aus dem Dataframe entfernen. Hierzu wird einfach der Befehl `.drob_duplicates()` angewendet." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df= df.drop_duplicates()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Damit im index keine Lücke entsteht (162,163,[ ], 165,166) wird der Index zurückgesetzt." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df= df.reset_index(drop=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Jetzt sollte alles passen und kein Duplikat vorhanden sein." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.loc[163:164]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 4 Daten Visualisieren\n", "---\n", "Matplotlib, Seaborn, Plotly Express oder ggplot, um nur einizge zu nennen, sind Visalisierungs-Pakete für Python. Jedes dieser Werkzeuge hat Vor-und Nachteile im Bezug die Syntax, Zielplot und Dateninput. Einige sind ausgelegt auf grosse Datenmene andere auf einfaches Userinterface oder wurden von anderen Programmiersprachen zu Python portiert. Somit ist es of der Fall das man je nach Zielplot zwischen diese Paketen wechselt oder man sich auf eines fixiert aufgrund des Interfaces oder anderen Gründen. \n", "\n", "\n", "\n", "### 4.1 Pandas plot\n", "Pandas selber beinhaltet einige Visualisierungfunktionen welche als Methoden integriert sind.\n", "\n", "Mit dem `.plot()` Befehlt wird eine Visualisierung des ganzen Dataframes erstellt." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import matplotlib\n", "df.plot()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.plot.scatter(x=\"age\", y=\"chol\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Die Punkte zeigen somit die Überlappund des Alter eines Patienten und dem zugehörigen Cholesterol Wert.\n", "\n", "Möchte man nur einen betimmten Parameter plotten wird der Kolonnenname indexiert `df[\"Kolonnenamen\"]`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df[\"age\"].plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Die obige Grafik ist nun sehr minimal und es fehlen beschreibende Informationen. Weitere Paremeter können nun in den Klammern des `.plot()` Befehls erfasst werden.\n", "\n", "Generell sind alle Parameter unter folgendem Link ersichtlich: **[https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.plot.html](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.plot.html)**\n", "\n", "Hier sind einige Beispiele dazu:\n", "* Title der Grafik -> title=\"title\"\n", "* Grafik Grösse -> figsize=(x,y)\n", "* x- und y-Achsentitel -> xlabel=\"xlabel\", ylabel=\"xlabel\"\n", "* Rotation der X-Achsen Indexierung -> rot=10\n", "* Legende -> legende=True" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df[\"age\"].plot(figsize=(10, 5),title=\"Alter der erfassten Patieneten\",xlabel=\"Patienten Index\", ylabel=\"Alter\", rot=45, legend=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Jetzt ist die Grafik sinnvoll formatiert, jedoch mach es eigentlich gar keinen Sinn das Alter der Patienten auf diese Art zu Visualisieren, da man gar keine Informationen aus dieser Grafik extrahieren kann.\n", "\n", "### 4.2 Visualisierung auswählen\n", "\n", "Je nach Datentyp, Quelle, Zusammensetzung und Ziel sollte eine bestimmte Visualisierung ausgewählt werden. Generell orientirt man sich daran ob man an einer Verteilung, einem Vergleich, ans Zusammenhänge oder an einer Zusammensetzung interessiert ist und eine entsprechende representierbare Grafik erstellen möchte.\n", "\n", "\n", "\n", "Im Bezug auf den Parameter `age` wäre man zum Beispiel an der Verteilung interessiert, also wieviele Patienten eines bestimmten Alter es gibt. Hierzu eignet ein Histogram Plot. Diese Art von Plot kann ebenfalls mit Pandas generiert werde mittel des `.hist()` Befehls." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df[\"age\"].hist()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Auf der y-Achse ist die Anzahl Patienten in einer bestimmten Alterskategorie aufgeführt. Auf der x-Achse sind also gleichmässige Abschnitte welche eine Kategorie bilden. So sind zum Beispiel ca 2 Patienten in Alterskategorie von ca 20-34 Jahre alt. In der Kategorie 56-63 Jahre sindca run 62 Patienten. Jetzt kann man die Anzahl an Alterskategorien noch erhöhen in dem den Parameter `bins=50` einfügt." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df[\"age\"].hist(bins=100, figsize=(10, 8), grid=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Diese Grafik ist schon einiges Übersichtlicher und gibt eine klare Übersich über die Altersverteilung der Patienten.\n", "\n", "---\n", "---\n", "## Kontrollaufgabe 4\n", "Schreiben Sie den Code um den folgenden plot zu generiern \n", "\n", "" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Hier den Code schreiben\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 4.3 Statistische Visualisierungen\n", "Besonder wichtig sind Visualisierungen welche Statistische Auswertungen bildlich unterstützen. Wie bereits weiter oben beschrieben kann mit dem `.describe()` Befehl eine statistische auswertung über die Kolonnen erstellt werden." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df[\"age\"].describe()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Diese Statistischen Parameter kann auf einfache weise mit einem Boxplot representieren. Den entsprechenden Befehl das is `.boxplot()` wobei noch eine bestimme Kolonne als Parameter bestimmt werden muss." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.boxplot(column=\"age\", figsize=(5, 4),grid=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Diese ist somit eine visuell representierung von statistischen Basisparametern. Boxplots können mit einem weiteren Dataframe parameter erweitert werden. So ist man zum Beispiel interssiert and den Altersunterschieden zwischen Mann und Frau." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.boxplot(column=\"age\", by=\"sex\", figsize=(8, 5),grid=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 4.4 Abhängigkeiten zwischen Parametern erkennen\n", "Sogennante Korrelationsplots sind oft einen statistische Visulasierung welche verwendet wird um Zusammenhänge zwischen verschiedenen Parametern zu finden. \n", "\n", "Eine einfache Methode hierzu ist es den Pearson Koeffizient zwischen zwei Parametern zu berechnen So wird zum Beispel der Parameter `age` und `chol` als das Alter und der Cholesterolspiegel gegenübergestellt. Dies zuerst mit einem Scatterplot visualisiert werden" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.plot.scatter(x=\"age\", y=\"chol\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Steigt nun der Cholesterolspiege mit steigendem Alter ergibt des einen positive Pearson Koeffizient, wobei eine absolute Abhängigkeit zwischen diesen Wert bei 1 liegen würde.\n", "\n", "In der folgenden Übersicht ist aufgezeigt wie sich der Pearson Koeffizien verhält:\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Damit man nicht jedes Parameter Paar einzeln berechnen muss erstellt man eine Korrelationsmatrix wobei dann jeder Parameter gegenüber jedem Parameter verrechnet wird. Diese Korrelationsmatrix wird einfach mit dem Befehl `.corr()` erstellt." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.corr()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Nun kann man diese Matrix nach hohen (oder tiefen Werten) durchsuchen um Paramterpaare zu finden welche stark voneinen Abhängig sind. Dabei wäre man besonders an der `output` Zeile interessiert da diese Ja die Wahrscheinlichkeit auf einen Herzinfarkt aufzeigen würde um somit welcher andere Parameter den grössten Einfluss darauf hat.\n", "\n", "Wichtig ist das beim Korrelationsplot die diagonalen Werte ignoriert werden können das diese ja den Pearson Koeffizient des Parameters mit sich selber, also dem Wert 1, aufzeigt.\n", "\n", "Da der Mensch nicht gut is im scrennen von Zahlen können wir den Korrelationsplot mit eine Farbskala erweitern. Hierzu wir die Visualisierungsbibilothek plotly-express verwenden und der dazugehörige Befehtl `.imshow()`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "px.imshow(df.corr())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 5 Machine Learning (\"AI\") in a Nutshell\n", "---\n", "Machine Learning und AI ist ein aktuelles Thema und wird in verschiedenen technischen Bereichen eingesetzt, so auch im Gesundheitsbereich. Oft wird dabeim diffusen Begriffen wie \"deeplearning\", \"ai\", \"general artifical intelligence\" oder \"machine learning\" verwendet. Dabei wird oft menschen ähnliche Intelligenz suggeriert wo gar keine ist!\n", "\n", "Dieses Kapitel soll auf einfache weise das erstellen einer \"AI\" aufzeigen. Dabei spielen heute besonders grossen Datenmengen eine Rolle da diese es erlauben Iterative statistische Methoden zu \"trainieren\" ohne das man manuell Parameter einstellen muss. Um dies zu erreichen geht man immer nach dem gleichen Prinzip vor welches in der folgenden Grafik aufgzeigt ist:\n", "\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Pyhton Paket laden\n", "Hierzu verwenden wir die sklearn Bibliothek, eine Software für das erstellen von machine learning modellen mit Python" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import sklearn\n", "from sklearn.preprocessing import StandardScaler\n", "from sklearn.model_selection import train_test_split\n", "from sklearn.linear_model import LogisticRegression\n", "from sklearn.metrics import confusion_matrix\n", "from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 5.1 Get Data | Daten laden\n", "Hierzu verwenden wir wieder das \"heart.csv\" Datenset und laden dies nochmals neu als Dataframe\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "try:\n", " df = pd.read_csv('heart.csv')\n", "except:\n", " df = pd.read_csv('/kaggle/input/heart-attack-analysis-prediction-dataset/heart.csv')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 5.2 Clean, Prepare & Manuplate Data | Bereinigung, Vorbereitung und Manipulation der Daten\n", "Der wichtigste Schritt bildet die Aufarbeitung und Vorbereitung des Datensatzes um diesen für das Trainingen des Models bereit zu haben.\n", "\n", "Hier nochmals eine kurze Übersicht über den Datensatz:\n", "* Parameternazahl = 14 \n", "* Anzahl Werte pro Kolonnen 303\n", "\n", "Dies können wir nochmals auch mit dem `.shape` Paramer überprüfen:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.shape" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Der erste Wert beschreibt hier die anzahl Zeilen (hier = 303) und die zweite Zahl die Anzahl Kolonnen (also 14 Parameter)\n", "\n", "Als nächste wird das Dataframe aufgetrennt in eine Eingangs und Ausgangsdaten set. Dabei bilden alles Physiologischen Parameter den Eingangsdatensatz und die Kolonne \"output\" unseren Ausgangsdatensatz. Somit möchten wir auf grund unseres Eingangs Parameter den Ausgangsparameter voraussagen.\n", "* Eingang -> Input Paramter (age, sex, cp, trtbps, chol, fbs, restecg, thalachh, exng, oldpeak, slp, caa, thall)\n", "* Ausgang -> Output Parameter (output)\n", "\n", "In der Regel werden zwei neue Dataframes gebilded, das Eingangsdatenframe **X** und das Ausgangsdataframe **Y**:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "X= df.iloc[:,:-1].values\n", "Y= df.iloc[:,-1].values" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Wir können nochmals die Zusammensetzung mit dem `.shape` Befehl überprüfen" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(X.shape)\n", "print(Y.shape)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Nun werden noch bestimmte Parameter skaliert, heisst die Werte bestimmter Kolonnen werden angpasst damit diese nicht überproportianal das zu trainierende Modell beinflussen.\n", "\n", "\n", "\n", "Dabei muss man oft nur bestimmter Parameter skalieren welch in diesem Fall die folgenden wären\n", "* `age`,`trtbps`,`chol`,`thalachh` und `oldpeak`\n", "\n", "Dies sind die Kolonnen Nr. 0 3 4 5 6 und 8 im Dataframe, also die folgenden Werte:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "X[0:4,[0,3,4,5,6,8]]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Für die Skalierung wird eine Funktion von sklearn verwendet" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "X[:,[0,3,4,5,6,8]]=sklearn.preprocessing.StandardScaler().fit_transform(X[:,[0,3,4,5,6,8]])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Die skalierten Werte sehen nun so aus:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "X[0:4,[0,3,4,5,6,8]]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Weiter müssen die beiden Dataframes X und Y nochmals aufgetrennt werden und war in ein Trainings und Test Datenset. Dabei werden die beiden Trainingsdatensets verwendet um das Model zu trainieren und die beiden Testdatensets umd das Model anschliessend zu überprüfen. Oft nimmt man run 60-70% der Daten für das Training und den Rest für das Testen." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Xtrain,Xtest,Ytrain,Ytest= sklearn.model_selection.train_test_split(X,Y,test_size=0.25,random_state=2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 5.3 Train Model | Das Model trainieren\n", "Sobald die Daten augearbeitet sind kann man das Model trainieren. Dabei werden nur die Trainingsdaten verwendet (hier Xtrain und Ytrain).\n", "\n", "Das Model welches trainiert wird eine logistisches Regressionsmodel. Dabei haben alle Eingangswerte (X1, X2, X3, Xn,...) einen zugehörigen Gweichtsparameter (W1, W2, W3, Wn). Diese Gewichtsparameter werden währen des Trainings automatisch optimiert damit Eingangsparameter welche einen grossen Einfluss auf den Ausgang des Models haben ein entpsrechend grosses Gewicht erhalten und umgekehrt.\n", "\n", "\n", "\n", "Das Training wird in der nächsten Zelle beinhaltet und die Gewichtsparameter werden über 1000 Iterationen angepasst." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lr=sklearn.linear_model.LogisticRegression(max_iter=1000).fit(Xtrain,Ytrain)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Die oben erwähnten Gewichte können nach dem Training inspieziert werden" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lr.coef_" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 5.4 Test Data | Test Daten\n", "Um nun das trainierte Modell auszuwerten werden die beiden Testdatensets angewendet. Als Output möchte man am Ende etwas über die \"Performace\" des trainierten Modelles erfahren. Also zum Beispiel dessen Prezision oder Richtigkeit\n", "\n", "\n", "\n", "Um das Modell zu evalueieren wird dabei eine Konfusions-Matrix generiert welche die Grundlage bildet für weitere statistische Aussagen." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sklearn.metrics.confusion_matrix(Ytest,lr.predict(Xtest))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Die werten in der Konfusionsmatrix können dann weiter berechnet werden umd einen score für die \"Richtigkeit\" (Accuracy), \"Prezision\" (Precision) und \"Wiederfindung\" (Recall)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print('Accuracy score: ','{:.3}'.format(sklearn.metrics.accuracy_score(Ytest, lr.predict(Xtest))*100), \"%\")\n", "print('Precision score: ','{:.3}'.format(sklearn.metrics.precision_score(Ytest,lr.predict(Xtest))*100), \"%\")\n", "print('Recall score: ','{:.3}'.format(sklearn.metrics.recall_score(Ytest,lr.predict(Xtest))*100), \"%\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 5.5 Anwendung des Modells\n", "Ist das Modell fertig optimiert kann mann es auf neue Daten anwenden. Als Beispiel wird ein ein neues Datenset eines Patienten generiert." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "newData=[[-1.50691664e-01, 6.81005225e-01, 1.00257707e+00, -9.27377842e-02, -5.10243757e-03, 1.00000000e+00, 0.00000000e+00, 1.73000000e+02,\n", " 0.00000000e+00, 0.00000000e+00, 2.00000000e+00, 3.00000000e+00, 2.00000000e+00]]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Das neue Datenset eines Patienten kann dann mit dem `.predict()` Befehlt ausgewertet werden." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"Heart attack risk level: \", lr.predict(newData)[0])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Der Ausgangswert ist nun 1 und er Patient hätte ein erhöhtes Herz Infarkt Risiko." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "" ] } ], "metadata": { "interpreter": { "hash": "40fa215dad0e994e7adf7fc4b2715ad13f1cc7259c6abf1f98740877a22b9116" }, "kernelspec": { "display_name": "Python 3.8.6 64-bit ('3.8.6': pyenv)", "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.8.12" }, "orig_nbformat": 4 }, "nbformat": 4, "nbformat_minor": 2 }