网页排名算法计算错误的网页排名

时间:2019-03-01 20:14:59

标签: java algorithm pagerank

我正在尝试实现page rank算法。

我总共有5个网页(请参见下图)。下图表示图表,并显示哪个网页包含指向哪个页面的链接。

enter image description here

我已将这种网页链接存储在HashMap中,这样,每个网页的唯一链接都存储为key,而HashSet包含了所有到网络的链接给定网页指向的页面将存储为该键的值。 (请参见下图)

enter image description here

每个网页均由其唯一链接表示。上面提到的HashMap在代码中表示为

HashMap<URI, HashSet<URI>> graph = new HashMap<>();

我选择了等于{{1}的decay值和等于0.85的{​​{1}}

问题

生成上述epsilon之后,我正在计算每个网页的0.00001

最终融合网页排名

enter image description here

但我的实际网页排名是

Hashmap

每个页面的实际值都可以,因为每个页面的实际值和期望值之差小于所选的page rank Page A = 0.3170604814815385 Page B = 0.18719407056490575 Page C = 0.13199010955519944 Page D = 0.31131469834360015 Page E = 0.05244064005475638 除外。

我对此epsilon算法尝试了不同的输入,无论我尝试什么,我总是有一个或两个网页,其中页面排名值不正确。在所有页面都已收敛页面等级之前,即在每个页面的旧等级与新等级之间的差异小于Page D值之前,算法将返回。

问题

我在做什么错?为什么我的网页排名算法在所有网页都收敛之前返回网页排名?

代码

以下功能可生成上图所示的page rank

epsilon

以下功能计算网页排名

HashMap

以下两个函数是从private static HashMap<URI, HashSet<URI>> makeGraph(HashSet<WebPage> webpages) { HashMap<URI, HashSet<URI>> webPagesGraph = new HashMap<>(); HashSet<URI> singleWebPageLinks; HashSet<URI> availableWebPages = new HashSet<>(); // add all the web pages available in data set in a collection for (WebPage doc : webpages) { availableWebPages.add(doc.getUri()); } for (WebPage doc : webpages) { singleWebPageLinks = new HashSet<>(); for (URI link : doc.getLinks()) { // if link is not pointing to the web page itself and is available in data set if (!link.equals(doc.getUri()) && availableWebPages.contains(link)) { singleWebPageLinks.add(link); } } webPagesGraph.put(doc.getUri(), singleWebPageLinks); } return webPagesGraph; } 函数内部调用的实用程序函数

private static HashMap<URI, Double> makePageRanks(HashMap<URI, HashSet<URI>> graph,
                                                   double decay,
                                                   int limit,
                                                   double epsilon) {

        // Step 1: The initialize step should go here
        HashMap<URI, Double> oldPageRanks = new HashMap<>();
        HashMap<URI, Double> newPageRanks = new HashMap<>();

        double singleWebPageNewRank;
        int numLinkedPagesBySinglePage;
        double singleWebPageOldRank;
        boolean haveConverged = true;
        double rank;

        // provide ranks to each web page
        // initially the rank given to each page is 1/(total no. of web pages).
        // also give new page rank to each page equal to zero
        for (URI key : graph.keySet()) {
            oldPageRanks.put(key, (double) 1 / graph.size());
            newPageRanks.put(key, 0.0);
        }

        for (int i = 0; i < limit; i++) {
            // Step 2: The update step should go here

            for (URI uri : graph.keySet()) {

                singleWebPageOldRank = oldPageRanks.get(uri);

                numLinkedPagesBySinglePage = graph.get(uri).size();

                // if any web page doesn't have any outgoing links to any other
                // web page, increase the new page rank for every web page
                if (numLinkedPagesBySinglePage == 0) {
                    for (URI u : newPageRanks.keySet()) {
                        singleWebPageNewRank = decay * (singleWebPageOldRank / graph.size());
                        saveNewRank(newPageRanks, u, singleWebPageNewRank);
                    }
                } // increase the new page rank of every web page that is pointed to
                // by current web page
                else {
                    for (URI linkedWebPageURI : graph.get(uri)) {
                        singleWebPageNewRank = decay * (singleWebPageOldRank / numLinkedPagesBySinglePage);
                        saveNewRank(newPageRanks, linkedWebPageURI, singleWebPageNewRank);
                    }
                }
            }

            // account for random user/surfer by adding (1 - decay) / (total no. of web pages)
            // to each web page's new rank
            for (URI uri : newPageRanks.keySet()) {
                rank = newPageRanks.get(uri);
                rank = rank + ((1 - decay) / graph.size());
                newPageRanks.put(uri, rank);

                // check for convergence
                // check if difference b/w old rand and new rank for each web page
                // is less than epsilon or not
                // if difference between old and new ranks is greater than or
                // equal to epsilon even for one web page, ranks haven't converged
                if (oldPageRanks.get(uri) - newPageRanks.get(uri) >= epsilon) {
                    haveConverged = false;
                }
            }

            if (haveConverged) {
                return oldPageRanks;
            } else {
                haveConverged = true;
                overWriteOldRanksWithNewRanks(oldPageRanks, newPageRanks);
            }
        }

        return oldPageRanks;
    }

以下是简单的WebPage类

makePageRanks

最后是// save the new page rank for a given web page by adding the passed new page rank to // its previously saved page rank and then saving the new rank private static void saveNewRank(HashMap<URI, Double> newPageRanks, URI pageURI, double pageNewRank) { pageNewRank += newPageRanks.get(pageURI); newPageRanks.put(pageURI, pageNewRank); } // overwrite old page ranks for next iteration private static void overWriteOldRanksWithNewRanks(HashMap<URI, Double> oldRanks, HashMap<URI, Double> newRanks) { for (URI key : newRanks.keySet()) { oldRanks.put(key, newRanks.get(key)); // make new rank for each web page equal to zero before next iteration newRanks.put(key, 0.0); } } 方法,适用于希望查看我对页面排名算法提供的输入内容的人

public class WebPage {

    private ArrayList<String> words;
    private URI uri;
    private ArrayList<URI> links;

    WebPage(URI uri, ArrayList<String> words, ArrayList<URI> links) {
        this.words = words;
        this.uri = uri;
        this.links = links;
    }

    public ArrayList<String> getWords() {
        return words;
    }

    public URI getUri() {
        return uri;
    }

    public ArrayList<URI> getLinks() {
        return links;
    } 
}

1 个答案:

答案 0 :(得分:3)

摘要: 您正在测试错误的值。您必须减少代码的epsilon值,以使页面排名在所需值的0.00001以内。 0.00001内的两个连续猜测并不表示该结果。

除了我在评论中提到的问题外,我相信我也看到了您的问题。这是融合中的一个概念性问题。看起来单元测试的要求是收敛到预定值的epsilon以内。您尚未为此编写算法。您的测试

if (oldPageRanks.get(uri) - newPageRanks.get(uri) >= epsilon)

检查两个连续的近似值是否在该值内。这不是不能保证新页面排名在最终值的epsilon之内。 “接近”邻域的演算/拓扑定义读取以下内容,以猜测x和参考(正确)点z

abs(x - z) < delta  ==>  abs(f(x) - f(z)) < epsilon

您可能对deltaepsilon感到困惑。

如果逼近函数的梯度超出[-1,+1]范围,则​​可能会因该错误而跳闸。您需要找到为此保留的delta值,然后使用那个数量代替当前的epsilon。这是您提供给函数的epsilon值的简单更改。