データ マイニング Java - PageRank アルゴリズムの実装

まず、PageRank アルゴリズムの予備知識

PageRank アルゴリズム: 各 Web ページの PageRank 値を計算し、この値の大きさに従って Web ページの重要度を並べ替えます。

ユーザーの観点から見ると、Web サイトはいくつかのページの集合です。しかし、Web サイトの設計者にとって、これらのページは注意深く構成されており、ページ全体のリンクによって連続的に接続されています。したがって、Web 構造マイニングは主に Web サイト内のページのリンク構造を発見することですたとえば、検索エンジンなどのサービスを設計する場合、Web ページのリンク構造をマイニングすると、検索の効率と品質を向上させるために役立つ知識を得ることができます。
一般に、Web ページへのリンクは学術的な引用に似ているため、重要なページには、それを指す多くのページへのリンクが含まれる場合があります。つまり、あるページへのリンクが多数ある場合、それは重要なページである必要があります。同様に、ページが多くのページにリンクしている場合、そのページには大きな価値があります

u が Web ページ、Bu が u を指すすべてのページの集合、Fu が u を指すすべてのページの集合、c (<1) が正規化係数であると仮定すると、u ページのランク R(u) は次のようになります。次のように定義されます: R(u)=c∑_(v∈Bu)▒(R(v))/(|Fv|)、明らかに、基本的なページ分類方法は主にページの入次数を考慮します。を入力するとそのページのページランクが取得されます。同時に、ページのランク値が渡されると、平均分散方法を使用して、そのページが指すすべてのページにそのランク値が渡されます。つまり、そのページからリンクされている各ページがそのランク値を均等に分割します。

PageRank アルゴリズムの中核部分は、有向グラフから始めることができます。最も典型的な方法は、有向グラフに従って隣接行列を構築して処理することです。隣接行列 A=(ai,j) の要素 ai,j(∈[0,1]) は、ページ j からページ i を指す確率を表します。

2、PageRankアルゴリズムの基本的な考え方

基本的な PageRank アルゴリズムがランク値を計算するとき、各ページは自身のランク値を参照するページ ノードに均等に分配します。ページのレベル値が 1、ページ上に n 個のハイパーリンクがあり、各ハイパーリンク ページに割り当てられたレベル値が 1/n であると仮定すると、ページは参照する任意のページにジャンプすることがわかります。
一般に、隣接行列 A は、PageRank アルゴリズムを実装するために、いわゆる遷移確率行列 M に変換されます。M=(1-d) Q+d A、Q は定数行列で、最も一般的に使用されるのは Q=( qi,j )、qi,j=1/n、遷移確率行列 M は、ページ レベル値ベクトル R の反復計算を完了するのに役立つベクトル変換行列として使用できます: Ri+1=M*R

3. PageRank アルゴリズムの例

PageRank アルゴリズムの例
ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入

4 番目に、PageRank アルゴリズムの実装プロセス

実験内容
インターネット上の Web ページのリンクは、A、B、C、D の 4 つの Web ページのように、有向グラフとみなすことができます。Web ページのランク付けと並べ替えには、PageRank アルゴリズムを使用してください。クラスには、分子の息子が含まれて
ここに画像の説明を挿入

