Einleitung

Auf den folgenden Seiten möchte ich zeigen, wie in R KI und ML Modelle erzeugt werden kann. Für mich ist KI und ML noch ein sehr unbekanntes Feld. Daher werden einige Erklärungen etwas holprig, ja womöglich sogar idiotisch sein. ;) Diese Seite ist, wie alle anderen von mir produzierten Seiten, generell für eigene Dokumentationszwecke gedacht. Ich möchte hier meinen Lernfortschritt festhalten. Es ist also auf Denglish: Work in Progress. Die Seite und auch die Codes werden sich also ständig verändern. Hoffentlich zu besseren, effizienteren Darstellungen

Aktuell habe ich einige “Projekte”, an denen ich arbeite. Die Seiten sind noch sehr chaotisch. Das wird sich hoffentlich im Laufe der Zeit ändern. Die Links dazu findet man hier: https://rpubs.com/Exilkaerntner1970 Falls jemand drüberstolpert und meine Ausführungen hilfreich findet, freu ich mich. Falls jemand Verbesserungsvorschläge hat, steht es ihm frei, hier einen Kommentar zu hinterlassen.

Um mir R beizubringen, benutze ich unter Anderen Videos der Platform Youtube.com. Hier muss man naturgemäß viele “Leerläufe” durchlaufen. Wenn ich ein Video aber hilfreich finde, wird es mit Link gepostet.

Weitere sehr hilfreiche Links -wird ständig erweitert- sind:

Es gibt auch eine Unmenge an Büchern zum Thema R4Finance. Anbei einige Links zu Online- Büchern, die ich für sehr hilfreich gefunden habe:

https://bradleyboehmke.github.io/HOML/

Was ist eigentlich “künstliche” Intelligenz und maschinelles Lernen ?

Ich hab es mir leicht gemacht und hab dazu eine KI gefragt. ChatGPT gab folgende Definition: Künstliche Intelligenz (KI) bezieht sich auf die Entwicklung von Algorithmen und Computersystemen, die in der Lage sind, Aufgaben auszuführen, die normalerweise menschliche Intelligenz erfordern. Das Hauptziel der künstlichen Intelligenz besteht darin, Maschinen so zu gestalten, dass sie lernen, Probleme lösen und Entscheidungen treffen können, ähnlich wie es Menschen tun.

Es gibt zwei Hauptarten von künstlicher Intelligenz:

  1. Schwache KI (Weak AI): Diese Form der KI ist auf die Ausführung spezifischer Aufgaben beschränkt. Sie ist darauf ausgelegt, eine bestimmte Aufgabe zu erfüllen, ohne menschenähnliches Bewusstsein oder Verständnis zu haben. Beispiele für schwache KI sind Spracherkennungssysteme, Bilderkennung oder Empfehlungsalgorithmen.

  2. Starke KI (Strong AI): Im Gegensatz zur schwachen KI soll die starke KI ein umfassendes Verständnis für verschiedene Aufgaben entwickeln und in der Lage sein, eigenständiges Lernen und Problemlösungsfähigkeiten zu demonstrieren. Starke KI ist bisher theoretisch und es gibt noch keine Systeme, die diese Ebene der Intelligenz erreicht haben.

Es gibt verschiedene Techniken, die in der künstlichen Intelligenz verwendet werden, darunter maschinelles Lernen, neuronale Netzwerke, natürliche Sprachverarbeitung und Expertensysteme. KI findet Anwendungen in verschiedenen Bereichen wie Medizin, Finanzen, Automobilindustrie, Robotik, Spieleentwicklung und vielem mehr. Es ist jedoch wichtig, ethische Überlegungen und die Auswirkungen auf die Gesellschaft im Auge zu behalten, wenn KI-Technologien entwickelt und eingesetzt werden.

Überwachtes und unüberwachtes Lernen

