Bernd Thomas
Jul 5 · 5 min read

2.2 Ein Chi-Square Classifier, Fit und Prediction

computerwoche.de

Der Classifier besteht aus der

  • Auswertung der Häufigkeitsverteilungen der Ziffern für jede Position in der eingelesenen Grundgesamtheit und den Klassen-Samples bei Supervised Learning und
  • Anwendung der Chi-Square Funktion (Chi-Square Test)

Das “fit” (Training) dieses Modells besteht aus der Bestimmung der Chi-Quadrat Parameter aus dem Trainingsset und der Identifikation von Ziffern-Position(en) mit signifikanten Abweichungen zur Gleichverteilung bzw. der Verteilung aus dem Trainingsset als Grundgesamtheit. Mit dem Signifikanz-Level wird bestimmt, ob die Null-Hypothese verworfen werden muss. Diese statistische Signifikanz wird als (zu lernende) Besonderheit auffällig und als ursächlich für die gerade/ungerade-Klassenzuordnung einer Zahl interpretiert. Bewusst wird darauf hingewiesen, dass dadurch eine statistische “Auffälligkeit” zu einer Ursache-Wirkung-Beziehung umgedeutet wird, was im Prinzip wissenschaftlich nicht generell akzeptabel ist.

Allerdings ist diese Art der “Umdeutung” einer statistischen Auffälligkeit ein durchaus realistischer Lernvorgang bei Lebewesen, insbesondere bei solchen mit kognitiven Fähigkeiten!

Das predict mit Testzahlen Sets findet wie folgt statt: Die Ziffern einer Testzahl werden positionsweise mit den “erlernten” Wahrscheinlichkeiten für die Klassenzugehörigkeit (y=0 bzw. y=1) versehen. Z.B. in 1234 wird der '2' das Paar (q0,q1) zugeordnet, wobei q0 und q1 die als Wahrscheinlichkeiten interpretierten, relativen Häufigkeiten aus dem Lernprozess bzgl. Position 1 sind. Das Paar für die Position, die im Training die beste Chi-Square-Signifikanz ergab, wird für die Vorhersage akzeptiert und als Ergebnis ausgegeben. Die Klassenzugehörigkeit der Testzahl wird wie üblich über den höheren Wahrscheinlichkeitswert festgelegt: z.B. 0 falls q0 > 0.5, 1 falls q0 < 0.5.

Wir testen den trainierten Chi-Square Classifier mit einer Testzahl und dem Predict-Verfahren.

'''Predict Verfahren '''# Prediction für einzelne Testzahlen 
z = 185 # beliebig oder per Input
test_y = 1 # Correct classification
# Alternative: Dialog-Eingabe
#z = input('Eingabe: Ganzzahl max 4-stellig:')
#test_y = input('Eingbe: Zugehörige Klassifikation (0 gerade, 1 ungerade:)')
test_x = pad_zeros(n_pos,z)
test_x = [int(k) for k in test_x] # Change to list of integers
print('Ziffer Pos p0 p1')
for pos in range(n_pos):
digit = test_x[pos]
p0 = P0[pos,digit]
print(' %2d %2d %5.2f %5.2f' % (digit,pos,p0,1-p0))
print('Chi Squared best:')
print('%2d %8.2f %2d %5.2f' % (np.argmax(chi0[:,0]),chi0[:,0].max(),np.argmin(chi0[:,1]),chi0[:,1].min()))
idx_max_chi = np.argmax(chi0[:,0])
idx_min_prob = np.argmin(chi0[:,1])
position_found = idx_max_chi == idx_min_prob
if position_found:
det_pos = idx_min_prob
p0 = P0[det_pos,test_x[det_pos]]
print('(p0,p1) best:')
print('%5.2f %5.2f' % (p0,1-p0)) # Output Wahrsch. für Klasse 0 bzw 1
pred = 0 if p0 > 0.5 else 1 # Output Sprungfunktion
print('Prediction: Class', pred)
if pred == test_y: # Test mit Vorgabe in X_test
print('Correct Classification')

else:
print('Fehler im Chi-Quadrat Test: max chi vs min prob!')
Ziffer Pos p0 p1
0 0 0.37 0.63
1 1 0.64 0.36
8 2 0.51 0.49
5 3 0.00 1.00
Chi Squared best:
3 105.39 3 0.00
(p0,p1) best:
0.00 1.00
Prediction: Class 1
Correct Classification

Wir wenden den trainierten Classifier auf ein Set von Testdaten an, also Zahlen, die nicht schon für das Training verwendet wurden (zumindest überwiegend). Das Predict-Verfahren wird hier als Funktion chi_predict implementiert. Außerdem erfolgt eine Score-Berechnung für das Testset.

'''Predict Methode - Anwendung auf Testdaten Set '''def chi_predict_s(z,y,n_pos):
'''Predict class even/odd from Chi-squared test
Input: z Integer, y target class, n number of positions
Returns 1 if correct, 0 if not'''
global P0 # P0 aus Training

