楼主: 我的素质低
1330 0

〖移花接木〗Mllib机器学习工具包在Hadoop上的使用 [推广有奖]

已卖:2774份资源

学术权威

83%

还不是VIP/贵宾

-

TA的文库  其他...

〖素质文库〗

结构方程模型

考研资料库

威望
8
论坛币
23391 个
通用积分
28308.6707
学术水平
2705 点
热心指数
2881 点
信用等级
2398 点
经验
228576 点
帖子
2968
精华
52
在线时间
2175 小时
注册时间
2012-11-24
最后登录
2024-1-13

一级伯乐勋章 初级学术勋章 初级热心勋章 初级信用勋章 中级热心勋章 中级学术勋章 中级信用勋章 高级学术勋章 高级热心勋章 高级信用勋章 特级学术勋章

楼主
我的素质低 学生认证  发表于 2015-3-26 12:03:59 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

Hadoop是基于Java的数据计算平台,在我们公司得到了广泛应用。

     同样mllib也是我们算法组同学经常使用的一个机器学习工具包。但目前mllib工具包只提供了供C++程序调用的so链接库,没有可供java程序调用的jar包。由于这个需求有一定的普遍性,作者将mllib做了进一步封装,并通过jni的方式把其封装成了可供java程序调用的接口。





1      结构示意图





2      对mllib的二次封装



      原始的mllib开发包对模型的处理(训练,加载,预测)都是per model的,对于每一个模型都需要写一些重复类似的代码。实际应用中我们的模型也一般都是多个的(分行业,或分类目来做),不太会只是用一个大而泛的模型。mllib没有提供一个类似于Manager的类来管理多个模型。所以笔者对mllib进行了二次封装,能够让大家比较方便的通过配置来管理多个模型,也让大家从需要了解mlllib最底层的接口中解放出来。



封装的Manager类:

  1. class MlrManager
  2. {
  3. public:
  4.     MlrManager();
  5. virtual ~MlrManager();
  6. //提供的两个接口
  7. //初始化函数,输入为配置文件,以配置文件为驱动来加载模型
  8. bool Init(const char* pConf);
  9. //预测函数,输入为特征数组和模型编号,输出为预测分数
  10.     feature_t CalMlrScore(std::vector<feature_t>& vecFeatures,int nModel);
  11. private:
  12.     feature_t GetMlrScore(std::vector<feature_t>& vecFeatures,mllib::MlModel* pModel,ENUM_MODEL_TYPE enumModelType);
  13. private:
  14.     std::vector<mllib::MlModel*> m_vecModels;
  15.     int m_nTotalModelNum;
  16.     int m_nDefaultModelNum;
  17.     ENUM_MODEL_TYPE m_enumModelType;
  18.     mllib::MlModelManager m_modelManager;
  19. };
复制代码






MlrManager类被封装到了libMlrManagerJni.so链接库中,可供其它C++程序使用。


配置文件说明:




[PATH]


//设置root目录,后面的模型文件只需要指定相对这个root路径的相对路径即可


BASE_PATH = ./mlr_jni.tar/conf/


[MODEL]


//模型数目,指定了模型数目后,模型名就可以确定了:MODEL1 , MODEL2 …. MODEL${ TOTAL_MODEL_NUM }
TOTAL_MODEL_NUM = 4
//模型的类型(回归还是分类),不同的模型类型,预测时实现的方法是不一样的,一定要正确设置
#MODEL_TYPE = classification
MODEL_TYPE = regression
//指定具体某个模型使用的模型文件名称,不同的模型可以使用相同的模型文件。
MODEL1 = 1.model
MODEL2 = 2.model
MODEL3 = 3.model
MODEL4 = 3.model



MlrManager调用伪代码示例:


  1. #include "MlrManager.h"
  2. Main()
  3. {
  4.     MlrManager mlrMgr;
  5. mlrMgr.Init(confFile);
  6. vector<float> vecFeature(nFeatureSize);
  7. float fMlrScore = mlrMgr.CalMlrScore(vecFeature,1);
  8. }
复制代码



3 Jni封装成可供java调用的接口





3.1

封装后的java接口如下:

  1. public class MlrManagerJni{
  2. static {
  3.     //load链接库libMlrManagerJni.so,如果找不到libMlrManagerJni.so,该类将初始化失败
  4. System.loadLibrary("MlrManagerJni");
  5. }
  6. //接口初始化,输入为配置文件
  7. public native int mlr_init(String conf);
  8. //预测分数的接口,输入为特征字符串,特征分隔符,模型编号,输出为预测值
  9.     public native float mlr_calc(String features,String spliter , int nModel);
  10.     //释放接口
  11.     public native int mlr_destroy();
  12. }
复制代码






     具体如何封装的这里就不细说了,jni封装技术可以参考
