English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Este artigo introduce o algoritmo de regressão logística em aprendizado de máquina, usamos esse algoritmo para classificar dados. A regressão logística é um algoritmo de aprendizado supervisionado que precisa aprender o espaço de amostra e é aplicável a dados numéricos e nominal, por exemplo, precisamos julgar se os dados pertencem a uma classificação ou não com base no tamanho dos valores de característica de entrada (numéricos).
1. Dados de exemplo
Neste exemplo, temos os seguintes dados de exemplo:
Os dados de exemplo têm3os valores de característica: X0X0, X1X1X2X2
Nós usamos isso3o valor de característica X1X1和X2X2Para determinar se os dados atendem aos requisitos, ou seja, os dados que atendem aos requisitos são1Os dados que não atendem aos requisitos são 0.
Os dados de exemplo de classificação são armazenados em um array.
Nós escrevemos a função a seguir no arquivo logRegres.py para preparar os dados e observá-los:
#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
Vamos observar este exemplo de conjunto de dados:
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]
A primeira coluna dos dados de amostra sampleMat, ou seja, nossos valores característicos X0X0, são todos1Neste problema, devemos prestar atenção à compreensão ao calcular os parâmetros de regressão. Todos os dados de amostra juntos10não, a classificação correspondente também é10nulos.
Então, nosso problema atual é:
Precisamos encontrar a relação entre os valores característicos no espaço amostral e o resultado de classificação. Designar uma função ou função que, após a entrada de um conjunto de valores característicos, classifique automaticamente os dados de entrada com base na relação entre os valores característicos e o resultado de classificação do espaço amostral, resultando em1ou 0.
II. Função Sigmoid
Para resolver o problema mencionado na seção anterior, apresentamos primeiro a função Sigmoid:
Essa função tem as seguintes características:
Quando z=0, o valor é 0.50.5
Quando z aumenta continuamente, o valor se aproxima de1
Quando z diminui continuamente, o valor se aproxima de 0
Vamos olhar para a curva da função:
Se introduzirmos o valor do espaço amostral3os valores característicos X0X0, X1X1和X2X2o valor é introduzido na função, calcula-se um resultado. Então, esse resultado será próximo do nosso resultado de classificação (0 a1um valor entre). Se esse resultado estiver próximo de 0, acreditamos que a classificação é 0, se o resultado estiver próximo de1Nós acreditamos que a classificação é1.
Como introduzir em função? Na verdade, é simplesmente adicionar, porque quando z aumenta ou diminui, o valor da função se aproxima de1ou 0. Fazemos z=x0+x1+x2z=x0+x1+x2
Mas na verdade, nossa estimativa e o valor real de classificação podem ter erros, até ser completamente incorretos. Para corrigir esse problema, para o espaço amostral3os valores característicos X0X0, X1X1和X2X2, defina um coeficiente de regressão w0w0, w1w1e w2w2, para diminuir essa erro.+w1x1+w2x2
Na verdade, não é difícil imaginar que o valor desses coeficientes de regressão w determina a precisão, até a correção, de nossos resultados de cálculo. Isso significa que esses valores de w refletem as regras de classificação do espaço amostral.
Então, ao introduzir dados além de um conjunto de amostras de entrada, com os coeficientes de regressão w corretos, podemos obter resultados de classificação mais próximos das regras de classificação do espaço amostral.
Outra questão surge, como obtermos esse conjunto de coeficientes de regressão w?
III. Método de ascensão da derivada
O método de ascensão da derivada é iterar continuamente na direção da derivada da função para calcular os valores dos parâmetros, a fim de encontrar o valor máximo dos parâmetros. A fórmula de iteração é a seguinte:
Entre eles, αα é o passo, Δσ(w)Δσ(w) é a derivada da função σ(w)σ(w). Para a derivação da derivada, consulteAqui. A capacidade matemática do autor é limitada, então não há explicação.
Por fim, podemos obter a fórmula de cálculo da derivada:
Então, a fórmula de iteração é a seguinte:
Explicação da fórmula:
wk+1wk+1é o resultado do coeficiente de regressão do item de característica XX na iteração atual
wkwk é o resultado do coeficiente de regressão do item de característica XX na iteração anterior
αα é o comprimento do passo em direção ao gradiente em cada iteração
xixi é o i-ésimo elemento do item de característica XX
yiyi é o resultado de classificação do registro i da amostra
σ(xi,wk)σ(xi,wk) é o valor de resultado de classificação do registro i da amostra, calculado usando a função sigmoid e wkwk como coeficiente de regressão.
[yi−σ(xi,wk)][yi−σ(xi,wk)] é o valor de resultado de classificação correspondente ao registro i da amostra, e o erro do valor de resultado de classificação calculado usando a função sigmoid com wkwk como coeficiente de regressão.
Agora que temos a fórmula para calcular os coeficientes de regressão, vamos implementar uma função no arquivo logRegres.py para calcular os coeficientes de regressão do espaço amostral e imprimir nossos resultados:
def gradAscent(dataMatIn, classLabels): dataMatrix = mat(dataMatIn) #100 linha3Coluna #print dataMatrix labelMat = mat(classLabels).transpose() #100 linha1Coluna #print 'labelMat:\n',labelMat print 'labelMat forma: rowNum=',shape(labelMat)[0],'colNum=',shape(labelMat)[1] rowNum,colNum = shape(dataMatrix) alpha = 0.001 maxCycles = 500 weights = ones((colNum,1)) #3Linha1Coluna #print shape(dataMatrix) #print shape(weights) #print shape(labelMat) for k in range(maxCycles): #intensamente focado em operações matriciais h = sigmoid(dataMatrix*weights) #100 linha1Coluna #print h error = (labelMat - h) #subtração vetorial weights = weights + alpha * dataMatrix.transpose()* error #3Linha1Coluna 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 regressão: [[ 4.12414349] [ 0.48007329] [-0.6168482 ]]
Para verificar a precisão do coeficiente de revisão calculado, observamos o gráfico de dispersão do espaço amostral e a curva de ajuste dos coeficientes de regressão. Utilizamos 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 'Cálculo:',v,' Valor original',test_label[i] print 'Taxa de erro:',errCnt/trow if __name__=='__main__': #dataMat,labelMat=loadDataSet() #weights=gradAscent(dataMat,labelMat) ##print 'dataMat:\n',dataMat ##print 'labelMat:\n',labelMat #print 'Coeficientes de regressão:\n',weights #plotBestFit(weights) testClassify0()
A implementação do classificador é simples. Usamos os dados de amostra anteriores70 dados como nossos dados de amostra de teste, calculamos o coeficiente de regressão. Em seguida, usamos o classificador para os restantes30 registros para classificação, em seguida, comparar os resultados com os dados de amostra. Finalmente, imprime a taxa de erro. Podemos ver que a taxa de erro é 0, quase perfeita! Podemos modificar a proporção do espaço de amostra do exemplo de teste para testar várias vezes. Portanto, a conclusão é que a precisão do nosso algoritmo é bastante boa!
Então, o problema está resolvido até aqui? Parece que falta um pouco mais. Vamos estudar em detalhes o nosso método de cálculo do coeficiente de regressão e podemos notar que, durante esse processo, usamos a matriz composta pelos dados de amostra para a multiplicação de matrizes. Isso significa que, para calcular o coeficiente de regressão, percorremos todo o conjunto de dados de amostra.
O nosso problema voltou, os dados de amostra do nosso exemplo apenas têm100 registros, se tratarmos de milhares de dados de amostra, a complexidade de cálculo da função de coeficiente de regressão aumentará linearmente. Vamos ver como otimizar esse algoritmo.
Quarto, otimização do algoritmo de ascensão do gradiente - método de gradiente estocástico
após entendermos a fórmula de iteração do coeficiente de regressão
e após a implementação do nosso programa. Vamos melhorar o método de cálculo dos coeficientes de regressão da seguinte forma:
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 regressão:\n',weights plotBestFit(weights) #testClassify0()
Padrão é15Gráfico de dispersão de amostras e curva de ajuste de 0 iterações:
Não é difícil ver que a precisão está muito próxima do primeiro algoritmo!
V. Resumo
O algoritmo de regressão logística utiliza principalmente a função Sigmoid para classificar dados, e a precisão da classificação depende crucialmente dos coeficientes de regressão calculados a partir do espaço de amostra. Usamos o método de ascensão do gradiente para calcular os coeficientes de regressão e melhoramos o desempenho do algoritmo usando o método de ascensão do gradiente aleatório.
Isso é tudo sobre a descrição do algoritmo de regressão logística do idioma Python neste artigo. Espero que ajude a todos. Os amigos interessados podem continuar a consultar outros artigos de Python eAlgoritmosTópicos relacionados, se houver pontos fracos, bem-vindo a deixar um comentário. Agradecemos o apoio dos amigos ao site!
Declaração: O conteúdo deste artigo é extraído da Internet, pertence ao autor original, fornecido pelos usuários da Internet de forma voluntária e auto-publicado. O site não possui direitos autorais, não foi editado manualmente e não assume responsabilidade por eventuais responsabilidades legais. Se você encontrar conteúdo suspeito de violação de direitos autorais, por favor, envie um e-mail para: notice#oldtoolbag.com (ao enviar e-mail, substitua # por @ para denunciar e forneça provas relevantes. Apenas após verificação, o site deletará o conteúdo suspeito de violação de direitos autorais.)