您的位置:首页 > 运维架构

Hadoop好友推荐系统-寻找最佳DC

2017-07-13 09:33 507 查看

项目总目录:基于Hadoop的好友推荐系统项目综述

一、寻找最佳DC

1、前端展示

jsp页面

<div style="padding-left: 30px;font-size: 20px;padding-top:10px;">
<table>
<tr>
<td><label for="name">输入路径:</label>
</td>
<td><input class="easyui-validatebox" type="text"
id="findbestdc_input_id" data-options="required:true" style="width:300px"
value="/user/root/_filter/caldistance" /></td>

</tr>

<tr>
<td><label for="name">输入记录数:</label>
</td>
<td><input class="easyui-validatebox" type="text"
id="findbestdc_record_id" data-options="required:true" style="width:300px"
value="0" /></td>
<td><label for="name">如果已经运行了距离计算MR,可以不用设置此值</label></td>

</tr>

<tr>
<td><label for="name">阈值百分比:</label>
</td>
<td><input class="easyui-validatebox" type="text"
id="findbestdc_delta_id" data-options="required:true" style="width:300px"
value="2%" /></td>

</tr>
<tr>
<td></td>
<td><a id="findbestdc_submit_id" href="" class="easyui-linkbutton"
data-options="iconCls:'icon-door_in'">定位最佳DC</a></td>
</tr>

</table>
</div>

<div id="dc_return_id" style="padding-left: 30px;font-size: 20px;padding-top:10px;"></div>


jsp页面需要设置文件输入路径(默认就是距离计算任务的输出路径)、输入记录数(可以手工设置,如果运行过距离计算任务,则该值以保存在后台中,不需要手动设置)、阈值百分比(默认2%)。

js逻辑

//findbestdc_submit_id 找到最佳阈值
$('#findbestdc_submit_id').bind('click', function(){
var input_=$('#findbestdc_input_id').val();
var delta_=$('#findbestdc_delta_id').val();
var record_=$('#findbestdc_record_id').val();
// 弹出进度框
popupProgressbar('请等待','寻找最佳阈值DC中...',1000);
// ajax 异步提交任务
callByAJaxLocal_findbestdc('cloud/cloud_findbestdc.action',{input:input_,delta:delta_,record:record_});
});


这里使用callByAJaxLocal_findbestdc方法实现任务提交,其定义如下:如果任务执行成功,它将后台返回数据中的dc写入到前端的相应位置。

function callByAJaxLocal_findbestdc(url,data_){
$.ajax({
url : url,
data: data_,
async:true,
dataType:"json",
context : document.body,
success : function(data) {
//          $.messager.progress('close');
closeProgressbar();
console.info("data.flag:"+data.flag);
var retMsg;
if("true"==data.flag){
retMsg='操作成功!DC阈值为:'+data.dc;
$('#dc_return_id').html("推荐DC阈值为:"+data.dc);//将结果写入前端页面
}else{
retMsg='操作失败!失败原因:'+data.msg;
}
$.messager.show({
title : '提示',
msg : retMsg
});

}
});
}


后台逻辑

action层

对应的action从这里获取:callByAJaxLocal_findbestdc(‘cloud/cloud_findbestdc.action’,)

/**
* 遍历向量距离文件,寻找最佳阈值
*/
public void findbestdc(){
double dc=0.0;
Map<String,Object> map = new HashMap<String,Object>();
int recordInt = Integer.parseInt(record);
if(HUtils.INPUT_RECORDS==0&&recordInt!=0){
HUtils.INPUT_RECORDS=recordInt;
}
try{
if(HUtils.INPUT_RECORDS==0){
map.put("flag", "false");
map.put("msg", "请先运行计算距离MR任务,或者设置任务运行后的记录数!");
Utils.write2PrintWriter(JSON.toJSONString(map));
return ;
}
dc=HUtils.findInitDC(Double.parseDouble(delta.substring(0, delta.length()-1))/100, input,
HUtils.INPUT_RECORDS);
//前端传过来的delta是字符串"2%",substring(0, delta.length()-1))截取的就是"2",然后转为double除以100即可。
//public String substring(int beginIndex, int endIndex)返回一个新字符串,
//它是此字符串的一个子字符串。该子字符串从指定的 beginIndex 处开始,直到索引 endIndex - 1 处的字符。因此,该子字符串的长度为 endIndex-beginIndex。
}catch(Exception e){
e.printStackTrace();
map.put("flag", "false");
map.put("msg", e.getMessage());
Utils.write2PrintWriter(JSON.toJSONString(map));
return ;
}
map.put("flag", "true");
map.put("dc", dc);
Utils.simpleLog(JSON.toJSONString(map));
Utils.write2PrintWriter(JSON.toJSONString(map));
return;
}


其中的关键语句是

dc=HUtils.findInitDC(Double.parseDouble(delta.substring(0, delta.length()-1))/100, input,
HUtils.INPUT_RECORDS);


寻找最佳DC

HUtils.findInitDC的定义如下:

/**
* 根据给定的阈值百分比返回阈值,输入参数为阀值百分比、输入路径和总记录数
* 因为距离计算的MapReduce任务输出文件自动按照用户间的距离从小到大排序,所以计算阀值只需截取操作即可。
* @param percent
*            一般为1~2%
* @return
*/
public static double findInitDC(double percent, String path,long iNPUT_RECORDS2) {
Path input = null;
if (path == null) {
input = new Path(HUtils.getHDFSPath(HUtils.FILTER_CALDISTANCE
+ "/part-r-00000"));
} else {
input = new Path(HUtils.getHDFSPath(path + "/part-r-00000"));//初始化输入路径
}
Configuration conf = HUtils.getConf();
SequenceFile.Reader reader = null;
long counter = 0;
long percent_ = (long) (percent * iNPUT_RECORDS2);//计算截取的下标值(按前2%计算)
try {
reader = new SequenceFile.Reader(conf, Reader.file(input),
Reader.bufferSize(4096), Reader.start(0));
DoubleWritable dkey = (DoubleWritable) ReflectionUtils.newInstance(
reader.getKeyClass(), conf);
Writable dvalue = (Writable) ReflectionUtils.newInstance(
reader.getValueClass(), conf);
while (reader.next(dkey, dvalue)) {// 从小到大依次遍历距离结果文件
counter++;
if(counter%1000==0){//每1000个数据输出一个log
Utils.simpleLog("读取了"+counter+"条记录。。。");
}
if (counter >= percent_) {//遍历到了阀值下标处
HUtils.DELTA_DC = dkey.get();// 赋予最佳DC阈值
break;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
IOUtils.closeStream(reader);
}
return HUtils.DELTA_DC;//返回最佳DC的值
}


二、程序运行截图



这里的阀值百分比需要人为设置,这个值将影响DC值得选取,从而影响整个分类算法的准确性,需要经过多次尝试才能得出最佳的阀值百分比。关于该值的如何选取尚未有相关研究,在新型算法的论文中也提到这个值是个经验选取值,推荐在1%-2%,但是有时候得到的分类情况并不理想。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: