English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Este artículo introduce el algoritmo de regresión logística en el aprendizaje automático, usamos este algoritmo para clasificar los datos. El algoritmo de regresión logística es un algoritmo de aprendizaje supervisado que necesita aprender el espacio de muestra y es adecuado para datos numéricos y de tipo nominal, por ejemplo, necesitamos juzgar si los datos pertenecen a alguna clase o no según el tamaño de los valores característicos (numéricos) de los datos de entrada.
Primero, datos de muestra
En nuestro ejemplo, tenemos los siguientes datos de muestra:
Los datos de muestra tienen3Los valores de característica: X0X0, X1X1X2X2
A través de esto3El valor de característica X en los1X1和X2X2Para determinar si los datos cumplen con los requisitos, es decir, los que cumplen con los requisitos son1Los datos que no cumplen con los requisitos son 0.
Los datos de muestra de clasificación se almacenan en un array.
En el archivo logRegres.py escribimos la siguiente función para preparar los datos y observamos los datos impresos:
#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
Observemos este ejemplo de conjunto de datos:
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]
El primer columna de los datos de muestra dataMat, es decir, nuestras características X0, son todas1Este problema debemos entender con atención al calcular los parámetros de regresión. Todos los datos de muestra en total10Cero, las clasificaciones correspondientes también son10Cero.
Entonces, nuestro problema actual es:
Necesitamos encontrar la relación entre los valores de características en el espacio de muestras y los resultados de clasificación. Diseñamos una función o funcionalidad que, después de ingresar un conjunto de valores de características, pueda clasificar automáticamente los datos de entrada según la relación entre los valores de características del espacio de muestras y los resultados de clasificación, es decir, obtener un resultado que sea1O bien 0.
Segundo, función Sigmoid
Para resolver el problema mencionado en el capítulo anterior, aquí presentamos primero la función Sigmoid:
Esta función tiene las siguientes características:
Cuando z = 0, el valor es 0.50.5
Cuando z aumenta continuamente, el valor se acercará a1
Cuando z disminuye continuamente, el valor se acercará a 0
Veamos la gráfica de la curva de la función:
Si introducimos el valor del espacio de muestras3unos valores de características X0, X1X1和X2X2Se introduce el valor en la función y se calcula un resultado. Entonces, este resultado será cercano a nuestro resultado de clasificación (entre 0 y1Un valor entre). Si este resultado se acerca a 0, creemos que se clasifica como 0, si el resultado se acerca a1Entonces, creemos que se clasifica como1.
¿De qué manera se introduce en la función? En realidad, es suficiente sumar, porque cuando z aumenta o disminuye, el valor de la función se acerca a1o 0. Hacemos que z = x0+x1+x2z = x0+x1+x2
Pero en la práctica, nuestros resultados de cálculo y los valores de clasificación reales pueden tener errores, e incluso ser completamente incorrectos. Para corregir este problema, para el espacio de muestras3unos valores de características X0, X1X1和X2X2, definamos un coeficiente de regresión w0 y w1w1y w2w2, para reducir este error. Incluso si z = w0x0+w1x1+w2x2
En realidad, no es difícil imaginar que el valor de este grupo de coeficientes de regresión w determina la precisión de nuestros resultados de cálculo, e incluso su exactitud. Es decir, este grupo de valores w refleja las reglas de clasificación del espacio de muestras.
Entonces, cuando introducimos datos adicionales a un conjunto de muestras, con los coeficientes de regresión w correctos, podemos obtener resultados de clasificación más cercanos a las reglas de clasificación del espacio de muestras.
Otra vez, ¿cómo podemos obtener este grupo de coeficientes de regresión w?
Tercero, método de ascenso de gradiente
El método de ascenso de gradiente es iterar continuamente en la dirección de la gradiente de la función para calcular los valores de los parámetros, con el fin de encontrar el valor máximo de los parámetros. La fórmula de iteración es la siguiente:
Donde, α es el paso, Δσ(w) es la gradiente de la función σ(w). Para la derivación de la gradiente, consulteAquí. La capacidad matemática del autor es limitada, por lo que no se proporciona explicación.
Finalmente, podemos obtener la fórmula de cálculo de la gradiente:
Entonces, la fórmula de iteración es la siguiente:
Explicación de la fórmula:
wk+1wk+1es el resultado del coeficiente de regresión del item de características XX en esta iteración.
wkwk es el resultado del coeficiente de regresión del item de características XX en la última iteración.
αα es el paso de desplazamiento en la dirección de la梯度 en cada iteración.
xixi es el elemento i del item de características XX.
yiyi es el resultado de clasificación del registro i de la muestra.
σ(xi,wk)σ(xi,wk) es el valor de resultado de clasificación del registro i de la muestra, calculado utilizando la función sigmoid y wkwk como coeficiente de regresión.
[yi−σ(xi,wk)][yi−σ(xi,wk)] es el valor de resultado de clasificación correspondiente al registro i de la muestra, y el valor de error del resultado de clasificación calculado con la función sigmoid utilizando wkwk como coeficiente de regresión.
Ahora que tenemos la fórmula para calcular los coeficientes de regresión, implementamos una función en el archivo logRegres.py para calcular los coeficientes de regresión del espacio de muestras y mostrar nuestros resultados:
def gradAscent(dataMatIn, classLabels): dataMatrix = mat(dataMatIn) #100 filas3Columnas #print dataMatrix labelMat = mat(classLabels).transpose() #100 filas1Columnas #print 'labelMat:\n',labelMat print 'La forma de labelMat: rowNum=',shape(labelMat)[0],'colNum=',shape(labelMat)[1] rowNum,colNum = shape(dataMatrix) alpha = 0.001 maxCycles = 500 weights = ones((colNum,1)) #3Filas1Columnas #print shape(dataMatrix) #print shape(weights) #print shape(labelMat) for k in range(maxCycles): #pesado en operaciones de matrices h = sigmoid(dataMatrix*weights) #100 filas1Columnas #print h error = (labelMat - h) #resta vectorial weights = weights + alpha * dataMatrix.transpose()* error #3Filas1Columnas return weights if __name__=='__main__': dataMat,labelMat=loadDataSet() #weights=gradAscent(dataMat,labelMat) #print 'dataMat:\n',dataMat #print 'labelMat:\n',labelMat print weights
Imprimir resultados:
Coeficientes de regresión: [[ 4.12414349] [ 0.48007329] [-0.6168482 ]]
Para verificar la precisión de los coeficientes de revisión calculados, observemos el gráfico de dispersión del espacio de muestras y la curva de ajuste de los coeficientes de regresión. Usamos 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 'Valor calculado:',v,' Valor original',test_label[i] print 'Tasa de error:',errCnt/trow if __name__=='__main__': #dataMat,labelMat=loadDataSet() #weights=gradAscent(dataMat,labelMat) ##print 'dataMat:\n',dataMat ##print 'labelMat:\n',labelMat #print 'Coeficientes de regresión:\n',weights #plotBestFit(weights) testClassify0()
La implementación del clasificador es simple. Usamos los datos de muestra anteriores70 datos como nuestros datos de muestra para calcular los coeficientes de regresión. Luego, utilizamos el clasificador para los30 registros para clasificar, luego comparar los resultados con los datos de muestra. Finalmente, imprime la tasa de error. Podemos ver que la tasa de error es 0, prácticamente perfecto! Podemos modificar la proporción de los datos de muestra en el espacio original para probar varias veces. Entonces, la conclusión es que la precisión de nuestro algoritmo es bastante buena!
Entonces, ¿se resolvió el problema aquí? Parece que falta algo. Vamos a estudiar a fondo nuestro método de cálculo de coeficientes de regresión y descubriremos que en este proceso utilizamos la matriz compuesta de datos de muestra para realizar multiplicación de matrices. Es decir, para calcular los coeficientes de regresión, recorrimos toda la información de los datos de muestra.
Nuestro problema vuelve a aparecer, los datos de muestra en nuestro ejemplo solo tienen100 registros, si se procesan miles de datos de muestra, la complejidad de cálculo de la función de coeficientes de regresión aumentará directamente. Vamos a ver cómo optimizar este algoritmo.
Cuatro, optimización del algoritmo de ascenso de gradiente - método de gradiente ascendente aleatorio
Una vez que entendimos la fórmula de iteración del cálculo de los coeficientes de regresión
y después de nuestro programa implementado. Vamos a mejorar el método de cálculo de los coeficientes de regresión de la siguiente manera:
def stocGradAscent0(dataMatrix, classLabels): m,n = shape(dataMatrix) alpha = 0.01 weights = ones((n,1)) #initialize to all ones for i in range(m): h = sigmoid(sum(dataMatrix[i]*weights)) error = classLabels[i] - h weights = weights + alpha * error * mat(dataMatrix[i]).transpose() return weights
每一次迭代计算回归系数时,只使用样本空间中的一个样本点来计算。我们通过程序生成一个样本散点和拟合曲线的图来看一下这个算法的准确程度:
不难看出跟之前的算法相差还是比较大的。原因是之前的算法是通过500次迭代算出的结果,后者只经过了100次迭代。那么这里要说明的问题是,回归系数在随着迭代次数的增加是趋于收敛的,并且收敛的过程是存在波动的。说白了,就是迭代的次数越多,越接近我们想要的那个值,但是由于样本的数据是非线性的,这个过程也会有一定的误差。具体的回归系数和迭代次数的关系大家可以参考一些教材,例如《机器学习实战》中的描述,这里就不做详细介绍了。
我们这里只介绍一下如何改进我们的算法,使我们的算法能够快速的收敛并减小波动。方法如下:
每次迭代随机的抽取一个样本点来计算回归向量
迭代的步长随着迭代次数增大而不断减少,但是永远不等于0
改进代码,并打印出拟合曲线和样本散点图:
def stocGradAscent1(dataMatrix, classLabels, numIter=150): m,n = shape(dataMatrix) weights = ones((n,1)) #initialize to all ones for j in range(numIter): dataIndex = range(m) for i in range(m): alpha = 4/(1.0+j+i)+0.0001 #apha decreases with iteration, does not randIndex = int(random.uniform(0,len(dataIndex)))#go to 0 because of the constant h = sigmoid(sum(dataMatrix[randIndex]*weights)) error = classLabels[randIndex] - h weights = weights + alpha * error * 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 'Coeficientes de regresión:\n',weights plotBestFit(weights) #testClassify0()
Por defecto es15Gráficos de dispersión de muestras y curvas de ajuste de 0 iteraciones:
No es difícil ver que la precisión está muy cerca del primer algoritmo!
V. Resumen
El algoritmo de regresión logística principalmente utiliza la función Sigmoid para clasificar datos, la precisión de la clasificación depende de los coeficientes de regresión calculados en el espacio de muestras. Utilizamos el método de ascenso de gradiente para calcular los coeficientes de regresión y mejoramos el rendimiento del algoritmo mediante el método de ascenso de gradiente aleatorio.
Esto es todo el contenido del artículo sobre la descripción del algoritmo de regresión logística de Python para el aprendizaje automático, esperamos que sea útil para todos. Los amigos interesados pueden continuar consultando otros artículos de Python yAlgoritmosTemas relacionados, si hay deficiencias, bienvenidos los comentarios. Agradecemos el apoyo de los amigos a este sitio!
Declaración: El contenido de este artículo se obtiene de la red, pertenece a los propietarios originales, el contenido se contribuye y carga de manera autónoma por los usuarios de Internet, este sitio web no posee los derechos de propiedad, no se ha realizado una edición humana y no asume ninguna responsabilidad legal relacionada. Si encuentra contenido sospechoso de infracción de derechos de autor, bienvenido sea el envío de un correo electrónico a: notice#oldtoolbag.com (al enviar un correo electrónico, reemplace # con @ para denunciar, y proporcione evidencia relevante. Si se encuentra contenido sospechoso de infracción de derechos de autor, bienvenida es la comunicación por correo electrónico a: notice#w)