페이지 랭크(PR, PageRank) 알고리즘은 구글 검색엔진의 핵심이다.

 

요약하자면 하이퍼텍스트 정보를 이용하여 웹페이지 사이 연결정보로 검색 결과를 향상시키기 위한 알고리즘이다.

 

연결정보로부터 특정 페이지를 다른 페이지들이 얼마나 인용하는지 세는 방식이다.

 

예를 들어, A 페이지를 B, C 페이지에서 인용하고 있다고 가정하자.

 

이 때, B 페이지에서 전체 인용 링크 수 5개 중 1개가 A 페이지인 경우 PR(B) / L(B) = 1 / 5 가 된다.

 

PR(B)의 경우 초기값은 1이고, 재귀적으로 반복 계산되어 수렴되는 PR 을 사용한다.

 

N은 전체 문서 수, L은 인용 수, d는 Damping Factor 값(Random Surfer)이다.

 

여기서 Random Surfer는 사용자가 해당 페이지에 만족하지 못하고 다른 페이지로 이동하는 랜덤 확률을 나타낸다.

 

d 값은 일반적으로 (논문들에서) 0.85 값을 사용하며, 이는 85%는 만족하지 못하고 다른 페이지로 이동하며,

 

나머지 15%만이 해당 페이지를 유의깊게 읽어본다는 말이 된다.

 

위의 예를 1회 계산하면,

 

PR(A) = (1 - 0.85) / 3 + 0.85 * (1 / 5 + 1 / 1) = 1.07

 

여기서 C 는 전체 인용 링크 수 1개 중 1개가 A 페이지인 경우를 예로 들었다.

 

단순한 예에서는 PR 값이 순환되지 않아 PR(A), PR(B), PR(C) 값이 1회 계산으로 수렴되지만,

 

실제 서비스 환경에서는 계산을 반복할 수록 PR 값이 수렴하는 결과를 얻을 수 있다.

 

PageRank를 간단하게 Java 프로그램으로 테스트할 수 있다. (참고)

 

예를 들어 CSV 형태의 url, outLink1, outLink2, ... 데이터가 있다고 가정해보자.

 

먼저 다음과 같이 각 url 키를 담을 객체가 필요하다.

public class PageRankValue {
	private double pageRankScore;
	private double outLinkScore;
	private List<String> outLinks;
}

 

다음으로 매 url 마다 PageRankValue를 생성해야 한다.

private void addPageRankValue(String[] csv) {
	if (csv == null || csv.length == 0) throw new IllegalArgumentException();

	String key = csv[Configurations.IDX_KEY_LINK];
	if (!Validator.validateString(key)) throw new NullPointerException();

	PageRankValue prValue = null;
	if (mapPageRanks.containsKey(key)) prValue = mapPageRanks.get(key);
	else prValue = new PageRankValue();

	for (int i = (Configurations.IDX_KEY_LINK + 1); i < csv.length; i++) {
		prValue.addOutLink(csv[i]);
		if (!mapPageRanks.containsKey(csv[i])) mapPageRanks.put(csv[i], new PageRankValue());
	}
	mapPageRanks.put(key, prValue);
}

 

이제 미리 정해둔 iteration 횟수만큼 evaluation을 수행하면 된다.

@Override
public void evaluate() {
	// Set the outLinkScore for the entire links
	mapPageRanks.keySet().stream().forEach(k -> {
		PageRankValue prValue = mapPageRanks.get(k);
		Iterator<String> outLinks = prValue.getOutLinks();

		while (outLinks.hasNext()) {
			PageRankValue prOutLink = mapPageRanks.get(outLinks.next());

			if (prOutLink != null) {
				// Divides the source link's page rank score by the number of out links
				double score = prValue.getScore() / prValue.getOutLinkCount();
				prOutLink.addOutLinkScore(score);
			}
		}
	});

	// After setting outLinkScore, evaluate each page rank score using the number of entire links
	mapPageRanks.keySet().stream()
			.forEach(k -> mapPageRanks.get(k).evaluate(Configurations.DAMPING_FACTOR, mapPageRanks.size()));
}

 

이렇게 연습해본 PageRank 알고리즘에 실제 대용량의 데이터를 적용하려면, Hadoop, Spark 등과 같은 대용량 데이터 처리 프레임워크를 기반으로 처리해 볼 수 있다.

블로그 이미지

나뷜나뷜

,