Auch hier hilft mir ChatGPT: Supervised Learning und Unsupervised Learning sind zwei Hauptkategorien maschinellen Lernens, die sich durch ihre Herangehensweise an die Verarbeitung von Daten unterscheiden.

  1. Supervised Learning (Überwachtes Lernen):
    • Definition: In diesem Ansatz wird der Algorithmus mit gelabelten Trainingsdaten trainiert, bei denen die richtigen Ausgaben bereits bekannt sind.
    • Beispiel: Klassifikation und Regression sind häufige Anwendungen des überwachten Lernens. Zum Beispiel, wenn ein Modell lernen soll, Hunde von Katzen zu unterscheiden, werden ihm viele Bilder von Hunden und Katzen mit den entsprechenden Labels (Hund oder Katze) gezeigt. Das Modell lernt, die Muster in den Daten zu erkennen und kann dann neue, nicht gelabelte Bilder richtig klassifizieren.
  2. Unsupervised Learning (Unüberwachtes Lernen):
    • Definition: Hier werden dem Algorithmus unlabeled Trainingsdaten präsentiert, und das Modell muss Muster oder Strukturen in den Daten selbstständig identifizieren.
    • Beispiel: Clustering und Dimensionsreduktion sind typische Aufgaben des unüberwachten Lernens. Nehmen wir an, wir haben eine Menge von Kundenkaufdaten, aber ohne vorherige Information darüber, welche Art von Kunden es gibt. Ein Clustering-Algorithmus könnte Muster erkennen und die Kunden in verschiedene Gruppen einteilen, basierend auf ihren Einkaufsgewohnheiten, ohne dass uns vorher gesagt wurde, welche Gruppen existieren.

Zusätzlich gibt es noch einen dritten Typ, das sogenannte Reinforcement Learning (Verstärkungslernen): - Definition: Hierbei lernt ein Algorithmus, indem er Aktionen in einer Umgebung ausführt und Feedback in Form von Belohnungen oder Bestrafungen erhält. - Beispiel: Ein selbstfahrendes Auto könnte durch Verstärkungslernen lernen, wie es sich in verschiedenen Verkehrssituationen verhalten soll. Positive Belohnungen (z.B., sicheres Fahren) und negative Bestrafungen (z.B., Unfälle) beeinflussen das Modell, um bessere Entscheidungen zu treffen.

Insgesamt sind diese Arten des maschinellen Lernens Werkzeuge, die je nach Art des Problems und der verfügbaren Daten angewendet werden können.

Beide Definitionen muss man ersteinmal wirken lassen.

Erste Schritte

Auch hier lade ich zuerst die nötigen Bibliotheken. Die Liste der Bibliothecken wir sich ebenfalls ständig vergrößern.

######
# KI ML hands on


# alles löschen
rm(list = ls())

# libraries
# Normale Packages zur Verarbeitung der Daten
library(tidyverse)     # dplyr und ggplot2 inkludiert
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.4.4     ✔ tibble    3.2.1
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.1
## ✔ purrr     1.0.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
#library(dplyr)         # für die Datenverarbeitung (Manipulation)
#library(ggplot2)       # Erstellen von aussagefähigen Grafiken
library(egg)
## Lade nötiges Paket: gridExtra
## 
## Attache Paket: 'gridExtra'
## 
## Das folgende Objekt ist maskiert 'package:dplyr':
## 
##     combine
library(ggpubr)
## 
## Attache Paket: 'ggpubr'
## 
## Das folgende Objekt ist maskiert 'package:egg':
## 
##     ggarrange
library(stats)
library(visdat)

# AI packages
library(rsample)   # für das Resampling Prozedere (Stuchprobenwiederholung)
library(modeldata)
library(caret)     # zum Modellanlernen des Resamplings  
## Lade nötiges Paket: lattice
## 
## Attache Paket: 'caret'
## 
## Das folgende Objekt ist maskiert 'package:purrr':
## 
##     lift
library(h2o)       # Deto zu Caret
## 
## ----------------------------------------------------------------------
## 
## Your next step is to start H2O:
##     > h2o.init()
## 
## For H2O package documentation, ask for help:
##     > ??h2o
## 
## After starting H2O, you can use the Web UI at http://localhost:54321
## For more information visit https://docs.h2o.ai
## 
## ----------------------------------------------------------------------
## 
## 
## Attache Paket: 'h2o'
## 
## Die folgenden Objekte sind maskiert von 'package:lubridate':
## 
##     day, hour, month, week, year
## 
## Die folgenden Objekte sind maskiert von 'package:stats':
## 
##     cor, sd, var
## 
## Die folgenden Objekte sind maskiert von 'package:base':
## 
##     %*%, %in%, &&, ||, apply, as.factor, as.numeric, colnames,
##     colnames<-, ifelse, is.character, is.factor, is.numeric, log,
##     log10, log1p, log2, round, signif, trunc
# Einstellung des h2o paketes
h2o.no_progress()  # keine Fortschritsanzeige (Progress bar) anzeigen
h2o.init()         # Packet starten
## 
## H2O is not running yet, starting it now...
## Warning in .h2o.startJar(ip = ip, port = port, name = name, nthreads = nthreads, : You have a 32-bit version of Java. H2O works best with 64-bit Java.
## Please download the latest Java SE JDK from the following URL:
## http://docs.h2o.ai/h2o/latest-stable/h2o-docs/welcome.html#java-requirements
## 
## Note:  In case of errors look at the following log files:
##     C:\Users\MANFRE~1\AppData\Local\Temp\Rtmp4OYDev\file362876936bec/h2o_Manfred_St_ckler_started_from_r.out
##     C:\Users\MANFRE~1\AppData\Local\Temp\Rtmp4OYDev\file36283d545af1/h2o_Manfred_St_ckler_started_from_r.err
## 
## 
## Starting H2O JVM and connecting:  Connection successful!
## 
## R is connected to the H2O cluster: 
##     H2O cluster uptime:         4 seconds 286 milliseconds 
##     H2O cluster timezone:       Europe/Berlin 
##     H2O data parsing timezone:  UTC 
##     H2O cluster version:        3.44.0.3 
##     H2O cluster version age:    2 months and 10 days 
##     H2O cluster name:           H2O_started_from_R_Manfred_Stückler_jaz804 
##     H2O cluster total nodes:    1 
##     H2O cluster total memory:   0.96 GB 
##     H2O cluster total cores:    8 
##     H2O cluster allowed cores:  8 
##     H2O cluster healthy:        TRUE 
##     H2O Connection ip:          localhost 
##     H2O Connection port:        54321 
##     H2O Connection proxy:       NA 
##     H2O Internal Security:      FALSE 
##     R Version:                  R version 4.3.2 (2023-10-31 ucrt)

Ich verwende am Anfang die gleichen Datensätze wie im Online-Buch

# Einlesen der Ames Housing daten

ames <- AmesHousing::make_ames()

ames.h2o <- as.h2o(ames)


# Job zuteiung bei churn rates mit dem Datensat attriton
churn <- attrition %>%           # modelldatensatz von IBM watsonanalytics
  mutate_if(is.ordered,
            .funs = factor,
            ordered = FALSE)

chrun.h2o <- as.h2o(churn) 

Zufällige Stichprobenziehung

Danach sollen die der Datensätze in zwei Gruppen aufgeteilt werden. Die Aufteilung muss zufällig erfolgen.

#########
# Aufteilung in Trainings und Test-Datensatz

# normale R Formel
set.seed(123) # um die ergebnisse nachvollziehen zu können. Die Zahl ist egal
# zufallsziehung aus der Grundgesamtheit ames
ziehung1 <- sample(1:nrow(ames),
                   round(nrow(ames) * 0.7)) 

# Trainingsdatensatz
training1 <- ames[ziehung1,]

# Test DS
test1 <- ames[-ziehung1,]

#Gleicher Vorgehen mit dem Packet Caret
set.seed(123)
# Die Zufallsziehung
ziehung2 <- createDataPartition(ames$Sale_Price,
                                p = 0.7,
                                list = FALSE)
training2 <- ames[ziehung2,]
test2 <- ames[-ziehung2,]

# rsample Package
set.seed(123)
# ziehung
ziehung3 <- initial_split(ames,
                          prop = 0.7)
training3 <- training(ziehung3) 
test3 <- testing(ziehung3)

# Ziehung mit h2o daten
ziehung4 <- h2o.splitFrame(ames.h2o,
                           ratios = 0.7,
                           seed = 123)
training4 <- ziehung4[[1]]
test4 <- ziehung4[[2]]

Grafische Gegenüberstellung des Lern- und Testdatensatzes Test- und Lerndatensatz sollen annähernd die gleiche Verteilung zeigen. Das kann man am Einfachsten und Besten grafisch darstellen.

# Erste Grafische gegenüberstellung
p_train1 <- ggplot(training1, 
       aes(x = Sale_Price),
       )+
  geom_density(color= "blue") +
  scale_x_continuous(labels = scales::comma)+
  scale_y_continuous(limit = c(0, 0.00001),
                     labels = scales::percent)
  
p_test1 <- ggplot(test1, 
       aes(x = Sale_Price),
       )+
  geom_density(color= "red") +
  scale_x_continuous(labels = scales::comma)+
  scale_y_continuous(limit = c(0, 0.00001),
                     labels = scales::percent)

  graph1 <- ggarrange(p_train1, p_test1,
            labels = c("Dichte: Lern-DS",
                       "Dichte: Test-DS"),
            ncol = 2,
            nrow = 1)   
  
    annotate_figure(graph1,
                    top =text_grob("Vergleich der Dichte der beider Ziehungen. Klassische R-Formel", 
                                   color = "black",
                                   face = "bold",
                                   size = 14))

  #caret-Packet  
  p_train2 <- ggplot(training2, 
                     aes(x = Sale_Price),
  )+
    geom_density(color= "blue") +
    scale_x_continuous(labels = scales::comma)+
    scale_y_continuous(limit = c(0, 0.00001),
                       labels = scales::percent)
  
  p_test2 <- ggplot(test2, 
                    aes(x = Sale_Price),
  )+
    geom_density(color= "red") +
    scale_x_continuous(labels = scales::comma)+
    scale_y_continuous(limit = c(0, 0.00001),
                       labels = scales::percent)
  
  graph2 <- ggarrange(p_train2, p_test2,
            labels = c("Dichte: Lern-DS",
                       "Dichte: Test-DS"),
            ncol = 2,
            nrow = 1) 
  
  annotate_figure(graph2,
                    top =text_grob("Vergleich der Dichte der beider Ziehungen. Packet Caret", 
                                   color = "black",
                                   face = "bold",
                                   size = 14))

Als besseren Vergleich mache ich hier nur eine Grafik mit beide Funktionen übereinander gelegt.

p <- ggplot()+
    geom_density(data = training2,
                 aes(x = Sale_Price,
                     color = "Data1"),
                 alpha = 0.6) + 
    geom_density(data = test2,
                 aes(x = Sale_Price,
                     color = "Data2"),
                 alpha = 0.6) +
    labs(title = "Vergleich der Dichtefunktion mit dem Caret-Packet", 
         x = "Verkaufspreis",
         y = "Dichte") +
  scale_x_continuous(labels = scales::comma)+
    scale_y_continuous(limit = c(0, 0.00001),
                       labels = scales::percent)+
    scale_fill_manual(values = c("Data1" = "red", "Data2" = "blue")) +
    theme_minimal() +
    theme(legend.position = "top")

print(p)

rsample Packet

#rsample-Packet  
  p_train3 <- ggplot(training3, 
                     aes(x = Sale_Price),
  )+
    geom_density(color= "blue") +
    scale_x_continuous(labels = scales::comma)+
    scale_y_continuous(limit = c(0, 0.00001),
                       labels = scales::percent)
  
  p_test3 <- ggplot(test3, 
                    aes(x = Sale_Price),
  )+
    geom_density(color= "red") +
    scale_x_continuous(labels = scales::comma)+
    scale_y_continuous(limit = c(0, 0.00001),
                       labels = scales::percent)
  
  graph3 <- ggarrange(p_train3, p_test3,
            labels = c("Dichte: Lern-DS",
                       "Dichte: Test-DS"),
            ncol = 2,
            nrow = 1) 
  
  annotate_figure(graph3,
                    top =text_grob("Vergleich der Dichte der beider Ziehungen. Packet rsample", 
                                   color = "black",
                                   face = "bold",
                                   size = 14))

h2o packet

funktioniert noch nicht da es kein DF ist

Geschichtete Stichprobenziehung (stratified Sampling)

wird eher bei klassifizierungsproblemen verwendet.

 # Die "Abwanderungs"- Verteilung errechnen
  table(churn$Attrition) %>% prop.table()
## 
##        No       Yes 
## 0.8387755 0.1612245
  # stratified sampling mit der rsample package
  zieh_strat <- initial_split(churn,
                              prop = 0.7,
                              strata = "Attrition") # welche Wariable stratified werden soll
  # Test und Trainingssample
  train_strat <- training(zieh_strat)
  test_strat  <- testing(zieh_strat)

  
  
  table(train_strat$Attrition) %>% prop.table()  
## 
##        No       Yes 
## 0.8394942 0.1605058
  table(test_strat$Attrition) %>% prop.table()  
## 
##        No       Yes 
## 0.8371041 0.1628959

Cross Validation und Bootstraping (Umschreiben)

Und wieder habe ich ChatGPT gefragt, was das eigentlich ist: Cross-Validation und Bootstrapping sind beide Methoden, die in der Maschinenlernpraxis verwendet werden, um Modelle zu evaluieren und die Leistung von Algorithmen zu schätzen. Hier sind die grundlegenden Unterschiede zwischen Cross-Validation und Bootstrapping:

  1. Cross-Validation:
    • Idee: Cross-Validation (CV) teilt den Datensatz in Trainings- und Testsets auf und führt mehrere Iterationen dieses Prozesses durch, um robuste Modellevaluierungen zu erhalten.
    • Vorgehensweise: Typischerweise wird der Datensatz in k gleich große Teile (sogenannte Folds) unterteilt. Das Modell wird k-mal trainiert, wobei in jeder Iteration ein anderer Fold als Testset verwendet wird, während die verbleibenden Folds für das Training genutzt werden.
    • Vorteile: CV ermöglicht eine zuverlässige Schätzung der Modellleistung und hilft, das Risiko von Overfitting oder Underfitting zu reduzieren. Gängige Typen sind k-fold Cross-Validation oder Stratified k-fold Cross-Validation.
  2. Bootstrapping:
    • Idee: Bootstrapping erstellt mehrere Bootstrap-Stichproben (Zufallsauswahlen mit Wiederholung) aus dem Originaldatensatz, um die Stabilität und Zuverlässigkeit von Schätzungen zu verbessern.
    • Vorgehensweise: Für jede Bootstrap-Stichprobe wird das Modell trainiert und evaluiert. Die Ergebnisse werden dann gemittelt, um eine robustere Leistungsschätzung zu erhalten.
    • Vorteile: Bootstrapping ist besonders nützlich, wenn der verfügbare Datensatz klein ist. Es hilft auch bei der Bewertung der Stabilität von Schätzungen und der Unsicherheit der Modellleistung.

Zusammenfassung: - Cross-Validation ist eine Methode zur Evaluierung von Modellen durch wiederholtes Aufteilen des Datensatzes in Trainings- und Testsets. - Bootstrapping erstellt mehrere Bootstrap-Stichproben aus dem Originaldatensatz, um robuste Schätzungen der Modellleistung zu erhalten. - Beide Techniken sind nützlich, um sicherzustellen, dass die Modellleistung zuverlässig geschätzt wird und nicht stark von der Zufälligkeit der Datenteilung abhängt.

Beispiele zu Crossvalidation

# h2o CV formel
# FM x und y nicht gefunden
#h2o_cv <- h2o.glm( x = x,
#                   y = y,
#                   training_frame = ames.h2o,
#                   nfolds = 10)

vfold_cv(ames,           # Datensatz
         v = 10)         # Anzahl Stichproben
## #  10-fold cross-validation 
## # A tibble: 10 × 2
##    splits             id    
##    <list>             <chr> 
##  1 <split [2637/293]> Fold01
##  2 <split [2637/293]> Fold02
##  3 <split [2637/293]> Fold03
##  4 <split [2637/293]> Fold04
##  5 <split [2637/293]> Fold05
##  6 <split [2637/293]> Fold06
##  7 <split [2637/293]> Fold07
##  8 <split [2637/293]> Fold08
##  9 <split [2637/293]> Fold09
## 10 <split [2637/293]> Fold10

Beispiele für Bootstraping

# bootstraping Beispiel

bootstraps(ames,             # Datensatz
           times = 10)       # Anzahl der Stichproben  
## # Bootstrap sampling 
## # A tibble: 10 × 2
##    splits              id         
##    <list>              <chr>      
##  1 <split [2930/1086]> Bootstrap01
##  2 <split [2930/1073]> Bootstrap02
##  3 <split [2930/1052]> Bootstrap03
##  4 <split [2930/1060]> Bootstrap04
##  5 <split [2930/1084]> Bootstrap05
##  6 <split [2930/1072]> Bootstrap06
##  7 <split [2930/1080]> Bootstrap07
##  8 <split [2930/1083]> Bootstrap08
##  9 <split [2930/1061]> Bootstrap09
## 10 <split [2930/1087]> Bootstrap10

Feature und Target Engineering

Feature Engineering und Target Engineering sind zwei Schlüsselkonzepte im Bereich des maschinellen Lernens, bei denen es darum geht, die Eigenschaften (Features) von Daten und die Zielvariablen (Targets) zu optimieren oder anzupassen, um die Leistung von Modellen zu verbessern.

Feature Engineering:

Definition: Feature Engineering bezieht sich auf den Prozess der Erstellung neuer Eigenschaften oder der Transformation bestehender Eigenschaften, um die Leistung von maschinellen Lernalgorithmen zu verbessern.

Ziele: Dieser Prozess kann dazu dienen, relevante Informationen aus den Daten zu extrahieren, Rauschen zu reduzieren, die Daten für bestimmte Modelle vorzubereiten oder die Modellleistung insgesamt zu steigern.

Beispiele: Feature Engineering kann die Umwandlung von kategorialen Variablen in numerische Darstellungen (One-Hot-Encoding), die Extraktion von Merkmalen aus Textdaten (wie TF-IDF oder Wortvektoren), die Skalierung von Eigenschaften oder die Erstellung von Interaktionsmerkmalen umfassen.

Target Engineering:

Definition: Target Engineering bezieht sich auf den Prozess der Manipulation oder Transformation der Zielvariablen (die zu prognostizierenden Werte), um die Modellleistung zu verbessern.

Ziele: Ziel ist es, Muster oder Strukturen in den Zielvariablen besser zu erfassen, Rauschen zu reduzieren oder die Daten so anzupassen, dass das Modell besser geeignet ist, die gewünschten Ergebnisse vorherzusagen.

Beispiele: Bei der Regressionsanalyse könnte Target Engineering die Anwendung einer Transformation auf die Zielvariable sein, um eine normalere Verteilung zu erreichen. In der Klassifikation könnte es das Anwenden von Sampling-Methoden auf unbalancierte Klassen sein, um die Leistung zu verbessern. Feature Engineering und Target Engineering sind iterative Prozesse, die oft während der Modellentwicklung durchgeführt werden. Die richtige Auswahl und Transformation von Eigenschaften sowie die Anpassung der Zielvariablen können dazu beitragen, die Vorhersagegenauigkeit von Modellen zu steigern und ihre Robustheit zu verbessern.