Suite de la précédente "Implémentation des règles d'apprentissage Perceptron en Python" Cette fois, j'ai implémenté la règle d'apprentissage Widrow-Hoff, qui est l'une des méthodes de reconnaissance de formes, en Python sans utiliser de bibliothèque. Étant donné que je suis un débutant en Python et en apprentissage automatique, veuillez signaler les mauvais points.
Le plan et les formules des règles d'apprentissage de Widrow-Hoff sont résumés grossièrement dans la diapositive ci-dessous (à partir du milieu de la diapositive).
https://speakerdeck.com/kirikisinya/xin-zhe-renaiprmlmian-qiang-hui-at-ban-zang-men-number-3
Pour les données d'apprentissage qui existent sur une dimension comme indiqué dans la figure ci-dessous et qui appartiennent à l'une des deux classes, la fonction discriminante de chaque classe est obtenue.
Comme point de mise en œuvre,
w = (0,2,0,3)
et le coefficient d'apprentissage est ρ = 0,2
.Le code réel ressemble à ceci:
main.py
# coding: UTF-8
# #Veuve 1D-Exemple d'implémentation des règles d'apprentissage Hoff
import numpy as np
import matplotlib.pyplot as plt
from widrow_hoff import get_wvec
if __name__ == '__main__':
data = np.array([[1.0, 1],[0.5, 1],[-0.2, 2],[-0.4, 1],[-1.3, 2],[-2.0, 2]])#Groupe de données
features = data[:,0].reshape(data[:,0].size,1)#Vecteur caractéristique
labels = data[:,1]#Classe (cette fois c1=1,c2=2)
wvec = np.array([0.2, 0.3])#Vecteur de poids initial
xvecs = np.c_[np.ones(features.size), features]#xvec[0] = 1
#À propos de la classe 1
tvec1 = labels.copy()#Vecteur d'enseignant de classe 1
tvec1[labels == 1] = 1
tvec1[labels == 2] = 0
wvec1 = get_wvec(xvecs, wvec, tvec1)
print "wvec1 = %s" % wvec1
print "g1(x) = %f x + %f" % (wvec1[1], wvec1[0])
for xvec,label in zip(xvecs,labels):
print "g1(%s) = %s (classe:%s)" % (xvec[1],np.dot(wvec1, xvec), label)
#À propos de la classe 2
tvec2 = labels.copy()#Vecteur d'enseignant de classe 2
tvec2[labels == 1] = 0
tvec2[labels == 2] = 1
wvec2 = get_wvec(xvecs, wvec, tvec2)
print "wvec2 = %s" % wvec2
print "g2(x) = %f x + %f" % (wvec2[1], wvec2[0])
for xvec,label in zip(xvecs,labels):
print "g2(%s) = %s (classe:%s)" % (xvec[1],np.dot(wvec, xvec), label)
widrow_hoff.py
# coding: UTF-8
#Widrow-Logique d'apprentissage des règles d'apprentissage de Hoff
import numpy as np
#Apprendre le coefficient de poids
def train(wvec, xvecs, tvec):
low = 0.2#Coefficient d'apprentissage
for key, w in zip(range(wvec.size), wvec):
sum = 0
for xvec, b in zip(xvecs, tvec):
wx = np.dot(wvec,xvec)
sum += (wx - b)*xvec[key]
wvec[key] = wvec[key] - low*sum
return wvec
#Trouvez le coefficient de poids
def get_wvec(xvecs, wvec, tvec):
loop = 100
for j in range(loop):
wvec = train(wvec, xvecs, tvec)
return wvec
Lorsque cela a été fait, les résultats suivants ont été obtenus.
La fonction discriminante de chaque classe est la suivante.
g1(x) = 0.37x + 0.69 #Fonction discriminante de classe 1
g2(x) = -0.37x + 0.35 #Fonction discriminante de classe 2
De plus, la règle d'apprentissage de Widrof-Hoff est «g1 (x)> g2 (x)» pour les données de classe 1 et «g1 (x) <g2 (x)» pour les données de classe 2. C'était bien si ça devenait `(ça se reconnaît bien!).
Sur cette base, si vous regardez le résultat de l'exécution
・ Lorsque les données x = 1.0
(classe 1)
g1(1.0)
> g2(1.0)
=> OK
・ Lorsque les données x = 0,5
(classe 1)
g1(0.5)
> g2(0.5)
=> OK
-Pour les données x = -0,2
(classe 2)
g1(-0.2)
> g2(-0.2)
=> NG
-Pour les données x = -0,4
(classe 1)
g1(-0.4)
= g2(-0.4)
=> NG
-Pour les données x = -1,3
(classe 2)
g1(-1.3)
< g2(-1.3)
=> OK
・ Pour les données x = -2,0
(classe 2)
g1(-2.0)
< g2(-2.0)
=> OK
Par conséquent, les données «x = -0,2» et «x = -0,4» près du milieu de la classe 1 et de la classe 2 ne sont pas bien identifiées (mauvaise identification), et les autres sont bien identifiées. Ce résultat est cohérent avec l'intuition qu'il est difficile de discriminer près du milieu de la classe, et on considère que la fonction discriminante est bien déterminée.
Recommended Posts