http://www.searchtb.com/2010/12/how-to-run-jni-in-hadoop.html 如何在Hadoop集群运行jni程序),使用者也不用关心这个。下面介绍一下如何使用这个封装的接口。



3.2   开发阶段



把mlr_jni.tar包拷贝到开发机上,解压出来,解压后的目录结构如下:
conf/
conf/mlr.conf
conf/1.model
conf/2.model
……
conf/N.model
lib/
lib/ libMlrManagerJni.so
lib/ mlrmgrjni.jar


conf目录包含了mlr.conf配置文件,和一系列模型文件*.model。



lib目录包含了libMlrManagerJni.so,mlrmgrjni.jar两个文件,libMlrManagerJni.so是封装了原始mllib的C++接口,mlrmgrjni.jar是封装了libMlrManagerJni.so的java接口。


在Eclipse项目配置选项里把mlrmgrjni.jar加到classpath中。


MlrManagerJni调用伪代码示例:

  1. import mlr.MlrManagerJni;
  2. Mapper()
  3. {
  4. private MlrManagerJni m_mlrJni = new MlrManagerJni();
  5. public void configure(JobConf job) {
  6.     //初始化接口
  7.     m_mlrJni.mlr_init("./mlr_jni.tar/conf/mlr.conf")
  8. }
  9. public void map(){
  10.     //接口调用
  11.     fMlrScore = m_mlrJni.mlr_calc(strFeatures, MlrManager.FEATURE_SPLITER , nModel );
  12. )
  13. public void close() {
  14.     //释放接口
  15. if (m_mlrJni != null) {
  16.         m_mlrJni.mlr_destroy();
  17.         m_mlrJni = null;
  18.     }
  19. }
  20. }
  21. Run()
  22. {
  23.     //设置 lava.library.path路径,通过这个路径可以找到libMlrManagerJni.so链接库,MlrManagerJni接口初始化的时候需要加载这个链接库
  24.     conf.set("mapred.child.java.opts","-Djava.library.path=./mlr_jni.tar/lib");
  25.     //也可以通过如下这个方式来设置
  26.     //conf.set(“java.library.path”,” ./mlr_jni.tar/lib”);
  27. }
复制代码





3.3   运行阶段



      在运行环境中,把mlr_jni.jar拷贝到运行环境,解压出来。使用者把自己的模型文件拷贝到conf目录下,在mlr.conf文件中修改好相关配置,然后把conf目录和lib目录重新打包成mlr_jni.tar包。(注意这里的包名mlr_jni.tar是可以变的,但必须和java程序中有两处指定的包名是一致的)。


调用:

  1. hadoop jar -libjars ./lib/mlrmgrjni.jar mainClass -archives mlr_jni.tar ….
复制代码




-      libjars mlrmgrjni.jar选项会把mlrmgrjni.jar这个jar包添加到Mapreduce程序的java classpath中。
-      archives mlr_jni.tar选项,Hadoop Distributed Cache的机制将会把这个jar包拷贝到每一个task node,供MapReduce程序使用。这个选项等同于在hadoop程序中显示调用


  1. DistributedCache.addCacheArchive(“hdfs://path/mlr_jni.tar#mlr_jni.tar”,conf);
复制代码




3.4   常见错误

1)  Caused by: java.lang.NoClassDefFoundError: mlr/MlrManagerJni
java.lang.ClassNotFoundException: mlr.MlrManagerJni

原因:hadoop 命令行调用的时候没有加-libjars ./lib/mlrmgrjni.jar选项

2)  Caused by: java.lang.UnsatisfiedLinkError: no MlrManagerJni in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1709)


原因:MlrManagerJni 接口初始化失败,不能加载libMlrManagerJni.so。
hadoop 命令行调用的时候没有加-archives mlr_jni.tar选项,可以在hadoop WebUI上看下job的xml配置文件,mapred.cache.archives选项是否包含了mlr_jni.tar包,如下是一个包含了mlr_jni.tar包的例子:


mapred.cache.archives=hdfs://hdpnn:9000/home/hadoop/cluster-data/mapred/system/job_201012162127_130619/libjars/mlrmgrjni.jar,/home/hadoop/cluster-data/mapred/system/job_201012162127_130619/archives/mlr_jni.tar#mlr_jni.tar


还有可能是打mlr_jni.tar包的时候忘记把libMlrManagerJni.so文件放进lib目录中了。


文章出处:搜索技术博客-淘宝

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:Hadoop Mllib 移花接木 机器学习 lib sequence file java程序 实际应用 Mllib

已有 1 人评分论坛币 收起 理由
daazx + 10 精彩帖子

总评分: 论坛币 + 10   查看全部评分

心晴的时候,雨也是晴;心雨的时候,晴也是雨!
扣扣:407117636,欢迎一块儿吐槽!!

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群
GMT+8, 2026-1-2 05:25