Clojure로 짜본 weka API 활용 예제

Weka APIClojure를 활용 남자인지 여자인지 맞추는 프로그램을 짜보았다.
Weka API와 Clojure 모두 아직 익숙치 않다는 점 염두에 보시길 바란다. ^^;

일단 아래와 같이 학습셋이 주어져 있다.

나이, 성별, 로그인 횟수
40   , 남자,      10
20   , 여자,      13
10   , 여자,      15
30   , 남자,      9
20   , 남자,      8
60   , 여자.      2

이 학습셋을 기반으로 아래의 예제를 예측해 보도록 하겠다.

나이 34, 로그인 횟수 4번 인 사람이 여자일까 남자일까?

나이 7, 로그인 횟수 20번인 사람이 여자일까 남자일까?

데이터를 규칙성 있게 만들어 보고 싶었지만 뭐 이걸 자기 자신이 한번 예측해 보고 ML결과로 나온 것이 어떻게 나오는지 확인해 보는것도 꽤 재미있을듯 하다.

일단 코드를 보자.

[CODE vb]
(ns weka_example)

(import ‘(weka.classifiers Classifier Evaluation))
(import ‘(weka.classifiers.functions MultilayerPerceptron))
(import ‘(weka.core Attribute FastVector Instance Instances))

;set attributes
(defn createAttributes []
    (let [genderAttv
        (let [tmpvec (new FastVector 2)] (. tmpvec (addElement “male”) )
            (. tmpvec (addElement “female”))
            tmpvec
        )    
        ageAttr  (new Attribute “age”)
        gendAttr (new Attribute “gender” genderAttv)
        numLoginAttr (new Attribute “numLogins”)
        allAttributes (new FastVector 3)
        ]
        (. allAttributes (addElement ageAttr))
        (. allAttributes (addElement gendAttr))
        (. allAttributes (addElement numLoginAttr))
        allAttributes
    )
)

(defn createInstance [dataset age gender numLogins]
    (let [Inst (new Instance 3)]
        (. Inst (setDataset dataset))
        (. Inst (setValue 0 age))
        (. Inst (setValue 1 gender))
        (. Inst (setValue 2 numLogins))
        Inst
    )
)

(defn addInstance [dataset age gender numLogins]
        (. dataset (add (createInstance dataset age gender numLogins)))
        dataset
)

;create learning dataset
(defn createLearningDataSet [allAttributes]
    (let [trainingDataSet (new Instances “weka_example” allAttributes 5)]
        (. trainingDataSet (setClassIndex 1))
        (addInstance trainingDataSet (double 40) “male” (double 10))
        (addInstance trainingDataSet (double 30) “male” (double 9))
        (addInstance trainingDataSet (double 20) “male” (double 8))
        (addInstance trainingDataSet (double 20) “female” (double 13))
        (addInstance trainingDataSet (double 10) “female” (double 15))
        (addInstance trainingDataSet (double 60) “female” (double 2))
        trainingDataSet
    )
)

(defn learnPredict [learningDataSet]
    (let [classifier (new MultilayerPerceptron)]
        (. classifier (buildClassifier learningDataSet))
        classifier
    )
)

(defn predict [learnDataSet model]
    (let [testMaleInst (createInstance learnDataSet 34.0 “male” 4.0) 
        testFemaleInst (createInstance learnDataSet 7.0 “female” 20.0)]
        (println
            (format “나이 : 34, 로그인횟수: 4… 성별은? : %s”
                (if (= 1.0 (. model (classifyInstance testMaleInst))) (str “여자”) (str “남자”)  )
            )
        )
        (println
            (format “나이 : 7, 로그인횟수: 20… 성별은? : %s”
                (if (= 1.0 (. model (classifyInstance testFemaleInst))) (str “여자”) (str “남자”)  )
            )
        )
    )
)

(def learndata (createLearningDataSet (createAttributes)))
(println (str learndata))
(newline)
(predict learndata (learnPredict learndata))

[/CODE]

물론 Lisp이나 Weka API에 익숙하지 못한 분들은 보는데 시간이 걸리겠지만 코드 자체가 어려운 코드는 아니다. 다만 API에 너무 의존된 코드다 보니 흡사 자바 코드의 변종처럼 느껴지기도 하지만 나름 clojure 문법의 묘미를 잠시나마 느껴봤다.

테이터의 Attribute를 정해주고 이를 기반으로 Instance를 만들고 이런 Instance를 기반으로 Instances를 만들어 이를 Classifier에 넣어서 학습 시켜 모델을 만들고, 테스트 데이터로 테스트 Instance를 만들어 학습된 Classifier에 넣어서 결과를 받으면 된다.

위 설명이 대부분의 weka API를 이용한 데이터 마이닝 프로그램의 큰 얼개이다.

단순히 API만을 쓴다고 해도 이를 이해하기 위해서는 많은 설명이 필요하다. 데이터의 유형들에 대한 이해가 처음 수행이 되어야 하고 대부분의 Machine Learning 학습기가 어떠한 메카니즘으로 돌아가는지 이해가 필수다.

아무튼 이런 내용은 번역하고 있는 책을 통해서건 아니면 따로 블로그를 통해서건 나중에 설명을 하도록 하겠다.

일단 이 포스팅은 clojure를 가지고 weka API를 가지고 놀 수 있는 코드를 만들어보는 포스팅이니…

일단 결과를 보자.

@relation weka_example

@attribute age numeric
@attribute gender {male,female}
@attribute numLogins numeric

@data
40,male,10
30,male,9
20,male,8
20,female,13
10,female,15
60,female,2

나이 : 34, 로그인횟수: 4… 성별은? : 남자
나이 : 7, 로그인횟수: 20… 성별은? : 여자

결과가 나오기 전에 몇줄의 코드가 나오는데 이는 학습 Instances를 만든걸 가지고 toString()메서드를 쳐본것이다. 이 포멧은 arff라는  weka에서 주로 쓰이는 데이터 파일 포멧이다.
데이터 attribute에 nominal 이나 numeric 이나 data같은 포멧을 정의하는 헤더가 있어서 데이터 이해하기가 정말 쉬운 장점이 있다. 그래서 가장 마음에 드는 데이터 포멧중에 하나이다.

그리고 아래 정답이 나왔는데, 첫번째 답 성별은 남자로 나오고, 두번째는 여자로 나왔다.
한번 데이터를 기반으로 왜 이렇게 나왔는지 생각해 보는것도 재미있을 듯 하다. (아니면 데이터를 바꿔서 테스트 해보면 더 재미있을수도…. )

마지막으로 여기서 쓰인 알고리즘은 MultilayerPerceptron이라는 neural network알고리즘 이다.

이를 실행 하기 위해서는

java -cp clojure.jar:weka.jar clojure.lang.Script <파일명>

위와 같이 실행하면 된다. 각 jar 파일은 clojure와 weka 각 사이트에 가면 얻을 수 있다.

ps. 참고문헌은 Weka 툴킷에 포함된 Tutorial과 번역중에 있는 Collective Intelligence in Action 이다.

CC BY-NC 4.0 Clojure로 짜본 weka API 활용 예제 by from __future__ import dream is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.