ますおよび分母の mom 属性が含まれており、分子と分母を減らすための静的メソッド simplify()、分数を加算して結果を単純化するための静的メソッド getAdd()、および分数位相乗算と呼び出し simplify() のための静的メソッド getMultiply() も含まれています。 ) 結果を単純化します。
(2) 初期データセット dataList を定義し、遷移行列の各 Score クラス オブジェクトを定義し、InitData() メソッドを呼び出してデータセットを初期化します。
(3) Score クラス オブジェクト v0Score を定義し、インスタンス化します。v0Score オブジェクトは 1/4 のスコア値を表します。これは、ユーザーが 4 つの Web ページ A、B、C、D をクリックする確率が同じ 1 であることを意味します。 /4. 4 つの v0Score を格納する 1 次元配列 V0 を定義し、初期 PageRank も V0 に割り当てます。
(4) while ループに入り、getPageRank() メソッドを呼び出して PageRank マトリックスを取得します。getPageRank() メソッドの本体で pageRankList コレクションを定義して最終的な PageRank 値を保存し、dataList データ セット内のデータ dataItem の各項目を走査し、for ループを使用して dataItem を走査します。これにより、dataItem と Vk が行列乗算、および行列乗算後の各項目の結果 itemSum に保存します。dataItm を走査した後、itemSum を pageRankList コレクションに追加します。データセット dataList コレクションを走査した後、pageRankList を配列に変換して返します。
(5) isRankEqual()メソッドを呼び出して、新たに取得したPageRankマトリクス値が前回取得したPageRankマトリクス値と同じかどうかを判定し、一致しない場合は繰り返しを継続し、同じであれば繰り返しを終了します。isRankEqual()メソッドは主に仮パラメータV1と仮パラメータV2のPageRank行列の値が等しいかどうかを判定し、ブール型の値を返すもので、メソッド本体は配列V1を走査してそれぞれの分子を比較します。 V1 の項目と V2 の各要素。項目の分子が同じかどうか、異なる場合は false を返し、走査後に違いがない場合は true を返します。
(6) 新たに取得した PageRank マトリクス値が前回取得した PageRank マトリクス値と異なる場合は、最終出力の pageRank 変数に新たに取得した PageRank マトリクス値を代入し、毎回取得した PageRank 値を出力します。

ソースコードを実現する

Score类
package com.data.mining.entity;

import lombok.Data;

@Data
public class Score {
    
    
    private int son;
    private int mom;

    public Score(){
    
    }

    public Score(int s, int m){
    
    
        son = s;
        mom = m;
    }

    /**
     * 分数相加并调用simplify方法进行约分
     * @param s1
     * @param s2
     * @return
     */
    public static Score getAdd(Score s1, Score s2){
    
    
        if (s1.getMom() == 0 || s2.getMom() == 0) return s1.getMom() == 0 ? s2 : s1;
        int commonMom = s1.getMom() * s2.getMom();
        int commonSon = s1.getSon() * s2.getMom() + s2.getSon() * s1.getMom();
        Score addResult = simplify(commonSon, commonMom);
        return addResult;
    }

    /**
     * 分数相乘并调用simplify方法进行约分
     * @param s1
     * @param s2
     * @return
     */
    public static Score getMultiply(Score s1, Score s2){
    
    
        int tempMom = s1.getMom() * s2.getMom();
        int tempSon = s1.getSon() * s2.getSon();
        Score simplifyResult = simplify(tempSon, tempMom);
        return simplifyResult;
    }

    /**
     * 对分子分母进行约分
     * @param s
     * @param m
     * @return
     */
    private static Score simplify(int s, int m){
    
    
        int common = getCommon(s, m);
        s = s / common;
        m = m / common;
        Score result = new Score(s, m);
        return result;
    }

    /**
     * 找分子分母的最大公约数
     * @param s
     * @param m
     * @return
     */
    private static int getCommon(int s, int m){
    
    
        for (int i = s; i >= 1; i--) {
    
    
            if (m%i==0 && s%i==0){
    
    
                return i;
            }
        }
        return 1;
    }
}

PageRank算法实现代码
package com.data.mining.main;