test_x = pad_zeros(n_pos,z)
test_x = [int(k) for k in test_x] # Change to list of integers
test_y = y
for pos in range(n_pos):
digit = test_x[pos]
p0 = P0[pos,digit]
idx_max_chi = np.argmax(chi0[:,0])
idx_min_prob = np.argmin(chi0[:,1])
position_found = idx_max_chi == idx_min_prob
if position_found:
det_pos = idx_min_prob
p0 = P0[det_pos,test_x[det_pos]]
pred = 0 if p0 > 0.5 else 1 # Output Sprungfunktion
print(z,' >> Predicted Class:', pred, 'Target Class:', test_y)
if pred == test_y: # Test mit Vorgabe in X_test
return 1
else:
return 0

else:
print('Fehler im Chi-Quadrat Test: max chi vs min prob!')
return 0

# Erzeugen eines Testdaten Sets
nmin,nmax = 0,10000
n_cases = 50
N = 2
n_pos = 4
Z_test = np.random.randint(nmin,nmax,size=(n_cases,1))
y_test = Z_test[:] % N
y_test = (y_test > 0).astype(int) # Teilbar -> y=0, Rest >=1 -> y=1
test_chain = list(zip(Z_test,y_test))
score = 0.0
# Predict and Score für die Testdaten
for z,y in test_chain:
score += chi_predict_s(z[0],y[0],n_pos)

print('Score:',score/n_cases)

Output (gekürzt):
3133 >> Predicted Class: 1 Target Class: 1
3051 >> Predicted Class: 1 Target Class: 1
1838 >> Predicted Class: 0 Target Class: 0
2175 >> Predicted Class: 1 Target Class: 1
7654 >> Predicted Class: 0 Target Class: 0
5207 >> Predicted Class: 1 Target Class: 1
9061 >> Predicted Class: 1 Target Class: 1
4188 >> Predicted Class: 0 Target Class: 0
2535 >> Predicted Class: 1 Target Class: 1
5733 >> Predicted Class: 1 Target Class: 1
5674 >> Predicted Class: 0 Target Class: 0
3962 >> Predicted Class: 0 Target Class: 0
6514 >> Predicted Class: 0 Target Class: 0
8623 >> Predicted Class: 1 Target Class: 1
6835 >> Predicted Class: 1 Target Class: 1
5668 >> Predicted Class: 0 Target Class: 0
4462 >> Predicted Class: 0 Target Class: 0
9678 >> Predicted Class: 0 Target Class: 0
8784 >> Predicted Class: 0 Target Class: 0
1666 >> Predicted Class: 0 Target Class: 0
5219 >> Predicted Class: 1 Target Class: 1
783 >> Predicted Class: 1 Target Class: 1
4060 >> Predicted Class: 0 Target Class: 0
...
8593 >> Predicted Class: 1 Target Class: 1
Score: 1.0

Fazit

  • Das Chi-Quadrat Verfahren lernt offensichtlich die Bedeutung der Stellen und der Ziffern auf diesen Stellen.
  • Es gehen keine Vorgaben oder a priori Informationen über die Lösung ein (anders als beim Kernel Trick mit der sin**2 Funktion).
  • Natürlich ist der erlernte Zustand so eindeutig, dass man das mit “bloßem Auge” erkennt. Das ML Verfahren kennt das aber a priori nicht, daher die diversen Auswertungsschritte (Vergleich mit Zielklasse, Score etc.)
  • Es gibt gute Gründe zu der Annahme, dass Kinder durchaus auf diese Weise zwischen gerade / ungerade unterscheiden lernen, wenn sie zwar Zahlen kennen aber noch keine Arithmetik (z.B. Teilen durch 2 mit Rest). D.h. sie lernen auf die Ziffer ganz rechts zu schauen und merken sich die “geraden” Ziffern.
  • Das Trainingsdaten Set muss nicht 100% korrekt sein! D.h. das Verfahren kann auch gerade / ungerade unterscheiden lernen, wenn eine Teilmenge fehlerhaft klassifiziert sind. Das entspricht einer realen Robustheit des Lernverfahrens. Siehe Tests in 2.3.
  • Das Verfahren ist “supervised”, da beim Training die Klassifikation vorgeben ist. Interessant wäre zu prüfen, ob das Verfahren auch “unsupervised” vernünftige Ergebnisse liefert.
  • Es liegt nahe, das Verfahren auch für Vielfache anderer Zahlen aus zu probieren, z.B. für die 5 (siehe 2.3).

Weiter lesen: 2.3 Unabhängigkeit und Robustheit — Erweiterte Anwendung des Chi-Square Verfahrens

Zurück auf Anfang

bernhard.thomas@becketal.com
www.becketal.com

Beck et al.

*Arbeiten ist Zusammenarbeiten*. Von Menschen, Daten, Infrastrukturen. Dafür stehen wir.

Bernd Thomas

Written by

Dr. Bernhard Thomas — Mathematics, Theor. Biology, Computational Sciences, AI and advanced Technologies for the Enterprise. Beck et al. Consultant

Beck et al.

*Arbeiten ist Zusammenarbeiten*. Von Menschen, Daten, Infrastrukturen. Dafür stehen wir.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade