Lösung: Normalisierung
Experimentell lässt sich am Programmbeispiel leicht zeigen, dass die niedrige Lernrate von alpha = 0.01 von den großen Werten des Features "Durchschnittliche Anzahl der Zehen pro Spieler" toes bedingt wird. Bei alpha = 0.1 divergiert das KNN:
0. loop: weights=[ 0.1 0.2 -0.1] pred=0.86 delta=-0.14 -> weight_deltas=[-1.19 -0.091 -0.168]
1. loop: weights=[ 0.219 0.2091 -0.0832] pred=1.898 delta= 0.8976 -> weight_deltas=[7.62939 0.58342 1.07709]
2. loop: weights=[-0.5439 0.1508 -0.1909] pred=-4.755 delta=-5.755 -> weight_deltas=[-48.91391 -3.74048 -6.90549]
Werden diese Daten durch 10 geteilt befinden sich diese Daten im Bereich der beiden anderen Features "Gewinnerwartung" und "Zahl der Fans in Millionen".
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
import numpy as np weights = np.array([0.1, 0.2, -0.1]) def neural_network(input, weights): pred = input.dot(weights) # replaces w_sum(a,b) return pred toes = np.array([0.85, 0.95, 0.9, 0.9]) # normalized data wlrec = np.array([0.65, 0.8, 0.8, 0.9]) nfans = np.array([1.2, 1.3, 0.5, 1.0]) # Input is the first game of the season. input = np.array([toes[0],wlrec[0],nfans[0]]) # first game: 1 => win win_or_lose_binary = [1, 1, 0, 1] alpha = 0.1 # increased learning rate for i in range(3): pred = neural_network(input,weights) delta = pred - win_or_lose_binary[0] # one delta weight_deltas = input * delta # but three weight_deltas (weighted by input) print(f'{i}. loop: weights={np.array2string(weights, precision=4)} pred={pred:.4} delta={delta:.4} -> weight_deltas={np.array2string(weight_deltas, precision=5)}') weights = weights - alpha * weight_deltas # 3 new weights |
Jetzt lässt sich die Lernrate dementsprechend auf alpha = 0.1 erhöhen und das KNN konvergiert trotzdem wieder:
0. loop: weights=[0.1 0.2 -0.1] pred=0.095 delta=-0.905 -> weight_deltas=[-0.76925 -0.58825 -1.086 ]
1. loop: weights=[0.1769 0.2588 0.0086] pred=0.3289 delta=-0.6711 -> weight_deltas=[-0.5704 -0.43619 -0.80527]
2. loop: weights=[0.234 0.3024 0.0891] pred=0.5024 delta=-0.4976 -> weight_deltas=[-0.42295 -0.32343 -0.59711]
(Das KNN konvergiert sogar bis zu einer Lernrate von alpha = 0.41.)
Normalisierung
Die Anpassung der Dateneingaben auf ähnliche Wertebereiche wird als Normalisierung bezeichnet. Ein KNN mit normalisierten Daten konvergiert besser und schneller.
(Es gibt hierfür verschiedene mathematische Verfahren, auf die an dieser Stelle nicht eingegangen wird. Weitere Informationen finden sich z.B. hier:
https://towardsdatascience.com/data-normalization-in-machine-learning-395fdec69d02 (3.10.2022))
Fehlerflächen
Tatsächlich sind die Fehlerkurven nur kleine Ausschnitte bzw. 2-dimensionale Schnitte aus Fehlerflächen, deren Komplexität durch die Trainingsdaten und deren Gewichte festgelegt werden. Unter Umständen finden man nicht die absoluten Tiefpunkte mit der Steigung 0 in diesen eventuell sehr zerklüfteten Flächen, sondern nur lokale Tiefpunkte. Interessante Darstellungen finden sich dazu z.B. hier:
https://ml4a.github.io/ml4a/how_neural_networks_are_trained/ (04.10.2022)