<kbd id="5sdj3"></kbd>
<th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>

    hadoop之MapReduce推薦系統(tǒng)實戰(zhàn)

    共 1714字,需瀏覽 4分鐘

     ·

    2022-02-27 08:32

    需求背景

    前邊已經(jīng)使用mapReduce找到了每個月中溫度最高的兩天?,F(xiàn)在我們來看看平時的社交軟件,推薦系統(tǒng)的機(jī)制是怎樣的,其實也是非常簡單。如下圖所示,我們需要給每個人推薦好友,既然是推薦的,肯定需要符合以下規(guī)則:

    1 兩人不能是好友

    2 兩人最有可能認(rèn)識,定義關(guān)系鏈條只能跨越一個人,不能跨越兩個人。

    例如,可以推薦的人:

    從下圖,我們可以看出來,要給劉備推薦的好友列表是:諸葛亮(徐庶推薦),馬超(劉璋推薦),貂蟬(袁紹推薦),呂布(袁紹推薦),夏侯惇(曹操推薦),龐統(tǒng)(魯肅推薦),孫權(quán)(魯肅推薦)。

    不可以推薦的人:

    趙子龍,因為已經(jīng)跨越了徐庶和諸葛亮兩個人了。曹操,因為劉備和曹操就是好友。

    912a81d6aede64c7a72563d1f6282b1a.webp

    接下來我們知道了規(guī)則之后,我們先將圖譜分為兩個map,其中一個map用來匹配直接關(guān)系,一個map用來匹配間接關(guān)系。然后從間接關(guān)系中排除掉直接關(guān)系,剩下的就是可以推薦的人選。

    直接好友

    如下圖示例,我們先列出來這22個人的直接關(guān)系數(shù)據(jù),只要是兩者相連的的,肯定是直接好友。

    5a95b41b78ddf74becd308b20c9ba019.webp

    間接好友:

    如下圖,由于一個人的朋友圈的人,很可能相互認(rèn)識,所以只要是和這個人認(rèn)識的,都是間接好友關(guān)系。當(dāng)然,可能這兩個間接好友,早都已經(jīng)加了好友了。

    1896a4ac7228f8527262853f5e38198f.webp

    劉備認(rèn)識曹操,曹操圈子里,劉備和夏侯惇是間接好友關(guān)系。然后我們看到劉備的直接好友里面沒有夏侯惇,這個時候我們就可以通過曹操給劉備推薦夏侯惇。

    然后,雖然曹操圈子里,關(guān)羽和劉備是間接好友關(guān)系,但是我們在劉備好友列表中找到了關(guān)羽,是直接好友。所以不能通過曹操給劉備推薦關(guān)羽。

    而且我們看到了,目前只有22個人的時候,我們可以很輕松的列出來直接好友關(guān)系,但是間接好友的數(shù)據(jù)量就會是比較龐大的。因此我們開始借助程序來完成好友推薦功能。

    cc0aa4ce010825187d25814713c1dab8.webp

    數(shù)據(jù)模型

    首先第一步當(dāng)然是根據(jù)需求來構(gòu)建我們的數(shù)據(jù)模型了,讓我們的程序能夠更好的批量處理數(shù)據(jù)之間的關(guān)系。以下便是我們此次構(gòu)建出來的數(shù)據(jù)模型,每一行代表第一個人與后邊的人都是直接好友關(guān)系。(數(shù)據(jù)模型后續(xù)有更改,不可直接搬運,不過出錯了可以自己調(diào)節(jié)也算是鍛煉?。?!)

    76e896e8cd2dd77cc0d0887b5bfe8477.webp

    上傳數(shù)據(jù)文件

    數(shù)據(jù)模型建立好之后,我們就該上傳文件至hdfs了。

    hdfs dfs -D dfs.blocksize=1048576 -put friend.txt /data/friend/input

    編寫程序

    mapper

    map中,我們主要是通過遍歷每一行,來將每一行的直接朋友關(guān)系和間接朋友關(guān)系寫入文件中。很顯然,每一行的第一列和后邊的所有列都是直接好友。從第二列開始,兩兩互成間接好友關(guān)系。同時我們將兩個人關(guān)系進(jìn)行排序,否則,劉備-關(guān)羽,和關(guān)羽-劉備 程序會識別為不同的組合。

    /**
    * @author Ted
    * @version 1.0
    * @date 2022/2/2 16:19
    */
    public class FMapper extends Mapper<LongWritable,Text,Text,IntWritable> {

    Text mkey = new Text();
    IntWritable mval = new IntWritable();

    /**
    * 劉備 劉璋 關(guān)羽 徐庶 張飛 袁紹 曹操 魯肅
    * 徐庶 諸葛亮 劉備
    * 袁紹 呂布 劉備 曹操 貂蟬
    * @param key
    * @param value
    * @param context
    * @throws IOException
    * @throws InterruptedException
    */
    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
    //value:劉備 劉璋 關(guān)羽 徐庶 張飛 袁紹 曹操 魯肅
    String[] directFriends = StringUtils.split(value.toString(), ' ');

    //間接關(guān)系為1 , 直接關(guān)系為 0
    for (int i=1;i<directFriends.length;i++){
    mkey.set(getFriendPair(directFriends[0],directFriends[i]));
    mval.set(0);
    // 寫入文件
    context.write(mkey,mval);
    for (int j=i+1;j<directFriends.length;j++){
    mkey.set(getFriendPair(directFriends[i],directFriends[j]));
    mval.set(1);
    //寫入文件
    context.write(mkey,mval);
    }
    }

    }

    /**
    * 排序
    * @param person1
    * @param person2
    * @return
    */
    public static String getFriendPair(String person1,String person2){
    if(person1.compareTo(person2)>0){
    return person1+"-"+person2;
    }else {
    return person2+"-"+person1;
    }
    }

    }

    reducer

    reduce中,我們對map產(chǎn)生的文件進(jìn)行讀取,由于兩兩一組,value是0代表直接關(guān)系,value是1代表間接關(guān)系。我們判斷如果這兩人有直接關(guān)系,存在為0的情況,這組推薦關(guān)系拋棄掉。如果都是1,我們就將每一組相同的key值相加,來判斷間接關(guān)系的權(quán)重。

    /**
    * @author Ted
    * @version 1.0
    * @date 2022/2/2 16:33
    */
    public class FReduce extends Reducer<Text,IntWritable,Text,IntWritable> {

    IntWritable rValue = new IntWritable();

    /**
    * 一組key值 每個key代表的是某個兩個人,同時分到一個組,值就是這兩個人到底是直接朋友,還是間接朋友
    * 如果最后循環(huán)最后,沒有一個是0的,那么兩個人肯定是間接關(guān)系,rValue就是間接關(guān)系的深度
    * 如果間接關(guān)系深厚,關(guān)聯(lián)的好友很多,那么就優(yōu)先推薦。
    * @param key
    * @param values
    * @param context
    * @throws IOException
    * @throws InterruptedException
    */
    @Override
    protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
    // 劉備 關(guān)羽 0
    // 劉備 關(guān)羽 0
    // 劉備 關(guān)羽 1
    // 劉備 關(guān)羽 1
    int flag = 0;
    int sum = 0;

    for (IntWritable val: values){
    if(val.get()==0){
    flag = 1;
    }
    sum = val.get();
    }

    if(flag == 0){
    rValue.set(sum);
    context.write(key,rValue);
    }
    }
    }

    客戶端程序

    /**
    * @author Ted
    * @version 1.0
    * @date 2022/2/2 16:16
    */
    public class MyFriend {

    public static void main(String[] args) throws Exception{
    Configuration configuration = new Configuration(true);
    // 獲取客戶端啟動 指定參數(shù)列表
    String[] params = new GenericOptionsParser(configuration, args).getRemainingArgs();

    configuration.set("mapreduce.app-submission.cross-platform","true");

    // 創(chuàng)建任務(wù)
    Job job = Job.getInstance(configuration);
    job.setJarByClass(MyFriend.class);
    job.setJobName("myFriend");
    job.setJar("D:\\javaEngineer\\javaproject\\hadoop\\hadoophdfs\\target\\hadoop-hdfs-1.0-0.1.jar");

    // 輸入路徑
    TextInputFormat.addInputPath(job,new Path(params[0]));
    Path outputFile = new Path(params[1]);
    if(outputFile.getFileSystem(configuration).exists(outputFile)){
    outputFile.getFileSystem(configuration).delete(outputFile,true);
    }
    // 輸出路徑
    TextOutputFormat.setOutputPath(job,outputFile);
    // 設(shè)置Map 參數(shù)
    job.setMapperClass(FMapper.class);
    job.setMapOutputKeyClass(Text.class);
    job.setMapOutputValueClass(IntWritable.class);

    //設(shè)置reduce參數(shù)
    job.setReducerClass(FReduce.class);
    // 執(zhí)行任務(wù) 等待結(jié)束
    job.waitForCompletion(true);
    }

    }

    啟動hadoop集群

    程序?qū)懞昧耍酉聛懋?dāng)然是啟動我們的hadoop集群了。

    a9b523658494940b1c0256fe44bfa159.webp

    配置啟動參數(shù)

    接下來我們來指定mapReduce需要的參數(shù),其中輸入路徑和輸出路徑是最基本的要求,剩下的排序分組分區(qū)我們都采用系統(tǒng)默認(rèn)的方式。

    8fd6816b4ce3dc2e883cece76a2077c5.webp

    啟動客戶端

    然后我們開始運行客戶端,得到如下文件。

    hdfs dfs -ls -R /data/friend
    1994705b1569c0b3adc19942f14cbdd3.webp

    我們可以看看里面的內(nèi)容是不是和真實的場景相吻合。

    hdfs dfs -cat /data/friend/output/part-r-00000

    亂碼

    ebbd8a5445ee6d3ba01f311d7e2d516e.webp

    分析原因

    可以看到上傳的文件也是亂碼的。

    fa73ed0e61a61e476b8f1784a81fb820.webp

    將文件另存為為UTF-8編碼格式之后,文件正常

    06866ec0c77d64c11214c009e3b42302.webp

    重啟客戶端

    輸出結(jié)果如下。

    劉璋-關(guān)羽 1
    呂布-劉備 1
    周瑜-劉備 1
    夏侯惇-關(guān)羽 1
    夏侯惇-劉備 1
    孫權(quán)-關(guān)羽 1
    孫權(quán)-劉備 1
    孫權(quán)-夏侯惇 1
    孫權(quán)-大喬 1
    孫策-周瑜 1
    孫策-大喬 1
    小喬-周瑜 1
    小喬-孫權(quán) 1
    龐統(tǒng)-劉備 1
    龐統(tǒng)-周瑜 1
    龐統(tǒng)-孫權(quán) 1
    張飛-劉璋 1
    徐庶-關(guān)羽 1
    徐庶-劉璋 1
    徐庶-張飛 1
    曹操-劉璋 1
    曹操-呂布 1
    曹操-周瑜 1
    曹操-孫策 1
    曹操-張飛 1
    曹操-徐庶 1
    袁紹-關(guān)羽 1
    袁紹-劉璋 1
    袁紹-夏侯惇 1
    袁紹-孫權(quán) 1
    袁紹-張飛 1
    袁紹-徐庶 1
    諸葛亮-劉備 1
    諸葛亮-周瑜 1
    諸葛亮-孫權(quán) 1
    諸葛瑾-孫策 1
    諸葛瑾-徐庶 1
    諸葛瑾-曹操 1
    貂蟬-劉備 1
    貂蟬-曹操 1
    趙子龍-徐庶 1
    趙子龍-諸葛瑾 1
    馬超-劉備 1
    魯肅-關(guān)羽 1
    魯肅-劉璋 1
    魯肅-大喬 1
    魯肅-孫策 1
    魯肅-張飛 1
    魯肅-徐庶 1
    魯肅-曹操 1
    魯肅-袁紹 1
    魯肅-諸葛瑾 1
    黃忠-徐庶 1
    黃忠-諸葛瑾 1
    黃忠-趙子龍 1

    我們截取給曹操推薦的朋友圈人選

    曹操-劉璋 1 曹操-呂布 1 曹操-周瑜 1 曹操-孫策 1 曹操-張飛 1 曹操-徐庶 1
    魯肅-曹操 1 貂蟬-曹操 1 諸葛瑾-曹操 1

    再來看下關(guān)系圖譜,可以看出來是正確的,權(quán)重關(guān)系都為1。


    c7b7be7d404a475c8c8d2b36e776539d.webp

    增加復(fù)雜度

    接下來我們增加一下關(guān)系復(fù)雜度,讓徐庶加張飛和關(guān)羽好友,讓諸葛亮加劉備為好友,接下來,諸葛亮通過徐庶和劉備兩個人,會和張飛關(guān)羽分別產(chǎn)生兩次間接關(guān)系。圖譜變?yōu)槿缦聵幼樱?/p>f9c18964f1c6bd4c9b5d33dc8ffc94c8.webp

    數(shù)據(jù)模型變?yōu)槿缦聵幼?,再次上傳文件,運行客戶端程序。

    b3cd8c77349735d65c51d0e9966adf69.webp

    得到結(jié)果如下,發(fā)現(xiàn)并不是想象的樣子。

    a55a5ab20d9255b19b20ad0311474b25.webp

    取消reduce

    接下來我們?nèi)∠鹯educe任務(wù),只進(jìn)行輸出map文件,來調(diào)節(jié)bug。

    // 如果將reduce任務(wù)設(shè)置為0,那么就可以得到map輸出
    job.setNumReduceTasks(0);

    輸出map文件如下:

    7605fd2990ae40fb04035d89ad4d2250.webp

    很明顯,從map中,我們看到了兩個諸葛亮-關(guān)羽,兩個諸葛亮-張飛,因此reduce中的代碼是有錯誤的。并沒有正確完成權(quán)重相加。

    e2080a9b9dcecdd954a44a66b6502e4c.webp

    最后發(fā)現(xiàn)代碼書寫錯誤,居然只寫了等于號。

    56c73847167f418fd8fe55de223b3271.webp

    修改代碼,程序正確之后,我們重新maven打包。一定要maven打包,不然jar中的代碼還是原先的代碼。

    286714cca49a9ff37c8b4592a7c8c30e.webp

    添加reduce

    修改代碼,再次開放reduce任務(wù)。獲取結(jié)果如下。可以看到,諸葛亮-關(guān)羽的權(quán)重是2,諸葛亮-張飛的權(quán)重是2,應(yīng)該優(yōu)先給諸葛亮推送張飛和關(guān)羽這兩位好朋友。

    927de0341c472bfc904b0e768010eadc.webp

    最終結(jié)果如下圖,我們可以總hadoop的web端下載文件。

    劉璋-關(guān)羽 1
    呂布-劉備 1
    周瑜-劉備 1
    夏侯惇-關(guān)羽 1
    夏侯惇-劉備 1
    孫權(quán)-關(guān)羽 1
    孫權(quán)-劉備 2
    孫權(quán)-夏侯惇 1
    孫權(quán)-大喬 1
    孫策-周瑜 1
    孫策-大喬 1
    小喬-周瑜 1
    小喬-孫權(quán) 1
    龐統(tǒng)-劉備 1
    龐統(tǒng)-周瑜 1
    龐統(tǒng)-孫權(quán) 1
    張飛-劉璋 1
    徐庶-劉璋 1
    曹操-劉璋 1
    曹操-呂布 1
    曹操-周瑜 1
    曹操-孫策 1
    曹操-張飛 2
    曹操-徐庶 1
    袁紹-關(guān)羽 2
    袁紹-劉璋 1
    袁紹-夏侯惇 1
    袁紹-孫權(quán) 1
    袁紹-張飛 1
    袁紹-徐庶 1
    諸葛亮-關(guān)羽 2
    諸葛亮-劉璋 1
    諸葛亮-周瑜 1
    諸葛亮-孫權(quán) 1
    諸葛亮-張飛 2
    諸葛亮-曹操 1
    諸葛亮-袁紹 1
    諸葛瑾-劉備 1
    諸葛瑾-孫策 1
    諸葛瑾-徐庶 1
    諸葛瑾-曹操 1
    貂蟬-劉備 1
    貂蟬-曹操 1
    趙子龍-劉備 1
    趙子龍-徐庶 1
    趙子龍-諸葛瑾 1
    馬超-劉備 1
    魯肅-關(guān)羽 1
    魯肅-劉璋 1
    魯肅-大喬 1
    魯肅-孫策 1
    魯肅-張飛 1
    魯肅-徐庶 1
    魯肅-曹操 2
    魯肅-袁紹 1
    魯肅-諸葛亮 1
    魯肅-諸葛瑾 1
    黃忠-劉備 1
    黃忠-徐庶 1
    黃忠-諸葛瑾 1
    黃忠-趙子龍 1



    瀏覽 56
    點贊
    評論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報
    評論
    圖片
    表情
    推薦
    點贊
    評論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報

    <kbd id="5sdj3"></kbd>
    <th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>
    日韩国产一级无码 | 午夜福利成人视频 | 成人黄片AV256 | 无码日韩电影 | 日本黄色一区二区三区 |