开发文章

Hadoop好友推荐系统-画出决策图

Hadoop好友推荐系统-画出决策图
一、前端展示
1、jsp页面

复制内容到剪贴板
  1. <div style="margin:10px 0 40px 0;"></div>  
  2.    <div style="padding:20px 20px;">  
  3.   
  4.    <div style="padding-left: 30px;font-size: 15px;padding-top:10px;"><br>  
  5.        此页面用于寻找聚类中心,看图找到聚类中心的范围(x轴大于多少,y轴大于多少,在寻找聚类中心页面使用)<br>  
  6.        注意:决策图展示的不包含局部密度最大的点,所以在执行分类时需要把决策图中的聚类中心个数加1<br>  
  7.   
  8.    <br>  
  9.    <br>  
  10.    <a id="drawId" href="" class="easyui-linkbutton"   
  11.        data-options="iconCls:'icon-color_wheel',size:'large',iconAlign:'top'">画图</a>  
  12.   
  13.        <a id="showId" href="" class="easyui-linkbutton"   
  14.        data-options="iconCls:'icon-chart_line',size:'large',iconAlign:'top'">展示决策图</a>  
  15.    </div>  
  16.    </div>  
  17.    <div id="windowId" class="easyui-window" title="Decision Chart" data-options="minimizable:false,closed:true"   
  18.    style="width:550px;height:550px;padding:10px;">  
  19.        <img id="picId" src="" />  
  20.    </div>  

该页面只定义了两个按钮:画图和展示决策图,同时给定一个显示图片的位置。

2、js逻辑

复制内容到剪贴板
  1. var picId_path;  
  2. $(function() {  
  3.   
  4.     $('#drawId').bind('click'function(){  
  5.         console.info("draw pic");  
  6.         // 弹出进度框  
  7.         var win = $.messager.progress({  
  8.             title : 'Please waiting',  
  9.             msg : '画决策图中...',  
  10.             interval : '1200' //设置时间间隔较长   
  11.         });  
  12.         $.ajax({  
  13.             url : "cloud/cloud_drawDecisionChart.action",  
  14. //          data: {tableName:tableName},  
  15.             async:true,  
  16.             dataType:"json",  
  17.             context : document.body,  
  18.             success : function(data) {  
  19. //              console.info(data);  
  20.                 $.messager.progress('close');  
  21.                 var retMsg;  
  22.                 if("true"==data.flag){  
  23.                     picId_path=data.path;  
  24.                     retMsg='决策图生成成功!';  
  25.                 }else{  
  26.                     retMsg='决策图生成失败!';  
  27.                 }  
  28.                 $.messager.show({  
  29.                     title : '提示',  
  30.                     msg : retMsg  
  31.                 });  
  32.             }  
  33.         });  
  34.   
  35.     });  
  36.   
  37.     $('#showId').bind('click'function(){  
  38.         console.info("show pic");  
  39.         console.info("picId_src:"+picId_path);  
  40.         $("#picId").attr("src","pictures/decision_chart.png");//加载图片  
  41.   
  42.         $('#windowId').window('refresh');  
  43.         $('#windowId').window('open');  
  44.     });  
  45.   
  46.   
  47. });  

前端请求后台的URL是cloud/cloud_drawDecisionChart.action。

二、后台逻辑

1、action层

复制内容到剪贴板
  1. /** 
  2.      * 画决策图 
  3.      */  
  4.     public void drawDecisionChart(){  
  5.         String url =HUtils.getHDFSPath(HUtils.SORTOUTPUT);//指定绘图源数据的HDFS路径  
  6.         String file =Utils.getRootPathBasedPath("pictures\\decision_chart.png");//指定绘制的图片保存位置,默认为当前项目的pictures目录下的decision_chart.png  
  7.         Map<String,Object> map = new HashMap<String,Object>();  
  8.         map.put("path", file);  
  9.         try{  
  10.             DrawPic.drawPic(url, file);//绘制图片  
  11.         }catch(Exception e){  
  12.             e.printStackTrace();  
  13.             map.put("flag""false");  
  14.             Utils.write2PrintWriter(JSON.toJSONString(map));  
  15.             return ;  
  16.         }  
  17.         map.put("flag""true");  
  18.         Utils.write2PrintWriter(JSON.toJSONString(map));  
  19.         return ;  
  20.     }  

