You are on page 1of 6

WECA를 이용한 예측프로그램 만들기

오류 쿼리 분류기의 구현
Weka는 데이터 자체를 분석하기 위해도 쓰이지만 jar파일을 인클루드해 모델을 빌드하고 이를 런타임 서비스에 적용할 수도
있다. 2회 연재에서 API를 사용하는 방법을 숙지하고 있다면 Weka를 이용한 지능형 애플리케이션 구축도 어렵지 않을 것이
다. 그럼 이번 예제인 오류 쿼리 분류기를 빌드해 보기로 하자.

연 재 가 이 드 전희원 gogamza@freesearch.pe.kr, www.freesearch.pe.


1회 | 2009. 7 | 데이터 마이닝 및 WECA GUI를 알아보자 kr|학교에서는 정보검색 및 Machine Learning을 주로 연구했으며, 수년
2회 | 2009. 8 | WECA API 그리고 커멘드 라인 인터페이스 간의 검색엔진 개발 및 데이터마이닝 경험을 가지고 있다. 대용량 데이터 처
3회 | 2009. 9 | 오류 쿼리 분류기의 구현 리 및 데이터마이닝에 많은 관심을 가지고 있고, 현재 야후! 아시아 서치 엔
지니어링(Asia Search Eng)팀에서 방대한 양의 웹 데이터를 들여다보며 흥미로운 시간을
보내고 있다.

스텝
바이
스텝 3
이전 2회 연재에서 언급한 바와 같이 이번 연재는 오류 쿼리 제
“아후”
를 의미했을 가능성을 배제할 수 없을 것이다. 따라서
분류기 구현 예제를 구축해 보겠다. 일단 오류 쿼리가 무엇인지 “아후”
라는 쿼리가 입력됐을 때 쿼리만을 보고 검색엔진에서 이
생각해 볼 필요가 있다. 그래야 우리의 소기 목적인 오류 쿼리를 것을 오류 쿼리로 단정지을 수 없다.
잘 분류할 수 있을 것이기 때문이다. 두 번째,
“어라ㅓㄴ아라ㅣㅇ너리ㅏㄴ어리ㅏㅓㄴ이ㅏ렁나ㅣㅓ
정의를 하기에 앞서 왜 우리가 오류 쿼리를 분류해야 하는지 라ㅣㄴㅇㄹ”
와 같은 쿼리들을 예로 들자면 자모들이 빈번하게
살펴볼 필요가 있을 것이다. 필자가 실제 분석해본 경험에 따르 쿼리에 출현하는 것을 볼 수 있다. 이런 쿼리들은 쿼리가 and 검
면 오류 쿼리는 10번 중에 1번 정도의 비율로 검색엔진에 유입이 색 결과를 리턴한다고 가정했을 때 아무런 검색 결과도 리턴하지
된다. 물론 이 오류 산정 방법에서‘추정’
의 의미가 크지만 이 추 못할 가능성이 많은 쿼리들이다. 그러나 이러한 쿼리들은 자모의
정의 95% 이상은 실제 쿼리에 오류를 포함하는 것들이라 볼 수 비율을 카운팅해 간단하게 다른 추가 정보 없이 쿼리만으로 에러
있다. 만일 여러분의 검색엔진이 1000qps(query per second)를 쿼리 분류도 가능할 것이다.
가지고 있다고 한다면 이 오류 쿼리를 실제 검색 색인에 던지지 세 번째, 쿼리의 길이가 터무니없이 긴 경우를 볼 수 있다. 물
않고 정확하게 판단해 리턴해 버린다면 100qps의 컴퓨팅 리소스 론 쿼리가 정상적인 단어로 이뤄질 경우 원하는 문서가 있을 수
를 절약할 수 있는 것이다. 그럼 이제 필자가 생각하는 오류 쿼리 도 있겠지만, 일단, 쿼리가 길어질수록 오류를 포함할 가능성도
의 정의를 생각해볼 시간이다. 커진다. 아래의 쿼리는 실제 사용자가 입력한 쿼리의 한 예다.

오류 쿼리의 정의 “t8t8476969999999999999999999999999999966666666666/////
쿼리에 오류가 있다고 한다는 것은 무엇을 의미할까? 일단 몇 //////////////////////////////////////////////////////////////////////
가지 쿼리에서 오류가 의미하는 것은 어떤 것들이 있는지 살펴볼 //////////////////////////666666666666666666666666666666666
필요가 있을 듯 하다. 6666666666666666666666666666666669999999999999999999
첫 번째로, 일단 사용자가 의도하지 않는 쿼리를 생각할 수 있 999999999999999999999999999999999999999999999”
다. 예를 들어“야후”
를“아후”
라고 잘못 검색 했을 때 이것은 사
용자 관점에서 명백히 오류 쿼리라고 생각할 수 있다. 하지만 실 하지만 길다는 것이 어느 정도 길이여야 오류인지, 더 나아가

256 m a s o
오류 쿼리 분류기의 구현

서 자모 쿼리의 비율이 커질수록 이 기준점은 늘어나야 마땅할 기 위해 이 데이터 파일을 Weka Instances로 변환할 필요가 있
것이고, 특수문자 및 숫자, 기호 등이 혼합되어 있을 경우에도 서 다. 따라서 필자는 특징 생성을 위한 FeatureExtraction 클래스
로 다른 길이 기준을 적용해야 할 것이다. 따라서 네 번째로는 숫 를 만들 것이다.
자, 알파벳을 제외한 Ascii문자들의 비율을 따지는 것이 도움이 두 번째로, 이를 기반으로 학습을 실시해 모델을 빌드하고 모
될 것이다. 델 검증을 실시한다. 그리고 어떤 분류기가 가장 좋을 것인지 테
마지막 다섯 번째는 위 쿼리와“hgddddddddddddddd 스트는 1회 연재에서 했던 Weka GUI를 활용해 독자들이 판단
ddddddddddddddddddddddddddddddddddddddddddddvfddd 하면 될 것이다. 편의상 이번 컬럼에서는 Boost기법을 활용한 알
dddddddddddddddddddddddd”이런 쿼리와 같이 쿼리에서 동 고리즘을 적용해 보도록 하겠다.
일한 문자의 반복의 비율에 따른 기준도 도입할 만 할 특징으로 세 번째로, 만든 모듈을 커맨드라인 인터페이스를 통한 테스트
볼 수 있다. 실제 이런 형식의 오류 쿼리는 상당한 비율이어서 오 모듈을 만들어 테스트 할 수 있게 한다. 마지막 세 번째 단계에서
류 쿼리를 분류할 때 많은 도움이 될 것이다. 는 간단하게 커맨드라인 인터페이스 구축으로 명시했으나, 독자
위 언급한 다섯가지 중에서 첫 번째 것을 제외한 나머지 네 가 들의 검색 엔진의 쿼리 프로세싱 모듈 단에 장착을 할 수 있을 것
지 특징을 우리가 구현하고자 하는 분류기의 특징으로 사용하고 이다. 애초 루씬(Lucene) 쿼리 프로세싱 모듈에 장착하려 했으
자 한다. 만일 첫 번째 특징을 사용하고자 한다면 우리는 상당히 나 강좌의 설명 범위와 지면 분량 여건으로 생략하게 되었음을
정확하고 최신의 웹 사용 단어들을 포함한 질 좋은 사전을 구비 양해해 주기 바란다.
해야 한다. 하지만 이런 사전은 어느 누구도 가지고 있지 않을 것
이다. 따라서 제외하고 나머지 네 가지 특징을 사용해 분류기를 쿼리로부터 특징 추출하기
구축하도록 하겠다. 먼저 앞서 설명한 네 가지 특징을 쿼리로부터 추출하는
FeatureExtraction 클래스 코드를 작성해 보도록 하겠다.
구축 과정
<리스트 2> FeatureExtraction 클래스
일단 필자는 208개의 랜덤 제네레이션 된 쿼리 학습셋을 준비
public class FeatureExtraction {
했다. 이 학습셋은 필자가 약 10분(평가에만)을 투자해 만든 학 //한글 자소 유니코드
습셋이며, 정상 쿼리의 특징을 학습시키기보다 오류특징을 학습 // ㄱ ㄲ ㄴ ㄷ ㄸ ㄹ ㅁ ㅂ ㅃ ㅅ ㅆ ㅇ ㅈ ㅉ ㅊ ㅋ ㅌ ㅍ ㅎ
Integer[] ChoSung = { 0x3131, 0x3132, 0x3134,
시키는 것이 좀 더 직관적이라는 판단이 들어 오류 쿼리의 비율
0x3137, 0x3138, 0x3139, 0x3141, 0x3142, 0x3143, 0x3145,
을 좀 더 강화한 학습셋이다. Weka를 돌려보면 이 208개의 쿼리 0x3146, 0x3147, 0x3148, 0x3149, 0x314a, 0x314b, 0x314c,
0x314d, 0x314e };
로 교차 검증(cross-validation)을 실시한 결과를 볼 수 있을 것
이다. 다음에 제시되고 있는 <리스트 1>은 학습셋 샘플을 보여주 // ㅏ ㅐ ㅑ ㅒ ㅓ ㅔ ㅕ ㅖ ㅗ ㅘ ㅙ ㅚ ㅛ ㅜ ㅝ ㅞ ㅟ ㅠ ㅡ ㅢ ㅣ
고 있다. Integer[] JwungSung = { 0x314f, 0x3150, 0x3151,
0x3152, 0x3153, 0x3154, 0x3155, 0x3156, 0x3157, 0x3158,
0x3159, 0x315a, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f,
<리스트 1> 학습셋 샘플
0x3160, 0x3161, 0x3162, 0x3163 };
피싸모 1
사회교육원 사회복시사 비용 1 // ㄱ ㄲ ㄳ ㄴ ㄵ ㄶ ㄷ ㄹ ㄺ ㄻ ㄼ ㄽ ㄾ ㄿ ㅀ ㅁ ㅂ ㅄ ㅅ ㅆ ㅇ ㅈ ㅊ ㅋ ㅌ ㅍ ㅎ
스틸플랜틱 가부시키가이샤 1 Integer[] JongSung = { 0, 0x3131, 0x3132, 0x3133,
달감치킨메뉴 1 0x3134, 0x3135, 0x3136, 0x3137, 0x3139, 0x313a, 0x313b,
핑클 가면의 시간ㅡㅔ3 0 0x313c, 0x313d, 0x313e, 0x313f, 0x3140, 0x3141, 0x3142,
wkdtmtn 0 0x3144, 0x3145, 0x3146, 0x3147, 0x3148, 0x314a, 0x314b,
窮 1 0x314c, 0x314d, 0x314e };
www.inchoen.co.kr 1
구ㅏㅇ 0 HashSet<Integer> jasoSet = new HashSet<Integer>();
울산지역해군예비역하사관모임 1
포스닉 1 String Query = "";
public FeatureExtraction(){
for(Integer i : ChoSung){
jasoSet.add(i);
<리스트 1>을 보면 마지막 필드에 0, 1과 같은 숫자가 있는데, }
이것들이 비정상과 정상을 분류한 코드들이다. 먼저 모델을 만들

m a s o 257
스 텝 바 이 스 텝 | 3

for(Integer j : JwungSung){ 리를 구분해 낼 수 있게 된다.


jasoSet.add(j); 이제 쿼리 문자열을 입력해 네 가지 특징을 추출하는 메소드들
}
for(Integer k : JongSung){
을 모두 만들었다. 그렇다면 이제 이를 이용해 실제 쿼리를 입력
jasoSet.add(k); 받아 Weka 데이터셋 인스턴스인 Instances를 생성하는 클래스
}
를 만들어 보자.
}
public FeatureExtraction(String rawQuery) {
this();
Instances 생성하기
this.Query = rawQuery;
}
public boolean isJaso(int codepoint){ <리스트 3> MakeIQCInstances 클래스

return jasoSet.contains(codepoint) ? true : public class MakeIQCInstances {


false; public FastVector attributes = null;
} public Instances instances = null;
public boolean isSymbol(int cp){
return ( (cp >= 0 && cp <= 47) || (cp >= 60 && public MakeIQCInstances(){
cp <= 64 ) || attributes = getAttributesFV();
(cp >= 91 && cp <= 96) || (cp >= 123 && }
cp <= 255) );
}
public static FastVector getAttributesFV(){
public float ratioSymbol(){
//속성 정의
float symcnt = 0;
Attribute attrSymbol = new Attribute("Symbol
for(int i = 0 ; i < Query.length(); i++){
ratio");
if(isSymbol(Query.codePointAt(i)))
Attribute attrJaso = new Attribute("Jaso ratio");
symcnt++;
Attribute attrComp = new Attribute("Compression
}
ratio");
return symcnt/Query.length();
Attribute attrQryLength = new Attribute("Query
}
length");
public float ratioJaso(){
//클래스 속성
float jasocnt = 0;
FastVector fv = new FastVector(2);
for(int i = 0 ; i < Query.length() ; i++){
fv.addElement("1"); //정상 쿼리
if(isJaso(Query.codePointAt(i)))
fv.addElement("0"); //비정상 쿼리
jasocnt++;
Attribute attrCls = new Attribute("Class", fv);
}
return jasocnt/Query.length();
//속성 벡터 정의
}
FastVector AttributesFV = new FastVector(5);
public float ratioComp(){
AttributesFV.addElement(attrSymbol);
HashSet<Character> charSet = new
AttributesFV.addElement(attrJaso);
HashSet<Character>();
AttributesFV.addElement(attrComp);
for(int i = 0; i < Query.length() ; i++)
AttributesFV.addElement(attrQryLength);
charSet.add(Query.charAt(i));
AttributesFV.addElement(attrCls);
return 1.0F -
((float)charSet.size())/Query.length();
return AttributesFV;
}
}
public float queryLength(){
return (float)Query.length();
public static Instance getInstance(FastVector
}
attributes, String query, String cls, boolean isTest){
}
FeatureExtraction fx = new
FeatureExtraction(query);
Instance instance = new Instance(5);
<리스트 2>에서 중점적으로 봐야 될 메소드는 ratioSymbol(),
instance.setValue((Attribute)attributes.
ratioJaso(), ratioComp()이다. ratioSymbol() 메소드는 기호 elementAt(0), fx.ratioSymbol());
특징을 가지고 있는 Ascii 문자들의 쿼리 내 비율을 리턴한다. instance.setValue((Attribute)attributes.
elementAt(1), fx.ratioJaso());
ratioJaso()는 메소드 명에서 유추할 수 있겠지만, 쿼리의 자소 instance.setValue((Attribute)attributes.
비율을 리턴한다. 마지막으로 ratioComp() 메소드는 쿼리의 압 elementAt(2), fx.ratioComp());
instance.setValue((Attribute)attributes.
축률을 리턴하는데, 이 메소드를 통해 반복된 문자열을 가진 쿼

258 m a s o
오류 쿼리 분류기의 구현

elementAt(3), fx.queryLength()); 성된 모델을 저장∙로딩하는 메소드들을 포함하고 있다. 게다가,


if(!isTest) saveArff()라는 메소드를 통해 Instances를 Weka 포맷인 arff
instance.setValue((Attribute)attributes.
파일로 저장도 가능하다. 아마도 여러분들이 배포 가능한 모델을
elementAt(4), cls);
else 빌드하고 싶다면 saveModel(), loadModel() 메소드에서 힌트를
instance.setValue((Attribute)attributes.
발견할 수 있지 않을까 한다. 그리고 strPredict() 메소드를 통해
elementAt(4), "0");
return instance; 입력된 쿼리 문자열이 정상적인 쿼리인지 오류 쿼리인지 테스트
} 를 해볼 수 있다.
public Instances getInstancesFromFile(String 전체적인 테스트를 위해 필자가 Main.java를 <리스트 4>로 작
Filename) { 성해 두었다. 이 메인 메소드를 통해 위에서 설명한 모든 과정을
Instances insts = new Instances("iqc data set",
attributes, 0);
한꺼번에 돌려볼 수 있을 것이다.

try { <리스트 4> 메인 클래스


FileReader fi = new FileReader(Filename);
public class Main {
BufferedReader br = new BufferedReader(fi);
String line = "";
public static void main(String[] args) throws
while ((line = br.readLine()) != null) {
IOException{
String[] lineary = line.split("\t");
MakeIQCInstances makeinst = new
//System.out.println("length " +
MakeIQCInstances();
lineary.length);
Instances instances = null;
if(lineary.length !=2)
System.out.println("error " + line);
if(args.length == 1){
String qry = lineary[0];
instances =
String cls = lineary[1];
makeinst.getInstancesFromFile(args[0]);
Instance inst =
}else
getInstance(this.attributes,qry, cls, false);
System.exit(1);
insts.add(inst);
}
IQCClassifier IQC = new IQCClassifier(instances,
makeinst.attributes);
} catch (FileNotFoundException ex) {
String[] options = {"-P", "100" ,
Logger.getLogger(Main.class.getName()).log
"-S", "1",
(Level.SEVERE, "File not found!", ex);
"-I", "10",
"-W", "weka.classifiers.
} catch (IOException ex) {
trees.J48",
Logger.getLogger(Main.class.getName()).log "--",
(Level.SEVERE, "no inputted lines", ex); "-C", "0.25",
} "-M", "2"};
insts.setClassIndex(4); IQC.buildClassifier(new AdaBoostM1(), options);
this.instances = insts;
return instances; //모델 저장과 로딩 테스트
} IQCClassifier.saveModel(IQC.getClassifier(),
} "adamodel");
Classifier loadedmodel=
(Classifier)IQCClassifier.loadModel("adamodel");
MakeIQCInstances 클래스는 이전에 만들었던 Feature //System.out.println("loaded model \n" +
loadedmodel.toString());
Extraction 클래스를 기반으로 Instances를 구축하게 된다.
IQC.loadModel(loadedmodel);
getInstancesFromFile 메소드는 입력된 파일명을 읽어들여 네 //arff 파일 저장
가지 특징을 추출해 Instance를 만들고 이를 Instances 객체에 IQCClassifier.saveArff(IQC.getInstances(),
"iqc.arff");
추가하는 과정을 반복하게 된다.
//몇 가지 테스트
String test1 = "검색엔진";
모델 생성 및 테스트 String test2 = "ㅁㄴ엔진ㄴ";
IQCClassifier 클래스에서는 모델을 빌드하고 테스트 하며, 생

m a s o 259
스 텝 바 이 스 텝 | 3

System.out.println(test1 + " : " + 일단 먼저 제시된 메인 메소드를 실행시켜보면 model이라는


IQC.strPredict(test1)); 하부 디렉토리에 iqc.arff 파일이 생성되는데 이를 이용해 Weka
System.out.println(test2 + " : " +
IQC.strPredict(test2));
GUI를 열어 weka.classifiers.trees.J48 이라는 결정트리 C4.5
알고리즘으로 모델빌드를 해보자. 빌드가 모두 완료됐으면
BufferedReader in = new BufferedReader(new
Result list 창에서 마우스 오른쪽 버튼을 클릭해 Visualize tree
InputStreamReader( System.in));
String qry = ""; 를 클릭해 결정트리의 모습을 확인해 보자.
결정트리에서 상위 노드에 존재하는 특징은 학습셋에서 분류
while((qry = in.readLine()) != null){
System.out.println(qry + " : " + 를 하는데 가장 큰 영향을 끼치는 특징이라는 것을 의미한다. <화
IQC.strPredict(qry)); 면 1>을 보면 자소 비율이 쿼리의 클래스를 결정하는데 가장 큰
}
} 영향을 끼치는 특징이라는 것을 알 수 있다. 이런 트리뷰 말고 중
} 요 특징을 추출하는데 feature selection을 사용할 수도 있다. 이
부분도 상당히 재미있는 부분이니 여러분도 시간이 나시면 꼭 살
<리스트 4>에서
“IQC.buildClassifier(new AdaBoostM1(), 펴보길 바란다. 필자의 경우 메인 메소드를 아래와 같이 실행시
options);”
이 의미하는 바는 AdaBoost를 사용해 모델을 빌드한 켰다.
다는 의미인데, AdaBoost는 대표적인 Boosting 알고리즘으로
여러개의 분류기를 내부적으로 생성해 이들의 가중 다수 투표 java -Dfile.encoding=utf_8 -jar IQC.jar ../arff/sample_200.csv
(weighted majority voting)에 의해서 의사를 결정하는 방식이
다. Boosting 알고리즘은 첫 번째 생성한 분류기에서 틀리게 판 필자가 제공하는 소스코드의 루트에서 dist 디렉토리에서 위
단한 것들에 대해 더 가중치를 주어 다음 분류기에서 학습셋으로 의 명령을 실행시키면 <리스트 5>와 같은 로그가 출력된다.
선택돼 학습이 되도록 하게끔 구성이 되어 있어서 여러개의 분류
<리스트 5> 출력 결과
기들은 서로 상호 보완적인 역할을 하도록 구성이 된다.
Building Classifier....
그 밖에 Bagging 이라는 방식도 있는데 이 역시 T개의 분류기
를 생성하기 위해 전체 학습셋에서 대치(replace)를 허용해 서브 Correctly Classified Instances 198
학습셋 T개를 생성하고 이들 각각의 서브 학습셋을 기반으로 T 94.2857 %
Incorrectly Classified Instances 12
개의 분류기를 생성해 이들의 투표로 클래스를 판단하게 된다. 5.7143 %
이런 혼성모델 방식의 학습기는 일반적으로 단일의 학습기를 Kappa statistic 0.8254
Mean absolute error 0.091
선택해 사용하는 것보다 더 성능이 좋다고 알려져있다. 이러한
Root mean squared error 0.2113
분류의 알고리즘 쪽에서도 집단지성의 힘을 활용한다는 사실이 Relative absolute error 25.342 %
참 재미있기도 하다. 특히 필자와 같은 개발자들에게는 손쉽게 Root relative squared error 49.9661 %
Total Number of Instances 210
성능을 향상 시킬 수 있는 좋은 방법 중 하나이다.
Saving Model....
Loading Model....
Saving Arff File....
검색엔진 : 1
ㅁㄴ엔진ㄴ : 0

정확도가 94%에 육박하는 것은 필자가 학습셋으로 만든


Instances를 테스트할 때 다시 썼기 때문이다. 이 부분은 여러
분이 실제 새로운 테스트 셋을 만들어 테스트 해볼 수 있기를
바란다.
2개의 샘플 쿼리 테스트 이후에는 여러분이 커맨드라인으로
<화면 1> 트리뷰(Tree View) 직접 쿼리를 입력해 테스트 해볼 수 있을 것이다. 독자들이 직접

260 m a s o
오류 쿼리 분류기의 구현

weka.classifiers.trees.J48 단독으로 사용한 분류기와 Boost를 알고리즘이 어떠한 매커니즘으로 동작하는지 반드시 이해해야
이용해 weka.classifiers.trees.J48를 사용한 것의 결과차이를 비 하기 때문이다. 따라서 Weka 공부의 마지막 단계는 개별 알고리
교해 보기 바란다. 신기하게도 Boosting를 사용한 기법이 더 나 즘들의 이해로 마무리가 된다.
은 결과를 보이는 것을 알 수 있다. 물론 대체적으로 학습셋이 적 마지막으로 Weka 공부를 심도 깊게 해보고자 하는 독자에게
어서 수긍하기 힘들 수도 있겠지만 학습셋이 적을수록 Boosting 책 하나를 추천할까 한다. Data Mining: Practical Machine
방법이 힘을 얻는 다는 것은 이미 여러 논문에서 밝혀진 사실이 Learning Tools and Techniques (Second Edition) 으로 검색
니 큰 걱정 안 해도 될 듯 하다. 엔진 개발하는 사람들에게 잘 알려진 Managing Gigabytes를 공
저하신 Ian H. Witten이 공저자로 참여한 책이다. Witten 교수
결정트리(ID3, C4.5) 의 연구이력을 보면 데이터를 어떻게 효과적으로 저장하고 빠르
게 검색할 수 있을까 하는 연구를 시작으로 서서히 데이터에서
여기서 사용한 J48은 일반적으로 C4.5로 알려진 결정트리 알고리즘이
어떻게 하면 가치있는 정보를 뽑아낼 수 있을지를 연구하는 데이
다. 결정 트리에는 크게 3가지 방식(CART, ID3, C4.5)의 시스템이 존
재한다. 전혀 다른 알고리즘이라고 보는것이 아니라, 동일한 알고리즘을 터 마이닝으로 연구범위가 넓어지는 경향이 있음을 알 수 있다.
약간 다르게 변화시킨 시스템이라고 보면 된다. 검색과 데이터 마이닝이 크게 다른 영역이 아니라는 것은 이 부
이들 시스템은 트리 형태로 분기를 만들어가는 방식은 동일하나 속성의 분에서 보여주고 있다.
노드를 선정할 때 계산하는 불순도 계산 방식, 가지치기(pruning), 실수 연재를 보다 질문이 있으면 언제든지 필자의 블로그 http://
데이터를 다루는 방식들이 서로 다르다. 결정 트리 계통도에서 ID3와 freesearch.pe.kr 에 올려주기 바란다.
C.4.5는 같은 계통을 가진다. 쉽게 말해 같은 사람에 의해서 개발된 것
이다. 따라서 초기 버전인 ID3에서 기능 확장이 일어나 C4.5가 되었고,
이 C4.5를 상용화 한 것이 C5.0과 See5가 된다. 이달의 디스켓 : iqc.zip
대표적인 ID3와 C4.5의 차이점으로는 ID3는 사전 가지치기를 수행하는
반면, C4.5는 사후 가지치기를 한다. 필자 판단으로는 사후 가지치기가
참고자료
더 효과적이라고 생각한다.
1. Data Mining: Practical Machine Learning Tools and Techniques (Second
또한 weka에서 ID3를 이용한 알고리즘에서는 연속형 속성사용이 불가 Edition), Ian H. Witten, Eibe Frank

능했지만 C4.5의 경우 부등호 형식을 이용해 연속형 속성을 사용한 분


류작업이 가능하다.

이번 마지막 연재에서 제공한 학습셋과 소스코드는 이달의 디


스켓으로 함께 배포될 것이다. 여러분 취향대로 학습셋을 보강하
거나 테스트셋을 추가해 여러가지 실험을 해보면 많은 도움이 될
수 있을 거라 생각한다. 아마도 여러분의 것이 성능 좋게 나온다
면 이 모듈을 보강해 검색 시스템에 추가를 할 수도 있을 것이라
예상한다.
weka가 가장 오래되고 가장 널리 사용되는 데이터마이닝 패
키지이지만, 이미 Java진영에서는 Java Data Mining(JDM)
API를 공식적으로 지원하고 있다. 물론 오라클과 같은 벤더에는
이미 1.0 릴리즈를 했다. 만일 여러분이 좀 더 표준화된 API를
사용해 데이터마이닝 프로그램을 구축하고 싶다면 JDM을 사용 <월간>마소는
하는 것도 좋은 방법이 될 것이다.
아마도 어떤 분들은 Weka를 사용해보고 알고리즘이 궁금해 늘 개발자의 곁에 서 있습니다
져 알고리즘 공부를 시작할 수 있을 것이라 생각한다. 이는 아주 1년 후에도 내용이 살아있는 잡지

바람직한 접근방법이다. 그저 마구잡이로 사용하는 것보다 여러


분이 만드는 서비스의 목적에 맞는 알고리즘을 찾기위해 각각의

m a s o 261

You might also like