Zuweisung von numerischen Werten zu numerischen Eingabedaten
Beispiele:
Zuweisung von Klassen zu numerischen Eingabedaten
Beispiele:
Erkennen von Gruppierungen / Clustern bei numerischen Eingabedaten
Beispiele:
Vereinfachung von Daten mit einer großen Anzahl an Merkmalen zu Daten mit weniger, aber aussagekräftigeren Merkmalen
Optimieren von Strategien in einer Simulation
Beispiele:
Python Libraries für Machine Learning:
scikit-learn:
keras:
pytorch:
Schritte:
in scikit-learn:
x
oder X
) und eines Zielvektors / einer Zielmatrix (oft y
oder Y
)KNeighborsClassifier
, MLPClassifier
, LinearRegression
, ...model.fit(x, y)
model.score(x_val, y_val)
oder metrics.accuracy_score(x_val, y_val)
, ...model.predict(...)
oder model.predict_proba(...)
in keras:
x
) und ein Ziel-Array (y
)model.compile()
und "Lernen" via model.fit(x, y)
model.evaluate(x_val, y_val)
model.predict(...)
Iris Datensatz: einfacher Beispieldatensatz für Machine Learning / Data Science
Beinhaltet Abmessungen von 150 Iris-Pflanzen (Schwertlilien): 3 verschiedene Spezies mit je 50 Einträgen
Eigenschaften im Datensatz:
Beispiel CSV-Daten von http://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data:
5.1,3.5,1.4,0.2,Iris-setosa
4.9,3.0,1.4,0.2,Iris-setosa
4.7,3.2,1.3,0.2,Iris-setosa
...
7.0,3.2,4.7,1.4,Iris-versicolor
...
6.3,3.3,6.0,2.5,Iris-virginica
...
Aufgabe: trainiere einen Algorithmus, um Iris-Pflanzen basierend auf ihren Abmessungen zu klassifizieren
# load data via pandas
iris = pd.read_csv(
"http://archive.ics.uci.edu/ml/" +
"machine-learning-databases/iris/iris.data",
header=None,
names=["sepal_length", "sepal_width", "petal_length",
"petal_width", "species"]
)
iris_shuffled = iris.sample(frac=1.0)
# convert to numerical numpy arrays
measurements = iris_shuffled[[
"sepal_length",
"sepal_width",
"petal_length",
"petal_width",
]].to_numpy()
species = (
iris_shuffled["species"]
.replace({
"Iris-setosa": 0,
"Iris-versicolor": 1,
"Iris-virginica": 2,
})
.to_numpy()
)
from sklearn.neighbors import KNeighborsClassifier
model = KNeighborsClassifier()
from tensorflow import keras
model = keras.Sequential([
keras.layers.Dense(8),
keras.layers.Activation("relu"),
keras.layers.Dense(3),
keras.layers.Activation("softmax")
])
model.compile(
loss="sparse_categorical_crossentropy",
metrics=["accuracy"]
)
class NearestNeighborClassifier():
def fit(self, x, y):
# In a "real" machine learning algorithm,
# a lot of processing could happen here.
# In this case we're just storing the training data.
self.x = x
self.y = y
def predict_single(self, x):
vectors = self.x - x
distances = np.linalg.norm(vectors, axis=1)
min_index = np.argmin(distances)
return self.y[min_index]
model = NearestNeighborClassifier()
Trainieren basierend auf den ersten 130 Einträgen:
in scikit-learn:
model.fit(measurements[:130], species[:130])
in keras:
model.fit(
measurements[:130],
species[:130],
epochs=300,
validation_split=0.1
)
Anwenden der Klassifikation auf neue Daten (in scikit-learn):
demo_measurements = np.array([
[5.3, 3.4, 1.9, 0.6],
[6.0, 3.0, 4.7, 1.5],
[6.5, 3.1, 5.0, 1.7]
])
model.predict(demo_measurements)
# e.g. [0, 1, 1] in scikit-learn
model.predict_proba(demo_measurements)
# [[0.9 0.1 0. ]
# [0. 0.8 0.2]
# [0. 0.7 0.3]]
measurements_val = measurements[130:]
species_val = species[130:]
in scikit-learn (accuracy):
print(model.score(measurements_val, species_val))
in keras (categorical crossentropy, accuracy):
print(model.evaluate(measurements_val, species_val))
Regression:
Klassifizierung:
Lineare Regression: Festlegen einer linearen Funktion, die die Datenpunkte bestmöglich approximiert (kleinste Quadratsumme)
Beispiel: Wir betrachten verschiedene Einkäufe bei verschiedenen Supermärkten:
Aufgabe: Schätzung der Preise von:
Diese Aufgabe kann mit Hilfe von Regression beantwortet werden.
Eingangsdaten:
1, 1 → 5.00
2, 3 → 13.50
3, 2 → 10.90
0, 0 → 0.00
Ergebnis einer linearen Regression:
price = 0.05 + 1.13*x + 3.73*y
Machine Learning Verfahren, das in etwa die Interaktion von Neuronen im Gehirn nachahmt
Um einen Datenpunkt zu klassifizieren, werden ähnliche bekannte Datenpunkte betrachtet, für die schon eine Klassifizierung bekannt ist
Beispiel für die Iris-Klassifizierung:
An einer Grenze zwischen zwei Klassen wird mit Hilfe einer logistischen Funktion angegeben, wie groß die Wahrscheinlichkeit ist, dass der Datenpunkt zu der einen bzw zu der anderen Klasse gehört.
Die logistische Funktion selbst wird intern mittels Regression bestimmt (daher der Name).
Für die bekannten Klassen werden Wahrscheinlichkeitsverteilungen angenommen (z.B. Normalverteilung, Multinomialverteilung). Diese Verteilungen werden aus den Trainingsdaten hergeleitet.
Für einen neuen Datenpunkt wird dann errechnet, unter welcher der Verteilungen er am ehesten auftreten würde.
Zwei wichtige Verteilungen:
Einfachster Fall: Trennung von Klassen durch Geraden / Ebenen / Hyperebenen - diese Trenner sollen von den getrennten Punkten maximalen Abstand haben.
Durch Kernelfunktionen können die Grenzen auch andere Formen annehmen, z.B. die von Kegelschnitten für polynomiale Kernel vom Grad 2 oder anderen Kurven.
Überblick über Klassifizierungsalgorithmen in scikit-learn
Aufgabe: verwende andere Klassifizierungsalgorithmen in scikit-learn, z.B.:
sklearn.tree.DecisionTreeClassifier
sklearn.svm.SVC
sklearn.naive_bayes.GaussianNB
sklearn.neural_network.MLPClassifier
erwünschtes Datenformat für Machine Learning Algorithmen:
Aufgaben:
Welcher dieser beiden Sterne ist der Sonne am ähnlichsten?
# data: radius (km), mass (kg), temparature (K)
sun = [7.0e7, 2.0e30, 5.8e3]
star_a = [6.5e7, 2.2e30, 5.2e3]
star_b = [7.0e8, 2.1e30, 8.1e3]
manche Machine Learning Algorithmen wie z.B. k-Nearest-Neighbor betrachten Absolutwerte.
Hier würde vom Algorithmus im wesentlichen nur die Masse herangezogen werden, da alle anderen Werte im Vergleich verschwindend gering sind.
Lösung: Bevor ein Algorithmus angewendet wird, werden die Werte zentriert und skaliert (z.B. so, dass ihr Mittelwert 0 und ihre Standardabweichung 1 sind)
Fehlende Daten werden häufig in der Form von NaN
s auftreten.
Mögliche Behandlungen:
Manchmals: Kategorien als Eingangs- oder Ausgangsdaten - z.B. Land, Berufsgruppe, Messverfahren, ...
Beispiel für Eingangsdaten:
[["fr", "chrome"], ["uk", "chrome"], ["us", "firefox"]]
oftmals als Strings angegeben, Kodierung als Zahlen gewünscht
Eingangsdaten:
[["fr", "chrome"], ["uk", "chrome"], ["us", "firefox"]]
Kodierung als Ordinale (nicht für alle Algorithmen geeignet, da implizit geordnet (fr=0, uk=1, us=2)):
[[0., 0.], [1., 0.], [2., 1.]]
Eingangsdaten:
[["fr", "chrome"],
["uk", "chrome"],
["us", "firefox"]]
One-Hot-Kodierung:
# fr?, uk?, us?, chrome?, firefox?
[[1., 0., 0., 1., 0.],
[0., 1., 0., 1., 0.],
[0., 0., 1., 0., 1.]]
Beispiel für Preprocessing für Textklassifikation: Zählen von Wörtern
iris = pd.read_csv(
"http://archive.ics.uci.edu/ml/" +
"machine-learning-databases/iris/iris.data",
header=None)
iris_measures = iris.iloc[:, :4].to_numpy()
iris_species = iris.iloc[:, 4].to_numpy()
encoder = LabelBinarizer()
encoder.fit(iris_species)
iris_species_one_hot = encoder.transform(iris_species)
scaler = StandardScaler()
scaler.fit(iris_measures)
iris_measures_scaled = scaler.transform(iris_measures)
x = iris_measures_scaled
y = iris_species_one_hot
Um zu validieren, ob ein Verfahren ein passendes Ergebnis liefert:
Die Daten werden in Trainingsdaten und Validierungsdaten unterteilt
für iterative Algorithmen (z.B. Neuronale Netzwerke in keras):
für andere Algorithmen (z.B. sklearn):
Um das bestmögliche Modell zu bestimmen:
siehe Python Data Science Handbook → Hyperparameters and Model Validation → Selecting the Best Model
Klassifizierungsmetriken:
Regressionsmetriken:
Beispiel:
Ein Korb von Früchten enthält 10 Äpfel, 10 Orangen und 10 Pfirsiche
Ein Klassifizierungsalgorithmus liefert diese Ergebnisse:
accuracy: relativer Anteil korrekter Klassifizierungen (im Beispiel: 27/30=0.9)
confusion matrix: Tabelle mit Klassifizierungen für jede Kategorie
apples | oranges | peaches | |
---|---|---|---|
apples | 8 | 0 | 2 |
oranges | 0 | 10 | 0 |
peaches | 1 | 0 | 9 |
mittlere quadratische Abweichung
Bestimmtheitsmaß (R²):
vergleicht die mittlere quadratische Abweichung der Regression mit der Varianz der Eingangsdaten
Binäre Klassifizierung: Spam-Erkennung
Beispiele:
60 normale Nachrichten, 40 Spam-Nachrichten
1 normale Nachricht wird als Spam klassifiziert
5 Spam-Nachrichten werden als normal klassifiziert
precision (Genauigkeit) = 36/36=0.97 (35 von 36 Nachrichten, die als Spam Klassifiziert wuerden, sind tatsächlich Spam)
recall (Trefferquote) = 35/40 = 0.88 (35 von 40 Spam-Nachrichten wurden als solche erkannt)
siehe auch: Precision and recall auf der englischsprachigen Wikipedia
precision und recall haben unterschiedliche Relevanz in verschiedenen Szenarien
Beispiel: Beim Klassifizieren von E-mails als Spam ist precision besonders wichtig (vermeiden, eine E-mail fälschlicherweise als Spam zu klassifizieren)
f-score = harmonisches Mittel zwischen precision und recall
ROC (Receiver Operating Characteristic)
= Metrik, die true positives und false positives wiederspiegelt
Ein Klassifizierungsalgorithmus könnte bezüglich seiner true positives-Quote und false positives-Quote fein eingestellt werden:
Die ROC kann als Kurve dargestellt werden; je größer die Fläche unter der Kurve (area under the curve, AUC), desto besser die Klassifikation
Kreuzentropie (log loss): Misst, wie gut ein Modell einer Wahrscheinlichkeitsverteilung die tatsächliche Wahrscheinlichkeitsverteilung annähert
relevant bei neuronalen Netzwerken und logistischer Regression
Mögliches Problem beim Lernen: Der Algorithmus ist zu flexibel und erkennt scheinbare Muster in den Eingangsdaten, hinter denen aber keine Systematik steckt
Algorithmen, die anfällig für Overfitting sind:
Zur polynomialen Regression siehe: Data Science Handbook - Regularization
Manueller train-test Split:
rng = np.random.default_rng(seed=1)
random_indexes = rng.permutation(x.shape[0])
# e.g. [65, 44, 22, 133, 47, ...]
x_train = x[random_indexes[:120]]
y_train = y[random_indexes[:120]]
x_test = x[random_indexes[120:]]
y_test = y[random_indexes[120:]]
Automatische Unterteilung vis scikit-learn:
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x, y)
Validierung basierend auf den Testdaten:
from sklearn import metrics
y_prediction = model.predict(x_test)
score = metrics.accuracy_score(y_prediction, y_test)
print("accuracy:", score)
import pandas as pd
from sklearn.preprocessing import (
LabelBinarizer,
StandardScaler,
)
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn import metrics
# loading data
iris = pd.read_csv(
"http://archive.ics.uci.edu/ml/" +
"machine-learning-databases/iris/iris.data",
header=None)
iris_measures = iris.iloc[:, :4].to_numpy()
iris_species = iris.iloc[:, 4].to_numpy()
# preparing data
encoder = LabelBinarizer()
encoder.fit(iris_species)
iris_species_one_hot = encoder.transform(iris_species)
scaler = StandardScaler()
scaler.fit(iris_measures)
iris_measures_scaled = scaler.transform(iris_measures)
X = iris_measures_scaled
Y = iris_species_one_hot
# train-test-split
X_train, X_test, Y_train, Y_test = train_test_split(X, Y)
# training
model = KNeighborsClassifier()
model.fit(X_train, Y_train)
# validation
Y_prediction = model.predict(X_test)
score = metrics.accuracy_score(Y_prediction, Y_test)
print("accuracy: ", score)
# predicting further species
new_iris_data = [
[5.3, 3.4, 1.9, 0.6],
[6.0, 3.0, 4.7, 1.5],
[6.5, 3.1, 5.0, 1.7]
]
new_iris_predictions = model.predict(
scaler.transform(new_iris_data)
)
print("prediction data:")
print(new_iris_predictions)
predicted_labels = encoder.inverse_transform(
new_iris_predictions
)
print("predicted labels:")
print(predicted_labels)