上述代码的关键语句是:

复制内容到剪贴板
  1. DrawPic.drawPic(url, file);//绘制图片  

 

2、绘制图片

DrawPic的定义如下:
这里使用jfreechart来进行决策图的绘制,代码虽多但是功能一目了然,结合注释不难理解。

复制内容到剪贴板
  1. /** 
  2.  * 这里使用jfreechart来进行图表绘制,实际应用中推荐使用matlab等专业绘图程序 
  3.  */  
  4. public class DrawPic {  
  5.   
  6.     /** 
  7.      * @param args 
  8.      * @throws IOException 
  9.      */  
  10.     public static void main(String[] args) throws IOException {  
  11.         String path = "hdfs://sparkproject1:9000/user/root/iris_deltadistance/part-r-00000";  
  12.         drawPic(path,null);  
  13.     }  
  14.   
  15.     public static void drawPic(String url,String file) throws FileNotFoundException, IOException {  
  16.         XYSeries xyseries = getXYseries(url);//获取绘制决策图的数据  
  17.         XYSeriesCollection xyseriescollection = new XYSeriesCollection(); // 再用XYSeriesCollection添加入XYSeries  
  18.                                                                             // 对象  
  19.         xyseriescollection.addSeries(xyseries);  
  20.   
  21.         // 创建主题样式  
  22.         StandardChartTheme standardChartTheme = new StandardChartTheme("CN");  
  23.         // 设置标题字体  
  24.         standardChartTheme.setExtraLargeFont(new Font("隶书", Font.BOLD, 20));  
  25.         // 设置图例的字体  
  26.         standardChartTheme.setRegularFont(new Font("宋书", Font.PLAIN, 15));  
  27.         // 设置轴向的字体  
  28.         standardChartTheme.setLargeFont(new Font("宋书", Font.PLAIN, 15));  
  29.         // 应用主题样式  
  30.         ChartFactory.setChartTheme(standardChartTheme);  
  31.         // JFreeChart chart=ChartFactory.createXYAreaChart("xyPoit", "点的标号",  
  32.         // "出现次数", xyseriescollection, PlotOrientation.VERTICAL, true, false,  
  33.         // false);  
  34.         JFreeChart chart = ChartFactory.createScatterPlot("决策图""点密度",  
  35.                 "点距离", xyseriescollection, PlotOrientation.VERTICAL, true,  
  36.                 falsefalse);//产生绘制结果  
  37. //      String file="d:/decision_chart.png";  
  38.         try {  
  39.             ChartUtilities.saveChartAsPNG(new File(file), chart,  
  40.                     470, 470);//保存绘制结果到图片  
  41.         } catch (IOException e) {  
  42.             // TODO Auto-generated catch block  
  43.             e.printStackTrace();  
  44.         }  
  45.         System.out.println(new java.util.Date()+": finished drawing the pic in "+file);  
  46.     }  
  47.   
  48.     //获取绘制决策图的x,y的值  
  49.     public static XYSeries getXY(String url) {  
  50.         XYSeries xyseries = new XYSeries("");  
  51.   
  52.         Path path = new Path(url);  
  53.         Configuration conf = HUtils.getConf();  
  54.         SequenceFile.Reader reader = null;  
  55.         try {  
  56.             reader = new SequenceFile.Reader(conf, Reader.file(path),  
  57.                     Reader.bufferSize(4096), Reader.start(0));  
  58.             DoubleArrStrWritable dkey = (DoubleArrStrWritable) ReflectionUtils.newInstance(  
  59.                     reader.getKeyClass(), conf);  
  60.             DoublePairWritable dvalue = (DoublePairWritable) ReflectionUtils.newInstance(  
  61.                     reader.getValueClass(), conf);  
  62.   
  63.             while (reader.next(dkey, dvalue)) {// 循环读取文件  
  64.                 xyseries.add(dvalue.getFirst(), dvalue.getSecond());  
  65.             }  
  66.         } catch (Exception e) {  
  67.             e.printStackTrace();  
  68.         } finally {  
  69.             IOUtils.closeStream(reader);  
  70.         }  
  71.         return xyseries;  
  72.     }  
  73.   
  74.     /** 
  75.      * return the x*y 
  76.      * @param url 
  77.      * @return 
  78.      */  
  79.     public Double[] getR(String url){  
  80.         List<Double> list = new ArrayList<Double>();  
  81.         Path path = new Path(url);  
  82.         Configuration conf = HUtils.getConf();  
  83.         SequenceFile.Reader reader = null;  
  84.         try {  
  85.             reader = new SequenceFile.Reader(conf, Reader.file(path),  
  86.                     Reader.bufferSize(4096), Reader.start(0));  
  87.             DoubleArrStrWritable dkey = (DoubleArrStrWritable) ReflectionUtils.newInstance(  
  88.                     reader.getKeyClass(), conf);  
  89.             DoublePairWritable dvalue = (DoublePairWritable) ReflectionUtils.newInstance(  
  90.                     reader.getValueClass(), conf);  
  91.   
  92.             while (reader.next(dkey, dvalue)) {// 循环读取文件  
  93. //              list.add(dvalue.getSum()*dvalue.getDistance());  
  94.             }  
  95.         } catch (Exception e) {  
  96.             e.printStackTrace();  
  97.         } finally {  
  98.             IOUtils.closeStream(reader);  
  99.         }  
  100.         Double[] dList = new Double[list.size()];  
  101.         dList= list.toArray(dList);  
  102.         Arrays.sort(dList);  
  103.         return dList;  
  104.     }  
  105.   
  106.     /** 
  107.      * 每个数据文件提取最多500个数据点, 
  108.      * 前面500条记录包含的局部密度和最小距离的乘积的最大的500个,后面的点更不可能成为聚类中心点。 
  109.      * 在提取完成之后,获得所有数据的前100个最大的数据点存储在本地文件中 
  110.      * 供在用户看决策图后选择类别后写入中心点 
  111.      * 每个数据点文件需要先进行排序(从大到小,所以在MR任务中增加了一个) 
  112.      * @param url 
  113.      * @return 
  114.      * @throws IOException  
  115.      * @throws FileNotFoundException  
  116.      */  
  117.     public static XYSeries getXYseries(String url) throws FileNotFoundException, IOException{  
  118.         XYSeries xyseries = new XYSeries("");  
  119.   
  120.         List<IDistanceDensityMul> list = getIDistanceDensityMulList(url);  
  121.   
  122.         for(IDistanceDensityMul l:list){  
  123.             xyseries.add(l.getDensity(), l.getDistance());  
  124.         }  
  125.   
  126.         return xyseries;  
  127.     }  
  128.   
  129.     private static List<IDistanceDensityMul> getIDistanceDensityMulList(String url) throws FileNotFoundException, IOException{  
  130.         Configuration conf = HUtils.getConf();  
  131.         SequenceFile.Reader reader = null;  
  132.         // 多个文件整合,需排序  
  133.         List<IDistanceDensityMul> allList= new ArrayList<IDistanceDensityMul>();  
  134.         // 单个文件  
  135.         List<IDistanceDensityMul> fileList= new ArrayList<IDistanceDensityMul>();  
  136.   
  137.         FileStatus[] fss=HUtils.getHDFSPath(url,"true").getFileSystem(conf)  
  138.                 .listStatus(HUtils.getHDFSPath(url, "true"));  
  139.         for(FileStatus f:fss){  
  140.             if(!f.toString().contains("part")){  
  141.                 continue// 排除其他文件  
  142.             }  
  143.             try {  
  144.                 reader = new SequenceFile.Reader(conf, Reader.file(f.getPath()),  
  145.                         Reader.bufferSize(4096), Reader.start(0));  
  146. //               <density_i*min_distancd_j> <first:density_i,second:min_distance_j,third:i>  
  147. //                  DoubleWritable,  IntDoublePairWritable  
  148.                 CustomDoubleWritable dkey = (CustomDoubleWritable) ReflectionUtils.newInstance(  
  149.                         reader.getKeyClass(), conf);  
  150.                 IntDoublePairWritable dvalue = (IntDoublePairWritable) ReflectionUtils.newInstance(  
  151.                         reader.getValueClass(), conf);  
  152.                 int i=Utils.GETDRAWPICRECORDS_EVERYFILE;//默认设置为500个点  
  153.                 while (reader.next(dkey, dvalue)&&i>0) {// 循环读取文件  
  154.                     i--;  
  155.                     fileList.add(new IDistanceDensityMul(dvalue.getSecond(),  
  156.                             dvalue.getFirst(),dvalue.getThird(),dkey.get()));// 每个文件都是从小到大排序的  
  157.                 }  
  158.             } catch (Exception e) {  
  159.                 e.printStackTrace();  
  160.             } finally {  
  161.                 IOUtils.closeStream(reader);  
  162.             }  
  163.   
  164.             // 整合当前文件的前面若干条记录(Utils.GETDRAWPICRECORDS_EVERYFILE     )  
  165.             if(allList.size()<=0){// 第一次可以全部添加  
  166.                 allList.addAll(fileList);  
  167.             }else{  
  168.                 combineLists(allList,fileList);  
  169.             }  
  170.         }//for  
  171.         //第一个点太大了,选择去掉  
  172.         return allList.subList(1, allList.size());  
  173.     }  
  174.   
  175.     /** 
  176.      * 按照mul的值进行排序,从大到小排序 
  177.      * @param list1 
  178.      * @param list2 
  179.      */  
  180.     private static void combineLists(List<IDistanceDensityMul> list1,  
  181.             List<IDistanceDensityMul> list2) {  
  182.         List<IDistanceDensityMul> allList = new ArrayList<IDistanceDensityMul>();  
  183.         int sizeOne=list1.size();  
  184.         int sizeTwo = list2.size();  
  185.   
  186.         int i,j;  
  187.         for(i=0,j=0;i<sizeOne&&j<sizeTwo;){  
  188.             if(list1.get(i).greater(list2.get(j))){  
  189.                 allList.add(list1.get(i++));  
  190.             }else{  
  191.                 allList.add(list2.get(j++));  
  192.             }  
  193.         }  
  194.         if(i<sizeOne){// list1 has not finished  
  195.             allList.addAll(list1.subList(i, sizeOne));  
  196.         }  
  197.         if(j<sizeTwo){// list2 has not finished  
  198.             allList.addAll(list2.subList(j, sizeTwo));  
  199.         }  
  200.         // 重新赋值  
  201.         list1.clear();  
  202.         list1.addAll(allList);  
  203.         allList.clear();  
  204.     }  
  205.   
  206. }  

三、程序运行截图

程序运行截图.png

聚类中心应该是取局部密度和点距离都比较大的点,在决策图上看就是右上角位置的点,所以这里选择去点密度大于50,点距离大于50的点,这里有3个,加上没有画出来的局部密度最大的点,一共有4个聚类中心向量。

感谢 想作会飞的鱼 支持 磐实编程网 原文地址:
blog.csdn.net/xiaokang123456kao/article/details/75026179

文章信息

发布时间:2017-07-14

作者:想作会飞的鱼

发布者:aquwcw

浏览次数: