본문 바로가기

Data Mining & R

[JAVA] Weka 라이브러리를 활용하여 KNN 사용하기

http://blog.naver.com/hisukdory/50173466207


Machine Learning 기법중에 가장 많이 활용되는 알고리즘 중 하나인 KNN에 대해서 포스팅해보고자 한다.

KNN에 대해서 허졉하고 간단하게 설명하면 다음과 같다.

여러~~ 특징을 가지고 있는 point들에 대한 데이터가 모여있고 각 데이터가 Labeling이 되어있다고 한다면,

종종 특정 point의 Label이 무엇인지 기존의 데이터를 기반으로 알아내야 하는 경우가 있다.

그럴 때 사용되는 것이 KNN인데,

실제로 이를 구현하려고 하다보면 좀 까다로운 것이 사실이다. (귀찮은게 더 큰것 같기도 하고..?)

따라서 오늘은 오픈 라이브러리인 WEKA를 활용해서 KNN을 활용하는 법을 알아보기로 한다.

 

WEKA를 활용해서 KNN을 돌려보기 위해서 요구되는 작업은 아래와 같다.

#1 인풋 데이터를 ARFF 형태로 바꿔주기

#2 KNN에 넣고 돌리기

 

(가.. 간단하다..)

 

그럼 차례차례 짚어보도록 하자.

본 포스팅에서는 네트워크 SSID와 GPS 데이터 (Latitude, Longitude)를 기반으로 현재 머무르고 있는 위치가 어디인지를 KNN을 통해 추론해서 알려주는 프로그램을 구현하였다.

 

#1 인풋 데이터를 ARFF 형태로 바꿔주기

 

WEKA는 ARFF 포멧을 인풋 포멧으로 활용하고 있다.

해당 홈페이지 (http://www.cs.waikato.ac.nz/ml/weka/arff.html) 를 가면 인풋 포멧을 어떻게 만드는지 볼 수 있다.

필자의 원래 데이터는 다음과 같은 포멧을 가지고 있는데,

 

 

 

이를 ARFF 포멧으로 변환시키면 다음과 같이 바뀐다. 

애초부터 ARFF로 데이터를 모아두면 쉽고, 그게 아니라면 바꾸는 코드는 스스로들 짜야한다.

 

 

 

데이터를 간단하게만 설명하자면, 위에서 보다시피, 첫번째가 latitude, 두번째가 longitude, 세번째가 장소 label이다.

.arff 확장자를 가지는 파일을 얻었다면, 이제 자바 라이브러리를 통해서 KNN을 돌려볼 시간.

 

#2 KNN에 넣고 돌리기

 

위의 데이터에서 유추해볼 수 있듯이,

인풋으로 latitude와 longitude를 제시해준 뒤 그 값의 label을 추론해내는 코드를 만들어보았다.

Weka 라이브러리의 경우 홈페이지를 통해 다운받는 것도 방법인데,

필자는 다운받아서 해보려고 했더니 뭔가 에러가 나서 잘 안되더라.

그래서 그냥 소스코드를 통째로 첨부해서 활용을 했다.

장단점이 있을테니 판단은 각자가 하길 바란다. 

소스코드가 혹시라도 필요하다면, 이클립스 버젼을 아래에 링크 걸어두도록 한다.

(https://dl.dropboxusercontent.com/u/20008753/Weka.zip)

본 코드에서의 K 값은 5로 설정해두었다.

 

// 인풋으로 latitude와 longitude를 설정해준다.

public String getPlaceKeyword(String ssid, double lat, double lon) {

String placeKey = "";

BufferedReader reader;

int maxCnt = 0;

SortedMap<String, Integer> placeCntMap = new TreeMap<String, Integer>();

 

writeDataFile(ssid);

 

try {

// 인풋 파일을 불러오고

reader = new BufferedReader(

new FileReader("loc_data/" + ssid + ".arff"));

// 인풋 파일을 data instance로 만들어준다.

Instances data = new Instances(reader);

 

// 실험을 해볼 target instance를 만들고

Instance target = new DenseInstance(2);

// target instance의 attribute을 설정해준다.

target.setValue(0, lat);

target.setValue(1, lon);

 

// 그리고 만든 KNN instance!

LinearNNSearch knn = new LinearNNSearch(data);

 

// target과 K 숫자를 넣어주고 KNN을 돌린다.

Instances result = knn.kNearestNeighbours(target, K_INDEX);

for (int i = 0; i < result.size(); i++) {

// 결과값을 받아서

String place = result.get(i).stringValue(2);

// 미리 만들어 둔 결과 값 Map에 넣어준다.

if (!placeCntMap.containsKey(place)) {

placeCntMap.put(place, 1);

} else {

placeCntMap.put(place, placeCntMap.get(place) + 1);

}

}

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

} catch (Exception e) {

e.printStackTrace();

}

 

for (String key : placeCntMap.keySet()) {

if (placeCntMap.get(key) >= maxCnt) {

maxCnt = placeCntMap.get(key);

}

}

 

for (String key : placeCntMap.keySet()) {

if (placeCntMap.get(key) == maxCnt) {

placeKey = key;

}

}

 

return placeKey;

}

 

생각보다 굉장히 간단하다.

웹페이지에 쉽게 설명해둔 포스팅을 찾기가 힘들어서 스스로 포스팅을 하기로 했다.

 

많은 도움이 되었으면 좋겠다.


'Data Mining & R' 카테고리의 다른 글

K means Clustering in R example Iris Data  (0) 2016.04.24
K-means  (0) 2016.04.24
SVM , discriminant analysis, KNN 실습  (0) 2016.04.20
k Nearest Neighbors(KNN)  (0) 2016.04.20
Deep Neural Network (DNN)  (0) 2016.04.19