import com.data.mining.entity.Score;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class PageRank {
    
    
    //定义转移矩阵
    public static List<Score[]> dataList = new ArrayList<>();
    //定义转移矩阵中的每一项
    public static Score s00,s01,s02,s03,s10,s11,s12,s13,s20,s21,s22,s23,s30,s31,s32,s33;

    public static void main(String[] args) {
    
    
        initData();
        Score voScore = new Score(1, 4);
        Score[] V0 = {
    
    voScore, voScore, voScore, voScore};
        Score[] pageRank = V0;
        while (true){
    
    
            Score[] tmpVk = getPageRank(pageRank);
            if (isRankEqual(pageRank, tmpVk)) break; //新得到的PageRank矩阵和上次得到的PageRank矩阵不相同,则继续迭代,相同则不再迭代
            pageRank = tmpVk;
            System.out.println(Arrays.toString(pageRank));
        }
        System.out.println(Arrays.toString(pageRank));
    }

    /**
     * 判断V1和V2的PageRank矩阵内的值是否相等
     * @param V1
     * @param V2
     * @return
     */
    public static boolean isRankEqual(Score[] V1, Score[] V2){
    
    
        for (int i = 0; i < V1.length; i++) {
    
    
            int subSon = V1[i].getSon() - V2[i].getSon();
            int subMom = V1[i].getMom() - V2[i].getMom();
            if (subSon != 0 || subMom != 0) return false;
        }
        return true;
    }

    /**
     * 获取PageRank矩阵
     * @param Vk
     * @return
     */
    public static Score[] getPageRank(Score[] Vk){
    
    
        List<Score> pageRankList = new ArrayList<>();
        for (Score[] dataItem : dataList) {
    
    
            Score itemSum = new Score(0,0); //itemSum中存放PageRank矩阵的每一项
            //通过遍历数据集的每一行和Vk的每一列实现矩阵乘法
            for (int i = 0; i < dataItem.length; i++) {
    
    
                Score multiply = Score.getMultiply(dataItem[i], Vk[i]);
                itemSum = Score.getAdd(multiply, itemSum); //将对应项相乘的结果累加到itemSum中
            }
            pageRankList.add(itemSum);
        }
        return pageRankList.toArray(new Score[pageRankList.size()]);
    }

    /**
     * 初始化数据集
     */
    public static void initData(){
    
    
        s00 = new Score(0, 0);
        s01 = new Score(1, 2);
        s02 = new Score(1, 1);
        s03 = new Score(0, 0);
        s10 = new Score(1, 3);
        s11 = new Score(0, 0);
        s12 = new Score(0, 0);
        s13 = new Score(1, 2);
        s20 = new Score(1, 3);
        s21 = new Score(0, 0);
        s22 = new Score(0, 0);
        s23 = new Score(1, 2);
        s30 = new Score(1, 3);
        s31 = new Score(1, 2);
        s32 = new Score(0, 0);
        s33 = new Score(0, 0);

        Score[] s0 = {
    
    s00, s01, s02, s03};
        Score[] s1 = {
    
    s10, s11, s12, s13};
        Score[] s2 = {
    
    s20, s21, s22, s23};
        Score[] s3 = {
    
    s30, s31, s32, s33};

        dataList.add(s0);
        dataList.add(s1);
        dataList.add(s2);
        dataList.add(s3);
    }
}

実験結果
ここに画像の説明を挿入
この反復結果に直面して、著者はまだいくつかの疑問を抱いていますが、本書では最終的な反復結果は安定しており、最終結果は [3/9, 2/9, 2/9, 2/9] であると言われています。実験は最終的に満足のいく結果が得られず、データオーバーフローのためプログラムは直接終了しましたが、各反復の結果も含め、最後の出力結果は正解に非常に近いことがわかります。問題は見つかりませんでした。この写真の文字がなぜこんなに小さいのかわかりません。とにかく、はっきりと読めないので、表を使って記入してください。
ここに画像の説明を挿入

5. 実験の概要

著者は、この実験の結果が正しいことを保証するものではなく、Java 言語を使用して PageRank アルゴリズムを実装するアイデアを提供しているだけです。実験では答えが得られなかったので、著者は本に載っている答え付きの実験データをプログラムに入力し、プログラムが出力する結果は答えと一致しているので、問題は大きくないはずです。うまく書いていないところがあれば、ぜひご指摘ください!
著者のホームページには、他のデータ マイニング アルゴリズムの概要も掲載されています。ぜひご利用ください。

おすすめ

転載: blog.csdn.net/qq_54162207/article/details/128366809
おすすめ