English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Description de l'algorithme de régression logistique en machine learning en langage Python

Dans cet article, nous présentons l'algorithme de régression logistique en apprentissage automatique, nous utilisons cet algorithme pour classifier les données. L'algorithme de régression logistique est également un algorithme d'apprentissage supervisé basé sur l'espace d'échantillons et adapté aux données numériques et nominales, par exemple, nous devons juger de la classification ou non des données en fonction de la taille des valeurs des caractéristiques des données d'entrée (numériques).

I. Données d'échantillons

Dans notre exemple, nous avons les données d'échantillons suivantes :

Les données d'échantillons ont3les valeurs des caractéristiques : X0X0, X1X1, X2X2

Nous passons par cela3les valeurs des caractéristiques X1X1和X2X2Pour juger de la conformité des données aux exigences, c'est-à-dire les données conformes aux exigences sont1Ceux qui ne correspondent pas aux exigences sont 0.

Les données d'échantillons de classification sont stockées dans un tableau.

Dans le fichier logRegres.py, nous écrivons la fonction suivante pour préparer les données et affichons les données pour observation :

#coding=utf-8
from numpy import *
def loadDataSet():
 dataMat = []; labelMat = []
 fr = open('testSet.txt')
 for line in fr.readlines():
  lineArr = line.strip().split()
  dataMat.append([1.0, float(lineArr[1])])
  labelMat.append(int(lineArr[2))
 return dataMat,labelMat
if __name__=='__main__':
 dataMat,labelMat=loadDataSet()
 print 'dataMat:\n',dataMat

Nous allons observer quelques échantillons de données :

dataMat:
[[1.0, -0.017612, 14.053064], [1.0, -1.395634, 4.662541], [1.0, -0.752157, 6.53862], [1.0, -1.322371, 7.152853], [1.0, 0.423363, 11.054677], [1.0, 0.406704, 7.067335], [1.0, 0.667394, 12.741452], [1.0, -2.46015, 6.866805], [1.0, 0.569411, 9.548755], [1.0, -0.026632, 10.427743], [1.0, 0.850433, 6.920334], [1.0, 1.347183, 13.1755], [1.0, 1.176813, 3.16702], [1.0, -1.781871, 9.097953], [1.0, -0.566606, 5.749003], [1.0, 0.931635, 1.589505], [1.0, -0.024205, 6.151823], [1.0, -0.036453, 2.690988], [1.0, -0.196949, 0.444165], [1.0, 1.014459, 5.754399], [1.0, 1.985298, 3.230619], [1.0, -1.693453, -0.55754], [1.0, -0.576525, 11.778922], [1.0, -0.346811, -1.67873], [1.0, -2.124484, 2.672471], [1.0, 1.217916, 9.597015], [1.0, -0.733928, 9.098687], [1.0, -3.642001, -1.618087], [1.0, 0.315985, 3.523953], [1.0, 1.416614, 9.619232], [1.0, -0.386323, 3.989286], [1.0, 0.556921, 8.294984], [1.0, 1.224863, 11.58736], [1.0, -1.347803, -2.406051], [1.0, 1.196604, 4.951851], [1.0, 0.275221, 9.543647], [1.0, 0.470575, 9.332488], [1.0, -1.889567, 9.542662], [1.0, -1.527893, 12.150579], [1.0, -1.185247, 11.309318], [1.0, -0.445678, 3.297303], [1.0, 1.042222, 6.105155], [1.0, -0.618787, 10.320986], [1.0, 1.152083, 0.548467], [1.0, 0.828534, 2.676045], [1.0, -1.237728, 10.549033], [1.0, -0.683565, -2.166125], [1.0, 0.229456, 5.921938], [1.0, -0.959885, 11.555336], [1.0, 0.492911, 10.993324], [1.0, 0.184992, 8.721488], [1.0, -0.355715, 10.325976], [1.0, -0.397822, 8.058397], [1.0, 0.824839, 13.730343], [1.0, 1.507278, 5.027866], [1.0, 0.099671, 6.835839], [1.0, -0.344008, 10.717485], [1.0, 1.785928, 7.718645], [1.0, -0.918801, 11.560217], [1.0, -0.364009, 4.7473], [1.0, -0.841722, 4.119083], [1.0, 0.490426, 1.960539], [1.0, -0.007194, 9.075792], [1.0, 0.356107, 12.447863], [1.0, 0.342578, 12.281162], [1.0, -0.810823, -1.466018], [1.0, 2.530777, 6.476801], [1.0, 1.296683, 11.607559], [1.0, 0.475487, 12.040035], [1.0, -0.783277, 11.009725], [1.0, 0.074798, 11.02365], [1.0, -1.337472, 0.468339], [1.0, -0.102781, 13.763651], [1.0, -0.147324, 2.874846], [1.0, 0.518389, 9.887035], [1.0, 1.015399, 7.571882], [1.0, -1.658086, -0.027255], [1.0, 1.319944, 2.171228], [1.0, 2.056216, 5.019981], [1.0, -0.851633, 4.375691], [1.0, -1.510047, 6.061992], [1.0, -1.076637, -3.181888], [1.0, 1.821096, 10.28399], [1.0, 3.01015, 8.401766], [1.0, -1.099458, 1.688274], [1.0, -0.834872, -1.733869], [1.0, -0.846637, 3.849075], [1.0, 1.400102, 12.628781], [1.0, 1.752842, 5.468166], [1.0, 0.078557, 0.059736], [1.0, 0.089392, -0.7153], [1.0, 1.825662, 12.693808], [1.0, 0.197445, 9.744638], [1.0, 0.126117, 0.922311], [1.0, -0.679797, 1.22053], [1.0, 0.677983, 2.556666], [1.0, 0.761349, 10.693862], [1.0, -2.168791, 0.143632], [1.0, 1.38861, 9.341997], [1.0, 0.317029, 14.739025]]
labelMat:
[0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0]

La première colonne des données d'échantillon dataMat, c'est-à-dire notre valeur de caractéristique X0X0, est1Cette question doit être prise en compte lors du calcul des paramètres de régression. Tous les données d'échantillons en tout100, les résultats de classification correspondants sont également100.

Alors, notre problème actuel est :
Nous devons trouver la relation entre les valeurs de caractéristiques dans l'espace d'échantillons et les résultats de classification. Concevoir une fonction ou une fonctionnalité, qui, après l'entrée d'un ensemble de valeurs de caractéristiques, peut classer automatiquement les données en fonction de la relation entre les valeurs de caractéristiques de l'espace d'échantillons et les résultats de classification, c'est-à-dire obtenir un résultat soit1Soit 0.

Deuxième, fonction Sigmoid

Pour résoudre le problème mentionné dans la section précédente, nous présentons d'abord la fonction Sigmoid :

Cette fonction a les caractéristiques suivantes :

Quand z=0z=0, la valeur est 0.50.5
Quand z z augmente constamment, la valeur approche1
Quand z z diminue constamment, la valeur approche 0
Regardons le graphique de la fonction :

Si nous insérons dans l'espace d'échantillons3Des valeurs de caractéristiques X0X0, X1X1和X2X2La valeur insérée dans la fonction, calculée pour obtenir un résultat. Alors ce résultat sera proche de notre résultat de classification (0 à1Entre une valeur numérique). Si ce résultat est proche de 0, nous pensons que la classification est 0, si le résultat est proche1Nous pensons que la classification est1.

Comment les insérer dans la fonction ? En fait, une simple addition suffit, car lorsque z z augmente ou diminue constamment, la valeur de la fonction approche1Ou 0. Nous faisons en sorte que z=x0+x1+x2Z=x0+x1+x2

Mais dans la réalité, nos résultats de calcul et les valeurs de classification réelles auront des erreurs, même完全不正确。Pour corriger ce problème, nous devons corriger les erreurs pour l'espace d'échantillons.3Des valeurs de caractéristiques X0X0, X1X1和X2X2Définir une à une les coefficients de régression w0w0, w1w1Et w2w2Afin de réduire cette erreur.+w1x1+w2x2

En réalité, il n'est pas difficile d'imaginer que la valeur de ce groupe de coefficients de régression w w détermine l'exactitude, même la justesse de nos résultats de calcul. Autrement dit, cette valeur de w w réagit aux règles de classification de l'espace d'échantillons.
Alors, en ajoutant des données en dehors du groupe d'échantillons en entrée, avec les coefficients de régression w w corrects, nous pouvons obtenir des résultats de classification plus proches de la règle de classification de l'espace d'échantillons.
Mais comment obtenons-nous ce groupe de coefficients de régression w w ?

Troisième, méthode de montée de gradient

La méthode de montée de gradient, c'est-à-dire, dans la direction de la dérivée de la fonction, itérer constamment pour calculer la valeur des paramètres, afin de trouver une valeur maximale des paramètres. L'équation itérative suivante :

Dans laquelle, αα est la longueur d'étape, Δσ(w)Δσ(w) est la dérivée de la fonction σ(w)σ(w). Pour la dérivation de la dérivée, veuillez consulterIciLe mathématicien de l'auteur a des capacités limitées, il ne fait pas d'explications.

Finalement, nous pouvons obtenir l'équation de calcul de la dérivée :

Alors, l'équation itérative suivante :

Explication de la formule :

wk+1wk+1est le résultat du coefficient de régression du terme de caractéristique XX pour cette itération.
wkwk est le résultat du coefficient de régression du terme de caractéristique XX à l'itération précédente.
αα est la longueur de pas de chaque itération dans la direction de la pente.
xixi est l'élément i du terme de caractéristique XX.
yiyi est la valeur de classification de l'échantillon i du modèle.
σ(xi,wk)σ(xi,wk) est la valeur de classification correspondante à l'enregistrement i du modèle, calculée en utilisant la fonction sigmoïde et wkwk comme coefficient de régression.
[yi−σ(xi,wk)][yi−σ(xi,wk)] est la valeur de classification correspondante au enregistrement i du modèle, et la valeur d'erreur de classification calculée en utilisant la fonction sigmoïde avec wkwk comme coefficient de régression.

Maintenant que nous avons la formule de calcul du coefficient de régression, nous allons réaliser une fonction dans le fichier logRegres.py pour calculer le coefficient de régression de l'espace d'échantillonnage et imprimer nos résultats :

def gradAscent(dataMatIn, classLabels):
 dataMatrix = mat(dataMatIn)    #100 ligne3Colonne
 #print dataMatrix
 labelMat = mat(classLabels).transpose() #100 ligne1Colonne
 #print 'labelMat:\n',labelMat
 print 'labelMat de forme : rowNum=',shape(labelMat)[0],'colNum=',shape(labelMat)[1]
 rowNum,colNum = shape(dataMatrix)
 alpha = 0.001
 maxCycles = 500
 weights = ones((colNum,1)) #3Ligne1Colonne
 #print shape(dataMatrix)
 #print shape(weights)
 #print shape(labelMat)
 for k in range(maxCycles):    #opération matricielle lourde
  h = sigmoid(dataMatrix*weights)  #100 ligne1Colonne
  #print h
  error = (labelMat - h)    #soustraction vectorielle
  weights = weights + alpha * dataMatrix.transpose()* Erreur #3Ligne1Colonne
 return weights
if __name__=='__main__':
 dataMat,labelMat=loadDataSet()
 #weights=gradAscent(dataMat,labelMat)
 #print 'dataMat:\n',dataMat
 #print 'labelMat:\n',labelMat
 print weights

Résultat d'impression :

Coefficient de régression :
[[ 4.12414349]
 [ 0.48007329]
 [-0.6168482 ]]

Pour vérifier l'exactitude du coefficient de rétrospection calculé, regardons le diagramme de dispersion de l'espace d'échantillonnage et la courbe d'ajustement des coefficients de régression. Nous utilisons z(x1,x2)=w0+w1x1+w2x2作为我们的拟合函数,在坐标系中画出它的拟合曲线。以样本空间中X1X1和X2X2的值作为横坐标和纵坐标,画出样本空间的散点。代码如下:

def plotBestFit(weights):
 import matplotlib.pyplot as plt
 dataMat,labelMat=loadDataSet()
 dataArr = array(dataMat)
 n = shape(dataArr)[0] 
 xcord1 = []; ycord1 = []
 xcord2 = []; ycord2 = []
 for i in range(n):
  if int(labelMat[i])== 1:
   xcord1.append(dataArr[i,1]); ycord1.append(dataArr[i,2])
  else:
   xcord2.append(dataArr[i,1]); ycord2.append(dataArr[i,2])
 fig = plt.figure()
 ax = fig.add_subplot(111)
 ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')
 ax.scatter(xcord2, ycord2, s=30, c='green')
 x = arange(-3.0, 3.0, 0.1)
 y = (-weights[0]-weights[1]*x)/weights[2]
 y = y.transpose()
 ax.plot(x, y)
 plt.xlabel('X1'); plt.ylabel('X2');
 plt.show()
if __name__=='__main__':
 dataMat,labelMat=loadDataSet()
 weights=gradAscent(dataMat,labelMat)
 print '回归系数:\n',weights
 plotBestFit(weights)

运行后,我们得到如下图片:

通过我们的观察,我们的这个回归系数的算法还是比较准确的,拟合曲线将样本数据分成两部分,并且符合样本的分类规则。

接下来,我们来实现一个分类器,并测试这个分类器:

def classify0(targetData,weights):
 v = sigmoid(targetData*weights)
 if v>0.5:
  return 1.0
 else :
  return 0
def testClassify0():
 dataMat,labelMat=loadDataSet()
 examPercent=0.7
 row,col=shape(dataMat)
 exam=[]
 exam_label=[]
 test=[]
 test_label=[]
 for i in range(row):
  if i < row*examPercent:
   exam.append(dataMat[i])
   exam_label.append(labelMat[i])
  else:
   test.append(dataMat[i])
   test_label.append(labelMat[i])
 weights=gradAscent(exam,exam_label)
 errCnt=0
 trow,tcol=shape(test)
 for i in range(trow):
  v=int(classify0(test[i],weights))
  if v != int(test_label[i]):
   errCnt += 1
   print 'Valeur calculée :',v,' Valeur originale',test_label[i]
 print 'Taux d'erreur :',errCnt/trow
if __name__=='__main__':
 #dataMat,labelMat=loadDataSet()
 #weights=gradAscent(dataMat,labelMat)
 ##print 'dataMat:\n',dataMat
 ##print 'labelMat:\n',labelMat
 #print 'Coefficients de régression :\n',weights
 #plotBestFit(weights)
 testClassify0()

La mise en œuvre du classificateur est simple. Nous utilisons les données d'échantillon précédentes70 données en tant qu'échantillons de test, calculons les coefficients de régression. Ensuite, utilisons le classificateur pour les autres30 enregistrements pour la classification, puis comparons les résultats avec les données d'échantillon. Enfin, nous affichons le taux d'erreur. Nous pouvons voir que le taux d'erreur est de 0, presque parfait ! Nous pouvons modifier la proportion de l'échantillon d'origine pour tester plusieurs fois. Alors, la conclusion est que l'exactitude de notre algorithme n'est pas mauvaise !

Alors, le problème est-il résolu ici ? Il semble que quelque chose manque encore. Analysons en détail notre méthode de calcul des coefficients de régression, et nous pouvons constater que, dans ce processus, nous avons utilisé la matrice composée des données d'échantillon pour effectuer une multiplication de matrices. Autrement dit, pour calculer les coefficients de régression, nous avons parcouru l'ensemble des données d'échantillon.

Notre problème est de nouveau ici, les données d'échantillon de notre exemple ne sont que :100, si nous traitons des milliers de données d'échantillons, la complexité de calcul de notre fonction de coefficient de régression augmentera en ligne droite. regardons comment optimiser cet algorithme.

Quatre : Optimisation de l'algorithme de montée de gradient - Méthode de gradient stochastique

Une fois que nous avons compris la formule d'itération du coefficient de régression :

et après notre programme réalisé. Nous allons améliorer la méthode de calcul des coefficients de régression de la manière suivante :

def stocGradAscent0(dataMatrix, classLabels):
 m,n = shape(dataMatrix)
 alpha = 0.01
 weights = ones((n,1)) #initialiser à tous les uns
 for i in range(m):
  h = sigmoid(sum(dataMatrix[i]*weights))
  error = classLabels[i] - h
  weights = weights + alpha * erreur * mat(dataMatrix[i]).transpose()
 return weights

Lors de chaque itération, pour calculer les coefficients de régression, on utilise un seul point d'échantillon de l'espace d'échantillon. Pour voir l'exactitude de cet algorithme, nous générons un graphique de dispersion des échantillons et une courbe d'ajustement :

Il est facile de voir que cela diffère considérablement du précédent algorithme. La raison en est que l'algorithme précédent utilise500 itérations calculées, le second n'a passé que100 itérations. Alors, le problème à expliquer ici est que les coefficients de régression tendent à converger avec l'augmentation du nombre d'itérations, et le processus de convergence est fluctuant. En d'autres termes, plus le nombre d'itérations est élevé, plus nous nous rapprochons de la valeur désirée, mais en raison de la non-linéarité des données d'échantillon, ce processus comporte également une certaine erreur. Les relations entre les coefficients de régression et le nombre d'itérations peuvent être consultées dans certains manuels, par exemple, la description dans 'Pratique de l'apprentissage automatique', ici sans explication détaillée.
Nous ne présentons ici que la manière d'améliorer notre algorithme afin que notre algorithme puisse converger rapidement et réduire les fluctuations. Voici la méthode :

À chaque itération, un point d'échantillon aléatoire est tiré pour calculer le vecteur de régression
La longueur d'étape itérative diminue constamment avec le nombre d'itérations, mais ne vaut jamais 0

Amélioration du code et impression de la courbe d'ajustement et du graphique des points d'échantillon :

def stocGradAscent1(dataMatrix, classLabels, numIter=150):
 m,n = shape(dataMatrix)
 weights = ones((n,1)) #initialiser à tous les uns
 for j in range(numIter):
  dataIndex = range(m)
  for i in range(m):
   alpha = 4/(1.0+j+i)+0.0001 #apha diminue avec l'itération, ne 
   randIndex = int(random.uniform(0,len(dataIndex)))#aller à 0 en raison de la constante
   h = sigmoid(sum(dataMatrix[randIndex]*weights))
   error = classLabels[randIndex] - h
   weights = weights + alpha * erreur * mat(dataMatrix[randIndex]).transpose()
   del(dataIndex[randIndex])
 return weights
if __name__=='__main__':
 dataMat,labelMat=loadDataSet()
 #weights=stocGradAscent0(dataMat,labelMat)
 weights=stocGradAscent1(dataMat,labelMat)
 #weights=gradAscent(dataMat,labelMat)
 #print 'dataMat:\n',dataMat
 #print 'labelMat:\n',labelMat
 #print 'Coefficients de régression :\n',weights
 plotBestFit(weights)
 #testClassify0()

Par défaut, c'est15Graphique de dispersion des échantillons et de la courbe d'ajustement après 0 itérations :

Il est facile de voir que l'exactitude est très proche de la première algorithmes !

V. Conclusion

L'algorithmes de régression logistique utilise principalement la fonction Sigmoid pour classer les données, la clé de l'exactitude de la classification dépend de la valeur du coefficient de régression calculée à partir de l'espace d'échantillons. Nous utilisons la méthode de montée en gradient pour calculer les coefficients de régression, et améliorons les performances de l'algorithme en utilisant la méthode de montée en gradient aléatoire.

Voici tous les contenus de cet article sur la description de l'algorithmes de régression logistique en machine learning du langage Python, j'espère que cela vous sera utile. Les amis intéressés peuvent continuer à consulter d'autres articles sur Python etAlgorithmesThèmes connexes, si vous trouvez des insuffisances, n'hésitez pas à laisser un message. Merci à nos amis de soutenir ce site !

Déclaration : Le contenu de cet article est extrait du réseau, propriété de l'auteur original, le contenu est apporté par les utilisateurs d'Internet de manière volontaire et auto-prise en charge, ce site Web ne possède pas de propriété, n'a pas été traité par l'éditeur humain et n'assume aucune responsabilité juridique. Si vous trouvez du contenu suspect de violation de copyright, vous êtes invité à envoyer un email à : notice#oldtoolbag.com (veuillez remplacer # par @ lors de l'envoi d'un email pour signaler une violation, et fournir des preuves pertinentes. Une fois vérifié, ce site supprimera immédiatement le contenu suspect de violation de droit d'auteur.)

Vous pourriez aussi aimer