Wie Maschinen lernen ¶

Eine kurze Einführung ¶

Autor: Ralf Spielmann

In [1]:
import pandas as pd 

df = pd.read_csv('Euro_DM.csv', index_col='Unnamed: 0')
df.head()
Out[1]:
EURO DM
1 3 5.86749
2 5 9.77915
3 6 11.73498
4 8 15.64664
5 12 23.46996

Wir wissen: Euro * 1,95583 ist der Umrechnungsfaktor für DM

Aber die Maschine nicht ;-)

Simpler konstruierter Fall für unser Beispiel; absolut linear; hier würde einfach DM/Euro ausreichen, was die Maschine aber nicht wissen kann

image-2.png

Normales Problem für lineare Regression

image-3.png

Achtung jetzt folgt ein kleines bisschen Mathe ;-) ¶

Maschinen berechnen die Differenz zwischen dem Ziel (hier DM) und einer Vorhersage

Vorhersage ist : f(x) = x * w + b

x ist hier unser Euro Wert

w ist ein Gewicht, welches es für die Maschine herauszufinden gilt, es bestimmt die Steigung der Funktion, also wie steil 𝑓 ( 𝑥 ) in Abhängigkeit von 𝑥 ansteigt oder abfällt.

b ist ein konstanter Wert, genannt Bias, welchen die Maschine ebenfalls ermitteln muss, er verschiebt die gesamte Funktion entlang der y-Achse nach oben oder unten.

Die Differenz ergibt sich aus dem (Ziel(DM) - (Vorhersage(x * w + b))

Dann bilden sie daraus den quadratischen Fehler : (DM - (x * w + b))²

Diesen Fehler versuchen sie soweit als möglich zu reduzieren und bedienen sich hier der partiellen Ableitungen für die quadratische Funktion.

Diese berechnet die Steigung für unsere Funktion und ist somit geeignet, als Maß für die Reduzierung des Fehlers zu dienen.

Die Grafik habe ich ins Deutsche übersetzt, sie stammt ursprünglich von: www.tpointtech.com/gradient-descent-in-machine-learning

ChatGPT Image 12. Apr. 2025, 08_39_22.png

Simples Gradienten Abstiegsverfahren manuell implemetiert; Beispiel lineare Regression mit einem Feature und einem Target

In [2]:
# Wir belegen unser Feature x und unser Target y
x = df['EURO'].astype(float).reset_index(drop=True)
y = df['DM'].astype(float).reset_index(drop=True)
In [3]:
'''
Optimizer Funktion
Update der Gewichte und des Bias für ein eindimensionales x-Array.
Parameter: Feature x[n], Target y[n], Gewicht w, Bias b, Lernrate alpha.
y_predict = (w*x[i] + b)
quadrierter_fehler = (y[i] - y_predict)²
Ableitung der Funktion nach w: 2x*(y[i] - (w*x[i] + b))
Ableitung der Funktion nach b: 2*(y[i] - (w*x[i] + b))
'''
def ralfs_optimizer(x, y, w, b, alpha):
    sw = 0.0
    sb = 0.0

    for i in range(len(x)):
        sw += 2*x[i]*(y[i] - (w*x[i] + b))  # Summenbildung Steigung für x
        sb += 2*(y[i] - (w*x[i] + b))        # Summenbildung Steigung für Bias
        
    # neues Gewicht w und neuen Bias b berechnen
    w += (sw/len(x) *alpha) # altes Gewicht plus durschnittlicher Wert der Gradienten-Summe sw mal Lernrate
    b += (sb/len(x) *alpha) # alter Bias plus durschnittlicher Wert des Bias-Gradienten sb mal Lernrate
    #### für dieses Beispiel eines sehr einfachen, völlig linearen Falls benötigen wir keinen Bias,
    #### also lasse ich ihn hier weg und bleibe bei 0.0  
    
    b = 0.0

    return w, b
In [4]:
def avg_loss(x, y, w, b):
    total_error = 0.0
    for i in range(len(x)):
        total_error += (y[i] - (w*x[i] + b))**2
    return total_error / len(x)
In [5]:
import numpy as np
import matplotlib.pyplot as plt

def fit(x, y, epochs, optimizer,  w = 0.0, b = 0.0, alpha = 0.00001 ):
    for e in range(epochs+1):
        w, b = optimizer(x, y, w, b, alpha)
        
        ''' ab hier reine Ausgabe '''
        image_counter = 1
         # Ausgabe des aktuellen loss der Epoche
         # Plus Ausgabe als Plot
        if (e == 0) or (e < 21 and e % 4 == 0) or (e >= 30 and e % 10 == 0) or (e == epochs):
            print("epoche: ", str(e), "loss: "+ '%.10f'%(avg_loss(x, y, w, b)))
            print("w, b: " + "%.8f"%(w)+ " " + "%.4f"%(b))
            plt.figure(image_counter)
            axes = plt.gca()
            plt.scatter(x, y)
            plt.xlabel("Euro")
            plt.ylabel("DM")
            plt.grid()
            X_plot = np.linspace(0,200,200)
            plt.plot(X_plot, X_plot*w + b)
            #plt.show() # Einzelne Plots anzeigen mit show();  ohne show() -> gemeinsam nach dem Training in einem Plot anzeigen
            image_counter += 1
            
    return w, b
In [6]:
import matplotlib.pyplot as plt
import matplotlib

matplotlib.rcParams['mathtext.fontset'] = 'stix'
matplotlib.rcParams['font.family'] = 'STIXGeneral'
matplotlib.rcParams.update({'font.size': 18})

plt.scatter(x, y, color='#1f77b4', marker='o')
plt.xlabel("EURO")
plt.ylabel("DM")
plt.grid()

Start des Trainings mit (x, y, Anzahl Epochen)

In [7]:
w, b = fit(x, y, epochs = 100, optimizer = ralfs_optimizer)
epoche:  0 loss: 20708.3222708693
w, b: 0.29294031 0.0000
epoche:  4 loss: 5654.6225693629
w, b: 1.08688399 0.0000
epoche:  8 loss: 1544.0534478705
w, b: 1.50176069 0.0000
epoche:  12 loss: 421.6198376878
w, b: 1.71855526 0.0000
epoche:  16 loss: 115.1276775924
w, b: 1.83184166 0.0000
epoche:  20 loss: 31.4368086201
w, b: 1.89103967 0.0000
epoche:  30 loss: 1.2248565228
w, b: 1.94304109 0.0000
epoche:  40 loss: 0.0477234671
w, b: 1.95330561 0.0000
epoche:  50 loss: 0.0018594254
w, b: 1.95533171 0.0000
epoche:  60 loss: 0.0000724479
w, b: 1.95573164 0.0000
epoche:  70 loss: 0.0000028227
w, b: 1.95581059 0.0000
epoche:  80 loss: 0.0000001100
w, b: 1.95582617 0.0000
epoche:  90 loss: 0.0000000043
w, b: 1.95582924 0.0000
epoche:  100 loss: 0.0000000002
w, b: 1.95582985 0.0000
In [8]:
def predict(x, w, b):
    return (x * w + b)
In [9]:
''' Euro für Prediction '''
#euro = float(input("Eingabe Euro für Umrechnung: ").replace(",","."))

euro = 86.32
In [14]:
import locale
locale.setlocale(locale.LC_ALL, 'de_DE')
locale._override_localeconv["thousands_sep"] = "."
locale._override_localeconv["grouping"] = [3, 3, 0]

print('Berechnetes Gewicht w: {0} | Bias b: {1} \n'.format(locale.format_string('%.10f',w , grouping = True), locale.format_string('%.2f', b , grouping = True)))



print("Umrechnung für Eingabe: "+str(euro)+ " Euro in DM\n")


# ----------------------
dm = predict(euro, w, b) # Die Maschine sagt vorher ;-)
# ----------------------
dm_manuell = euro * 1.95583 # Wir wissen den Faktor: 1.95583



print("\tper Prediction (x * w + b):   = "+str(dm))
      
print("\tmanuell mit Faktor 1,95583: = " +str(dm_manuell) + "\n")

print('DM aus Prediction gerundet:         {0} für EURO: {1}'.format(locale.format_string('%.2f',round(dm,2), grouping = True), locale.format_string('%.2f', euro , grouping = True)))
print('DM aus Umrechnung manuell gerundet: {0} für EURO: {1} \n'.format(locale.format_string('%.2f',round(dm_manuell,2), grouping = True), locale.format_string('%.2f', euro , grouping = True)))
Berechnetes Gewicht w: 1,9558298507 | Bias b: 0,00 

Umrechnung für Eingabe: 86.32 Euro in DM

	per Prediction (x * w + b):   = 168.8272327113119
	manuell mit Faktor 1,95583: = 168.82724559999997

DM aus Prediction gerundet:         168,83 für EURO: 86,32
DM aus Umrechnung manuell gerundet: 168,83 für EURO: 86,32 

Lassen wir jetzt eine Lineare Regression aus der Bibliothek sklearn.linear_model für uns arbeiten¶

In [11]:
from sklearn.linear_model import LinearRegression

x = df["EURO"].to_numpy().reshape(-1, 1)
y = df["DM"].to_numpy()

model = LinearRegression()
model.fit(x, y)

print("Gewicht: " + str(model.coef_))
print("Bias: " + str(model.intercept_) + "\n")

dm = model.predict([[euro]])

print(str(euro) + " Euro sind: " + str(round(dm[0],2)))
Gewicht: [1.95583]
Bias: 0.0

86.32 Euro sind: 168.83