1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

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

        共 1714字,需瀏覽 4分鐘

         ·

        2022-02-27 08:32

        需求背景

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

        1 兩人不能是好友

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

        例如,可以推薦的人:

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

        不可以推薦的人:

        趙子龍,因?yàn)橐呀?jīng)跨越了徐庶和諸葛亮兩個(gè)人了。曹操,因?yàn)閯浜筒懿倬褪呛糜选?/p>912a81d6aede64c7a72563d1f6282b1a.webp

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

        直接好友

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

        5a95b41b78ddf74becd308b20c9ba019.webp

        間接好友:

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

        1896a4ac7228f8527262853f5e38198f.webp

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

        然后,雖然曹操圈子里,關(guān)羽和劉備是間接好友關(guān)系,但是我們?cè)趧浜糜蚜斜碇姓业搅岁P(guān)羽,是直接好友。所以不能通過(guò)曹操給劉備推薦關(guān)羽。

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

        cc0aa4ce010825187d25814713c1dab8.webp

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

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

        76e896e8cd2dd77cc0d0887b5bfe8477.webp

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

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

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

        編寫程序

        mapper

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

        /**
        * @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中,我們對(duì)map產(chǎn)生的文件進(jìn)行讀取,由于兩兩一組,value是0代表直接關(guān)系,value是1代表間接關(guān)系。我們判斷如果這兩人有直接關(guān)系,存在為0的情況,這組推薦關(guān)系拋棄掉。如果都是1,我們就將每一組相同的key值相加,來(lái)判斷間接關(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值 每個(gè)key代表的是某個(gè)兩個(gè)人,同時(shí)分到一個(gè)組,值就是這兩個(gè)人到底是直接朋友,還是間接朋友
        * 如果最后循環(huán)最后,沒(méi)有一個(gè)是0的,那么兩個(gè)人肯定是間接關(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);
        // 獲取客戶端啟動(dòng) 指定參數(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);
        }

        }

        啟動(dòng)hadoop集群

        程序?qū)懞昧耍酉聛?lái)當(dāng)然是啟動(dòng)我們的hadoop集群了。

        a9b523658494940b1c0256fe44bfa159.webp

        配置啟動(dòng)參數(shù)

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

        8fd6816b4ce3dc2e883cece76a2077c5.webp

        啟動(dòng)客戶端

        然后我們開始運(yùn)行客戶端,得到如下文件。

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

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

        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

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


        c7b7be7d404a475c8c8d2b36e776539d.webp

        增加復(fù)雜度

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

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

        b3cd8c77349735d65c51d0e9966adf69.webp

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

        a55a5ab20d9255b19b20ad0311474b25.webp

        取消reduce

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

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

        輸出map文件如下:

        7605fd2990ae40fb04035d89ad4d2250.webp

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

        e2080a9b9dcecdd954a44a66b6502e4c.webp

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

        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
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            www.五月婷婷 | 天堂99 | 丁香五月婷婷在线 | 欧美图片区小说区 | 狼友视频主页 | 亚洲成A人片777777久久 | 肏屄视频一区 | 欧美色涩| 最近中文字幕免费mv第一季歌词強上 | 99re这里只有精品一区 |