ITS's Dev Story

오늘은 로지스틱 회귀를 이용한 말의 배앓이 치사율 평가를 위한 로지스틱 회귀를 사용하는 예제를 풀어 보기로 하였다. 우선, 데이터에서 누락된 값이 있기 때문에 이를 다루는 효과적인 방법들이 필요하게 된다. 이에는 몇 가지 선택사항이 있다. 선택사항은 아래와 같다.

-------------------------------------------------------------------------------------------

* Numpy 기계학습의 모든 문서는 제가 머신러닝을 공부하고, 제 프로젝트에 필요한 알고리즘을 찾기 위해 정리하는 일종의 '요점정리 노트' 입니다. 혹여나 오해 없으시기 바랍니다. (2016.03.14 추가)

-------------------------------------------------------------------------------------------

* 사용 가능한 모든 데이터에서 속성의 평균값 사용

* 알려지지 않은 값은 특별한 값으로 채우기

* 혹은 무시

* 유사한 아이템들의 평균값 사용

* 값을 예측하기 위한 기계학습 알고리즘 사용

이 경우, 사용하게 될 데이터 집합은 전처리가 된것이다. 따라서 기존의 알고리즘으로 쉽게 사용할 수 있다는 장점이 있다. 내가 사용하는 로지스틱 회귀 분류 함수 소스코드는 아래와 같다.


def classifyVector(inX, weights):
    prob = sigmoid(sum(inX*weights))
    if prob > 0.5: return 1.0
    else: return 0.0

def colicTest():
    frTrain = open('horseColicTraining.txt'); frTest = open('horseColicTest.txt')
    trainingSet = []; trainingLabels = []
    for line in frTrain.readlines():
        currLine = line.strip().split('\t')
        lineArr =[]
        for i in range(21):
            lineArr.append(float(currLine[i]))
        trainingSet.append(lineArr)
        trainingLabels.append(float(currLine[21]))
    trainWeights = stocGradAscent1(array(trainingSet), trainingLabels, 1000)
    errorCount = 0; numTestVec = 0.0
    for line in frTest.readlines():
        numTestVec += 1.0
        currLine = line.strip().split('\t')
        lineArr =[]
        for i in range(21):
            lineArr.append(float(currLine[i]))
        if int(classifyVector(array(lineArr), trainWeights))!= int(currLine[21]):
            errorCount += 1
    errorRate = (float(errorCount)/numTestVec)
    print "the error rate of this test is: %f" % errorRate
    return errorRate

def multiTest():
    numTests = 10; errorSum=0.0
    for k in range(numTests):
        errorSum += colicTest()
    print "after %d iterations the average error rate is: %f" % (numTests, errorSum/float(numTests))
 

그 다음, 파이썬 쉘에 아래와 같이 입력한다.

내가 사용하는 데이터 값은 아래와 같다.

누락된 값은 아래와 같이 0.35가 나왔다.

이는 누락된 값이 30% 이상이므로 나쁘지 않은 결과이다. colicTest() 함수에서 반복 횟수를 변경할 수 있고, 오류율 20%에 근접하기 위해 stochGradAscent1()에서 alpha의 크기를 변경할 수 있다.

오늘은 여기까지 하기로 했다.

오늘은 머신러닝 중 최적화 알고리즘, 로지스틱 회귀에 대해 탐구해 보기로 하였다. 가장 빠른 시간에 A에서 B로 가기 위해서는 가장 빨리 갈 수 있는 길을 컴퓨터가 찾아야 할 것이다. 이러한 것을 처리할 수 있는 가장 효과적인 방법이 바로 최적화 알고리즘이다.

-------------------------------------------------------------------------------------------

* Numpy 기계학습의 모든 문서는 제가 머신러닝을 공부하고, 제 프로젝트에 필요한 알고리즘을 찾기 위해 정리하는 일종의 '요점정리 노트' 입니다. 혹여나 오해 없으시기 바랍니다. (2016.03.14 추가)

-------------------------------------------------------------------------------------------

중학교 1학년 수학에서 처음으로 좌표평면을 이용한 함수를 배우게 되는데, 이도 이 알고리즘과 연관이 있다. 데이터가 표시된 좌표평면을 가로지르는 선을 최적선이라고 하고, 이 선을 그리는 것을 회귀라고 한다고 한다. 우선 나는 로지스틱 회귀 모델을 사용해서 기울기 상승 최적화 함수를 탐구해 보기로 하였다. 소스코드는 아래와 같다.

 

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[0]), float(lineArr[1])])
        labelMat.append(int(lineArr[2]))
    return dataMat,labelMat

def sigmoid(inX):
    return 1.0/(1+exp(-inX))

def gradAscent(dataMatIn, classLabels):
    dataMatrix = mat(dataMatIn)             
    labelMat = mat(classLabels).transpose() 
    m,n = shape(dataMatrix)
    alpha = 0.001
    maxCycles = 500
    weights = ones((n,1))
    for k in range(maxCycles):              
        h = sigmoid(dataMatrix*weights)     
        error = (labelMat - h)             
        weights = weights + alpha * dataMatrix.transpose()* error #matrix mult
    return weights


이후 매스플롯라이브러리를 사용해서 직접 풀룻하는 코드이다. 소스코드는 아래와 같다.

 
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]
    ax.plot(x, y)
    plt.xlabel('X1'); plt.ylabel('X2');
    plt.show()


▲ Python Shell Code

▲ 플롯으로 출력한 모습

오늘은 여기까지 하기로 했다.


오늘은 Coursera에서 Exploratory Data Analysis를 수료하였다.

이 수업은 Coursera의 특색, 동료 평가 (Peer Evaluation)의 특징을 제대로 살려, 정확한 데이터를 추출할 수 있도록 가이드를 제시해 주는 수업이었다. 조금 자랑이긴 하지만 나는 이 두 평가에서 만점을 맞았고, 개인적으로 굉장히 실력이 늘고 발전했다는 생각이 든다. 지금까지 해본 코세라 수업 중에는 동료 평가가 가장 부각된 수업이었다.

코세라의 전체적인 수업 형태를 보면 과제를 의무적으로 Github로 제출하도록 하여 소셜 코딩을 스스로 입문할 수 있도록 돕고, Codeskulptor와 R 등의 신형 기술을 빨리 접해볼 수 있는 기회 (한국 기준)를 많이 준다. 현재 미국의 여러 스타트업들에서는 이러한 기술을 사용할 줄 아는 능력을 굉장히 중요시 평가하고 있고, 이력서에 있는 학력 란에 자신이 취득한 Coursera 수료증을 기입할 수 있도록 하였다.

내가 지금까지 취득한 인증 수료증 (이력이나 학력으로 인정되는)은 아래와 같다. 수료증에 의미를 두고 공부한 것이 아니여서 모두 인증 수료증을 받진 않았는데 그 부분이 좀 아쉽다. 원래 인증 수료증을 취득하려면 미화로 49달러를 내야 한다. 하지만 나는 학생의 신분에서 49달러를 매 강좌마다 지불하기에는 너무 벅차다.

지금까지 취득한 모든 수료증 (인증 수료증 포함) 은 아래와 같다.

1년 전부터 시작해 지금까지 총 10개의 수료증을 취득하였다. 어려운 강좌는 중간에 재수강을 해서 수료증을 시간대비 많이 취득하지는 못했다. 하지만 점수는 거의 모두 90점대 이상이다.

나는 훌륭한 교육의 기회는 모두에게 균등하게 주어져야 한다고 생각한다. 내가 사설학원에 다니지 않으면서 그 시간에 Coursera를 듣는 이유이기도 하다.