English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
본문
이 글은 기계 학습에서의 로지스틱 회귀 알고리즘을 소개합니다. 우리는 이 알고리즘을 데이터를 분류하는 데 사용합니다. 로지스틱 회귀 알고리즘은 샘플 공간을 통해 학습이 필요한 감독 학습 알고리즘으로, 수치型和 nominal type 데이터에 적용됩니다. 예를 들어, 입력 데이터의 특징 값(수치형)의 크기에 따라 데이터가 어떤 분류에 해당하는지 여부를 판단해야 합니다.
1. 샘플 데이터
샘플 데이터는 다음과 같습니다:3개의 특징 값: X0X0, X1X1X2X2
우리는 이를 통해3개의 특징 값 중의 X1X1와 X2X2데이터가 요구사항을 충족하는지 판단하려면, 요구사항을 충족하는 것은1요구사항에 맞지 않는 것은 0입니다.
샘플 데이터는 배열에 저장되어 있습니다
logRegres.py 파일에서 이렇게 함수를 작성하여 데이터를 준비하고, 데이터를 출력하여 관찰해 보겠습니다:
#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
우리가 이 데이터 샘플을 관찰해 보겠습니다:
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]
샘플 데이터 dataMat의 첫 번째 열, 즉 우리의 특징 값 X0X0는 모두1이 문제는 계산 회귀 파라미터를 계산할 때 주의해야 할 점입니다. 모든 샘플 데이터는 총100개, 이에 대한 분류 결과도100개.
그렇다면, 지금 우리의 문제는 다음과 같습니다:
샘플 공간의 특징 값과 분류 결과 간의 관계를 찾아야 합니다. 함수나 기능을 설계하여 입력된 특징 값에 대해 샘플 공간의 특징 값과 분류 결과 간의 관계를 바탕으로 자동으로 입력 데이터를 분류할 수 있도록 합니다. 결과는 0 또는10 또는 1입니다.
2. Sigmoid 함수
이전 장에서 언급한 문제를 해결하기 위해, 우리는 여기서 먼저 Sigmoid 함수를 소개합니다:
이 함수는 다음과 같은 몇 가지 특징이 있습니다:
z=0z=0일 때, 값이 0입니다.50.5
z가 지속적으로 증가하면, 값이1
z가 지속적으로 감소하면, 값이 0에 접근합니다
함수의 곡선도를 보여드리겠습니다:
를 샘플 공간의3각 특징 값 X0X0, X1X1와 X2X2의 값代入하여 함수에代入하여 계산한 결과는 우리의 분류 결과에 가까울 것입니다. 그렇다면 이 결과는 0에서1이 값 중 하나를 함수에代入하여 계산한 결과는 우리의 분류 결과에 가까울 것입니다. 그렇다면 이 결과는 0에서1그렇다면, 우리는 분류를1입니다.
함수에 어떻게代入하든지? 그렇다면 간단히 더하면 됩니다. 因為zz가 지속적으로 증가하거나 감소하면, 함수의 값도相应的趋近于1또는 0. z=x0+x1+x2z=x0+x1+x2
하지만 실제로는 계산 결과와 실제 분류 값 사이에 오차가 있으며, 심지어 완전히 잘못된 것도 있습니다. 이 문제를 수정하기 위해, 우리는 샘플 공간의3각 특징 값 X0X0, X1X1와 X2X2를 사용하여, w0w0, w1w1와 w2w2그렇게 하여 이 오차를 줄입니다. z=w0x0+w1x1+w2x2
실제로는 생각하기 어렵지 않습니다. 이 그룹 w 회귀 계수의 값은 우리의 계산 결과의 정확성을 결정하며, 심지어는 정확성을 결정합니다.也就是说, 이 그룹 w의 값은 샘플 공간 분류 규칙을 반영합니다.
그렇다면, 입력 데이터 외의 데이터를 입력할 때, 올바른 w 회귀 계수와 함께 사용하면 샘플 공간 분류 규칙에 가까운 분류 결과를 얻을 수 있습니다.
문제가 다시 생겼습니다. 그렇다면 이러한 w 회귀 계수를 어떻게 얻을 수 있을까요?
3. 경사 상승 방법
경사 상승 방법은 함수의 경사 방향에서 반복적으로 계산하여 파라미터 값을 찾기 위해 사용됩니다. 반복 계산 공식은 다음과 같습니다:
α는 단계, Δσ(w)는 σ(w) 함수의 경사입니다. 경사의 유도에 대한 내용은 참고하십시오여기서저의 수학 능력이 제한적이므로 설명하지 않겠습니다.
마지막으로, 경사의 계산 공식을 얻을 수 있습니다:
그렇다면, 반복 계산 공식은 다음과 같습니다:
공식 설명:
wk+1wk+1는 이번 반복의 XX 특성 항목의 회귀 계수 결과입니다
wkwk는 이전 반복의 XX 특성 항목의 회귀 계수 결과입니다
αα는 각 반복에서 경사 방향으로 이동하는 단계입니다
xixi는 XX 특성 항목 중 i번째 요소입니다
yiyi는 샘플의 i번째 기록의 분류 샘플 결과 값입니다
σ(xi,wk)σ(xi,wk)는 샘플의 i번째 기록을 사용하여 sigmoid 함수와 wkwk를 회귀 계수로 계산한 분류 결과 값입니다
[yi−σ(xi,wk)][yi−σ(xi,wk)]는 샘플의 i번째 기록에 대한 분류 결과 값이며, sigmoid 함수를 사용하여 wkwk를 회귀 계수로 계산한 분류 결과 값과의 오차 값입니다.
지금, 회귀 계수 계산 방정식을 가지고 있으므로, logRegres.py 파일에서 함수를 구현하여 샘플 공간의 회귀 계수를 계산하고 결과를 출력하겠습니다:
def gradAscent(dataMatIn, classLabels): dataMatrix = mat(dataMatIn) #100행3열 #print dataMatrix labelMat = mat(classLabels).transpose() #100행1열 #print 'labelMat:\n',labelMat print 'labelMat의 형상:rowNum=',shape(labelMat)[0],'colNum=',shape(labelMat)[1] rowNum,colNum = shape(dataMatrix) alpha = 0.001 maxCycles = 500 weights = ones((colNum,1)) #3행1열 #print shape(dataMatrix) #print shape(weights) #print shape(labelMat) for k in range(maxCycles): #마트릭스 연산에 중점 h = sigmoid(dataMatrix*weights) #100행1열 #print h error = (labelMat - h) #벡터 연산 weights = weights + alpha * dataMatrix.transpose()* 에러 번호3행1열 return weights if __name__=='__main__': dataMat,labelMat=loadDataSet() #weights=gradAscent(dataMat,labelMat) #print 'dataMat:\n',dataMat #print 'labelMat:\n',labelMat print weights
출력 결과:
회귀 계수: [[ 4.12414349] [ 0.48007329] [-0.6168482 ]]
우리가 계산한 회귀 계수의 정확성을 검증하기 위해, 샘플 공간의 산점도와 회귀 계수의 적합곡선을 확인해 보겠습니다. 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 '계산 값:',v,' 원值',test_label[i] print '오류율:',errCnt/trow if __name__=='__main__': #dataMat,labelMat=loadDataSet() #weights=gradAscent(dataMat,labelMat) ##print 'dataMat:\n',dataMat ##print 'labelMat:\n',labelMat #print '회귀 계수:\n',weights #plotBestFit(weights) testClassify0()
분류기의 구현은 매우 간단합니다. 우리는 이전 샘플 데이터에서 사용한70개의 데이터를 테스트 샘플 데이터로 사용하여 회귀 계수를 계산합니다. 그런 다음, 나머지30개의 데이터를 분류하고, 그 결과를 샘플 데이터와 대조한 후, 오류율을 출력합니다. 오류율이 0으로, 거의 완벽한 것처럼 보입니다. 테스트 샘플 데이터를 원래 샘플 공간 비율을 수정하여 여러 번 테스트할 수 있습니다. 그렇다면, 우리의 알고리즘의 정확률은 꽤 좋습니다!
그래서 여기까지 문제가 해결되었습니까? 아직도 조금 더 남았어 보입니다. 우리가 회귀 계수를 계산하는 방법을 자세히 연구해보면, 이 과정에서 샘플 데이터로 구성된 행렬을 행렬 곱셈을 사용했음을 발견할 수 있습니다. 즉, 회귀 계수를 계산하기 위해 전체 샘플 데이터를 순회했습니다.
우리의 문제는 여전히 있습니다. 우리의 예제에서의 샘플 데이터는 단지100개의 데이터를 처리할 때는, 만약 수천 개나 만개의 샘플 데이터를 처리할 때, 우리의 회귀 계수 계산 함수의 계산 복잡도는 직선으로 상승합니다. 이제 이 알고리즘을 어떻게 최적화할 수 있는지 보让我们来看看如何优化这个算法。
4. 그래디언트 상승 알고리즘 최적화 - 무작위 그래디언트 상승법
회귀 계수 반복 계산 방정식을 이해한 후에.
우리가 구현한 프로그램 이후로. 우리는 회귀 계수 계산 방법을 다음과 같이 개선하였습니다:
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 * 에러 * 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 #alpha 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 * 에러 * 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 '회귀 계수:\n',weights plotBestFit(weights) #testClassify0()
기본적으로는150 반복의 샘플 산점도와 맞춤선도:
정확도는 첫 번째 알고리즘과 매우 가깝습니다!
5. 요약
로지스틱 회귀 알고리즘은 주로 Sigmoid 함수를 사용하여 데이터를 분류하며, 분류의 정확도는 샘플 공간에서 계산된 회귀 계수에 달려 있습니다. 회귀 계수를 계산하기 위해 그레이디언트 상승법을 사용하며, 알고리즘의 성능을 개선하기 위해 무작위 그레이디언트 상승법을 적용했습니다.
이것이 모두입니다. 이 문서에서 Python 언어가 설명한 로지스틱 회귀 알고리즘에 대한 내용입니다. 여러분에게 도움이 되길 바랍니다. 관심이 있는 분은 이 사이트의 다른 Python과알고리즘관련 주제, 부족한 점이 있으면, 댓글을 남겨 주시기 바랍니다. 친구들에게 이 사이트의 지지를 감사합니다!
선언: 이 문서의 내용은 인터넷에서 가져왔으며, 저작권자는 모두에게 있으며, 인터넷 사용자가 자발적으로 기여하고 자체적으로 업로드한 내용으로, 이 사이트는 소유권을 가지지 않으며, 인공적으로 편집된 처리가 없으며, 관련 법적 책임도 부담하지 않습니다. 저작권 위반 내용을 발견하시면, notice#w로 이메일을 보내 주시기 바랍니다.3codebox.com(이메일을 보내면, #을 @으로 변경하십시오.)를 통해 신고하시고 관련 증거를 제공하시면, 사실이 확인되면 이 사이트는 즉시 위반된 내용을 제거합니다.