1. 简介

  Apache Hivemall是机器学习算法(machine learning algorithms)和多功能数据分析函数(versatile data analytics functions)的集合,它通过Apache Hive UDF / UDAF / UDTF接口提供了一些易于使用的机器学习算法。Hivemall 最初由Treasure Data 开发的,并于2016年9月捐献给 Apache 软件基金会,进入了Apache 孵化器。

Apache Hivemall提供了各种功能包括:回归(regression)、分类(classification)、推荐(recommendation)异常检测(anomaly detection)、k-最近邻(k-nearest neighbor)以及特征工程(feature engineering)。同时它还支持最先进的机器学习算法,如软信度加权(Soft Confidence Weighted)、权重向量的自适应正则化(Adaptive Regularization of Weight Vectors)、因式分解机(Factorization Machines)和AdaDelta。

1.1. 架构

Apache Hivemall 设计主要是运行在Apache Hive之上,但是还支持在Apache Pig 和 Apache Spark 上运行。所以我们也可以把它当做是一个跨平台的机器学习类库。我们可以通过Apache Hive构建预测模型然后在Apache Spark/Pig上使用;反之也是可以的。
架构如下所示:
Hivemall架构

2. 开始运行

2.1. 安装

2.1.1. 前置条件

  • Hadoop v2.4.0 or later
  • Hive v0.13 or later
  • Java 7 or later
  • hivemall-core-xxx-with-dependencies.jar
  • define-all.hive

2.1.2. 安装

将下面两行配置添加到$HOME/.hiverc文件中。

add jar /home/myui/tmp/hivemall-core-xxx-with-dependencies.jar;
source /home/myui/tmp/define-all.hive;

这样在每次启动一个Hive session时,都会自动载入Hivemall所有的功能。除了添加配置之外,也可以每次都运行下面的命令行。

$ hive
add jar /tmp/hivemall-core-xxx-with-dependencies.jar;
source /tmp/define-all.hive;

2.1.3. 其他选择

你也可以在以下的平台上运行Hivemall:

  • Apache Spark
  • Apache Pig
  • Apache Hive on Docker for testing

2.1.4. 源代码编译

方法如下:

$ git clone https://github.com/apache/incubator-hivemall.git
$ cd incubator-hivemall
$ bin/build.sh

这时,你可以在目录./target中发现hivemall的jars文件。

2.2. 作为类持久函数(permanent functions)安装

Hive v0.13及之后的更新版本在生命周期中支持类持久函数。

Permanent functions在你通过Hiveserver使用Hive时候,或者避免每次session都要安装hivemall的时,是非常有用的。

  1. 将hivemall的jar包放入HDFS
  2. 创建permanent functions
  3. 确认函数

2.2.1. 将hivemall的jar包放入HDFS

首先将hivemall的jar包放入HDFS,如下:

hadoop fs -mkdir -p /apps/hivemall
hadoop fs -put hivemall-with-dependencies.jar /apps/hivemall

2.2.2. 创建permanent functions

以下是一个辅助的步骤来定义hivemall数据库的功能,而不是默认数据库。

CREATE DATABASE IF NOT EXISTS hivemall;
USE hivemall;

然后使用 define-all-as-permanent.hive创建 permanent functions,一哥DDL脚本定义永久UDFS。

set hivevar:hivemall_jar=hdfs:///apps/hivemall/hivemall-with-dependencies.jar;

source /tmp/define-all-as-permanent.hive;

2.2.3. 确认函数

在命令行输入:

show functions "hivemall.*";

会显示

> hivemall.adadelta
> hivemall.adagrad

2.3. 输入格式

接下来介绍在Hivemall的训练数据的输入格式,在这里将会使用EBNF(扩展的巴科斯范式)注解来描述这种格式。

2.3.1. 分类的输入格式

Hivemall的分类器需要2到3个参数:特征值、标签和选项。训练方法的前两个参数表示的是训练示例。在统计学上,特征值和标签分别被称为解释变量和响应变量。

2.3.2. 特征值格式(分类和回归)

在回归和分类之间的特征值的格式是相同的。Hivemall对于特征值的类型的列可以是ARRAY<INT|BIGINT|TEXT>等多种类型。Hivemall使用一种不常见的数据格式类似于LIBSVMVowpal Wabbit

在一个数组中,每个特征值的格式如下:

feature ::= <index>:<weight> or <index>

每个索引的元素或者权重的数据格式如下:

index ::= <INT | BIGINT | TEXT>
weight ::= <FLOAT>

索引通常从1开始的整数类型(INT/BIGINT)。下面是一个特征值的示例:

10:3.4  123:0.5  34567:0.231

注意:稍后将会提到,索引"0"将会作为虚拟变量保存。

除了数字之外,你也可以使用TEXT值作为一个索引。比如:你可以使用array("height:1.5", "length:2.0")做为特征值。

"height:1.5" "length:2.0"

2.3.3. 定量和分类变量

定量变量必须有一个索引的目录。
Hivemall(v0.3.1之后)提供add_feature_index函数,这个函数很方便的将索引添加到定量变量。

select add_feature_index(array(3,4.0,5)) from dual;

输出结果:

["1:3.0","2:4.0","3:5.0"]

你可以对每个特征值忽略指定权重,比如分类变量如下:

feature :: = <index>

2.3.4. Bias/Dummy变量

注意:"0"倍保存为偏差变量(在统计学称为虚拟变量)。
Hivemall中addBias函数追加"0:1.0"作为特征值数组中的一个元素。

2.3.5. 特征值哈希化

Hivemall通过mhash function支持特征值的哈希化。

在默认的设置中,mhash函数接受一个文本格式的特征值,然后生成一个范围在1到224=16777216的哈希数。

在特征值维数比较大的时候,特征值哈希化是非常有用的。当预测模型比较大,会超出内存限制或者发生内存溢出的时候,可以考虑使用mhash function

一般情况下,当特征值为数少于16777216的时候,是没有必要使用mhash的。如果特征值的索引是非常大的文本,使用大量的内存空间,考虑使用mhash函数如下:

-- feature is v0.3.2 or before
concat(mhash(extract_feature("xxxxxxx-yyyyyy-weight:55.3")), ":", extract_weight("xxxxxxx-yyyyyy-weight:55.3"))

-- feature is v0.3.2-1 or later
feature(mhash(extract_feature("xxxxxxx-yyyyyy-weight:55.3")), extract_weight("xxxxxxx-yyyyyy-weight:55.3"))

输出

43352:55.3

2.3.6. 二分分类器的标签格式

标签必须是一个INT类型的列,并且值是1或-1,如下所示:

<label> ::= 1 | -1

或者,也可以使用以下的格式,使用1代表正数,0代表负数:

<label> ::= 1 | -1

2.3.7. 多类分类器的标签格式

标签可以使用任意的元类型,如下:

<label> ::= <primitive type>

往往,标签列的类型是INT,BIGINT或TEXT

2.3.8. 回归的输入格式

在回归算法里,响应/预测变量是一个真实的数字。
在Hivemall v0.3之前,值接受FLOAT类型作为目标值:

<target> ::=<FLOAT>

你需要显示的将一个double值转换成float:

CAST(target as FLOAT)

另一方面,v0.3版本之后,可以接受多种兼容的格式:

<target> ::= <FLOAT | DOUBLE | INT | TINYINT | SMALLINT| BIGINT >

2.3.9. 逻辑回归的目标

逻辑回归实际上是一个二分分类方案,虽然它可以产生正的的训练样本的概率。
一个训练集输入的目标值必须在0.0到1.0,更明确一点就是0.0或1.0。

2.3.10. 帮助函数

-- hivemall v0.3.2 and before
select concat("weight",":",55.0);

-- hivemall v0.3.2-1 and later
select feature("weight", 55.0);
weight:55.0

select extract_feature("weight:55.0"), extract_weight("weight:55.0");
weight | 55.0

-- hivemall v0.4.0 and later
select feature_index(array("10:0.2","7:0.3","9"));

[10,7,9]

select 
  convert_label(-1), convert_label(1), convert_label(0.0f), convert_label(1.0f)
from 
  dual;

0.0f | 1.0f | -1 | 1

2.3.11. 量化特征

`array<string> quantitative_features(array<string> featureNames, ...) 是一个helper函数来创建稀疏表中的数量特征。

select quantitative_features(array("apple","value"),1,120.3);
["apple:1.0","value:120.3"]

2.3.12. 分类特征

array<string> categorical_features(array<string> featureNames, ...) 是一个helper函数,要从表中创建稀疏分类特征。

select categorical_features(
  array("is_cat","is_dog","is_lion","is_pengin","species"),
  1, 0, 1.0, true, "dog"
);
["is_cat#1","is_dog#0","is_lion#1.0","is_pengin#true","species#dog"]

2.3.13. 准备训练数据表

select 
  rowid() as rowid,
  concat_array(
    array("bias:1.0"),
    categorical_features( 
      array("id", "name"),
      id, name
    ),
    quantitative_features(
      array("height", "weight"),
      height, weight
    )
  ) as features, 
  click_or_not as label
from
  table;

3. 几点有效的Hivemall建议

3.1. 显式使用addBias()会有更好的预测结果

训练者学习以下形式的函数$f(x)= y$或权重$W$,以预测其中x是特征向量的标签。$y=f(x)=Wx$
如果没有偏差条款(bias caluse)(或正则化处理),由于$f(x)$与原点(0,0)交叉,所以f(x)不能处理成超平面分割(1,1)和(2,2)。
使用偏差条款b,训练者学习以下函数$f(x)=Wx+b$之后,预测模型会考虑到数据集中存在的偏差,预测到超平面并不一定与原点相交。

Hivemall的addBias()向特征向量添加偏差。 要使用一个偏差条款,需要在训练和测试的数据集中使用addBias()。例如:偏值b是默认值为0(v3版本之前为"-1")的特征。

注意:偏差是所有训练和测试集中表现出来的特征。

3.1.1. 数据集中添加偏差变量

create table e2006tfidf_test_exploded as
select 
  rowid,
  target,
  split(feature,":")[0] as feature,
  cast(split(feature,":")[1] as float) as value
  -- extract_feature(feature) as feature, -- hivemall v0.3.1 or later
  -- extract_weight(feature) as value     -- hivemall v0.3.1 or later
from 
  e2006tfidf_test LATERAL VIEW explode(addBias(features)) t AS feature;

3.1.2. 训练集中添加偏差变量

create table e2006tfidf_test_exploded as
select 
  rowid,
  target,
  split(feature,":")[0] as feature,
  cast(split(feature,":")[1] as float) as value
  -- extract_feature(feature) as feature, -- hivemall v0.3.1 or later
  -- extract_weight(feature) as value     -- hivemall v0.3.1 or later
from 
  e2006tfidf_test LATERAL VIEW explode(addBias(features)) t AS feature;

3.2. 使用rand_amplify()会有更好的预测结果

本节介绍了对提高预测分数有用的放大技术。
迭代算法在机器学习中是必不可少的(例如,随机梯度下降)以获得良好的预测模型。但是因为每个MapReduce作业的输入和输出都通过HDFS,所以MapReduce不适用于迭代算法。
在这节中,将会描述Hivemall如何处理这种问题,下面以KDD Cup 2012,Track 2 Task为例:

  1. 在Map阶段放大训练数据,在Reduce阶段进行清洗
  2. 在每个Map任务中放大和清洗训练数据
  3. 结论

3.2.1. 在Map阶段放大训练数据,在Reduce阶段进行清洗

Hivemall提供放大UDTF来枚举机器学习中的迭代效果,无需几个MapReduce步骤。
放大(amplify)功能为每行返回多行,其中第一个参数${xtimes}是乘法因子。
在下面的例子中,乘法因子设置为3。

set hivevar:xtimes=3;

create or replace view training_x3
as
select 
  * 
from (
select
   amplify(${xtimes}, *) as (rowid, label, features)
from  
   training_orcfile
) t
CLUSTER BY rand();

在上面的示例中,CLUSTER BY子句使用分配密钥的随机密钥将Map的输出分配给reducer,并且reducer的输入记录是随机清洗的。
记录和随机清洗的乘法与迭代具有相似的效果。 因此,我们建议用户使用放大视图进行训练,具体如下:

create table lr_model_x3 
as
select 
 feature,
 cast(avg(weight) as float) as weight
from 
 (select 
     logress(features,label) as (feature,weight)
  from 
     training_x3
 ) t 
group by feature;

上述两个MapReduce的查询过程如下所示:

查询过程
在本示例中,使用trainning_x3函数而不是简单训练表,这样得到了更高和更好的AUC(0.746214)。

amplify()中的一个问题是,在第1阶段的清洗(复制)和合并阶段可能会成为瓶颈。 当训练表比较大,涉及100个Map任务时,合并运算操作需要通过(外部)合并排序来合并至少100个文件!

注意:实际瓶颈不是M/R迭代,而是清洗训练实例。没有清洗的迭代(如Spark示例中)交导致非常慢的收敛,并导致需要更多的迭代。 但是,清洗的过程是避免不了的,即使在迭代MapReduce变体中。
result

3.2.2. 在每个Map任务中放大和清洗训练数据

为了处理大量的训练数据,Hivemall提供了rand_amplifyUDTF,可以在Map任务中随机清洗输入的行。 当填写由${shufflebuffersize}指定的本地缓冲区时,rand_amplifyUDTF以随机顺序输出行。

使用rand_amplify(),training_x3的视图定义如下:

set hivevar:shufflebuffersize=1000;

create or replace view training_x3
as
select
   rand_amplify(${xtimes}, ${shufflebuffersize}, *) as (rowid, label, features)
from  
   training_orcfile;

训练查询执行如下所示:

result
map-local的乘法和清洗在合并阶段没有瓶颈,并且在单个MapReduce作业中查询的效率是比较高的。

result
这个例子中使用 rand_amplify 得到了更好的AUC(0.743392)

3.2.3. 结论

我们建议用户使用amplify()进行小型训练输入,并使用rand_amplify()进行大型训练输入,以在合理的训练时间内获得更好的准确性。

方法 消耗时间 (sec) AUC
Plain 89.718 0.734805
amplifier+clustered by 479.855 0.746214
rand_amplifier 116.424 0.743392

3.3. RDBMS实时预测

Apache Hivemall提供了一个在Apache Hive上构建预测模型的批量学习方案。 学习过程本身是一个批处理过程,但是可以通过对事务关系DBMS进行预测来实现在线/实时预测。

在本节将介绍如何使用关系DBMS运行实时预测,我们假设您已经运行了a9a二进制分类任务。

3.3.1. 前置条件

  • Mysql
    mysql-connector-java.jar放到$SQOOP_HOME/lib路径。
  • Sqoop
    Sqoop 1.4.5不支持Hadoop v2.6.0。 因此,您需要为Hadoop 2.6构建软件包。 为此,您需要编辑build.xml和ivy.xml,如此补丁(https://gist.github.com/myui/...所示。

3.3.2. 在Mysql上准备模型表

create database a9a;
use a9a;

create user sqoop identified by 'sqoop';
grant all privileges on a9a.* to 'sqoop'@'%' identified by 'sqoop';
flush privileges;

create table a9a_model1 (
  feature int, 
  weight double
);

不要忘记编辑MySQL配置文件(/etc/mysql/my.cnf)中可以从Hadoop主站和从站节点访问的bind_address。

3.3.3. Hive导出表到MySQL

使用Sqoop检查MySQL服务器的连接。

export MYSQL_HOST=dm01

export HADOOP_HOME=/opt/hadoop
export HADOOP_CONF_DIR=${HADOOP_HOME}/etc/hadoop/
export HADOOP_COMMON_HOME=${HADOOP_HOME}

bin/sqoop list-tables --connect jdbc:mysql://${MYSQL_HOST}/a9a --username sqoop --password sqoop

因为Sqoop无法读取Hive表,所以需要创建TSV表。

create table a9a_model1_tsv 
  ROW FORMAT DELIMITED 
    FIELDS TERMINATED BY "\t"
    LINES TERMINATED BY "\n"
  STORED AS TEXTFILE
AS
select * from a9a_model1;

检查'a9a_model1_tsv'的位置如下:

desc extended a9a_model1_tsv;
> location:hdfs://dm01:9000/user/hive/warehouse/a9a.db/a9a_model1_tsv

bin/sqoop export \
--connect jdbc:mysql://${MYSQL_HOST}/a9a \
--username sqoop --password sqoop \
--table a9a_model1 \
--export-dir /user/hive/warehouse/a9a.db/a9a_model1_tsv \
--input-fields-terminated-by '\t' --input-lines-terminated-by '\n' \
--batch

导出成功完成后,您可以在MySQL的模型表中找到条目。

mysql> select * from a9a_model1 limit 3;
+---------+---------------------+
| feature | weight              |
+---------+---------------------+
|       0 | -0.5761121511459351 |
|       1 | -1.5259535312652588 |
|      10 | 0.21053194999694824 |
+---------+---------------------+
3 rows in set (0.00 sec)

我们建议创建一个模型表索引,以提高在线预测中的查寻效率。

CREATE UNIQUE INDEX a9a_model1_feature_index on a9a_model1 (feature);
-- USING BTREE;

3.3.4. 将测试数据从Hadoop导出到MySQL(可选步骤)

在将要导出的Hive中准备一个测试数据表。

create table a9atest_exploded_tsv
  ROW FORMAT DELIMITED 
    FIELDS TERMINATED BY "\t"
    LINES TERMINATED BY "\n"
  STORED AS TEXTFILE
AS
select
  rowid, 
  -- label, 
  extract_feature(feature) as feature,
  extract_weight(feature) as value
from
  a9atest LATERAL VIEW explode(addBias(features)) t AS feature;

desc extended a9atest_exploded_tsv;
> location:hdfs://dm01:9000/user/hive/warehouse/a9a.db/a9atest_exploded_tsv,

准备一个测试表,从Hadoop的导入数据。

use a9a;

create table a9atest_exploded (
  rowid bigint,
  feature int, 
  value double
);

然后,运行Sqoop将数据从HDFS导出到MySQL。

export MYSQL_HOST=dm01

bin/sqoop export \
--connect jdbc:mysql://${MYSQL_HOST}/a9a \
--username sqoop --password sqoop \
--table a9atest_exploded \
--export-dir /user/hive/warehouse/a9a.db/a9atest_exploded_tsv \
--input-fields-terminated-by '\t' --input-lines-terminated-by '\n' \
--batch

为rowid列添加一个索引以提高rowid的选择。

CREATE INDEX a9atest_exploded_rowid_index on a9atest_exploded (rowid) USING BTREE;

导出成功完成后,您可以在MySQL的测试表中找到条目。

mysql> select * from a9atest_exploded limit 10;
+-------+---------+-------+
| rowid | feature | value |
+-------+---------+-------+
| 12427 |      67 |     1 |
| 12427 |      73 |     1 |
| 12427 |      74 |     1 |
| 12427 |      76 |     1 |
| 12427 |      82 |     1 |
| 12427 |      83 |     1 |
| 12427 |       0 |     1 |
| 12428 |       5 |     1 |
| 12428 |       7 |     1 |
| 12428 |      16 |     1 |
+-------+---------+-------+
10 rows in set (0.00 sec)

3.3.5. 通过MySQL在线/实时预测

定义用于逻辑回归预测的S形函数如下:

DROP FUNCTION IF EXISTS sigmoid;
DELIMITER //
CREATE FUNCTION sigmoid(x DOUBLE)
  RETURNS DOUBLE
  LANGUAGE SQL
BEGIN
  RETURN 1.0 / (1.0 + EXP(-x));
END;
//
DELIMITER ;

我们在这里假设对具有(0,1,10)的“特征”进行预测,并且它们中的每一个是分类特征(即权重为1.0)。然后,您可以通过逻辑回归获得概率如下:

select
  sigmoid(sum(m.weight)) as prob
from
  a9a_model1 m
where
  m.feature in (0,1,10);
+--------------------+
| prob               |
+--------------------+
| 0.1310696931351625 |
+--------------------+
1 row in set (0.00 sec)

类似于Hive的方式,您可以运行预测如下:

select
  sigmoid(sum(t.value * m.weight)) as prob, 
  if(sigmoid(sum(t.value * m.weight)) > 0.5, 1.0, 0.0) as predicted
from
  a9atest_exploded t LEFT OUTER JOIN
  a9a_model1 m ON (t.feature = m.feature)
where
  t.rowid = 12427; -- prediction on a particular id

也可以使用SQL视图来测试上述查询中的目标“t”。

+---------------------+-----------+
| prob                | predicted |
+---------------------+-----------+
| 0.05595205126313402 |       0.0 |
+---------------------+-----------+
1 row in set (0.00 sec)

3.4. 综合学习稳定预测

这个例子说明了如何在Hivemall中运行集体学习。

3.4.1. UDF准备

delete jar /home/myui/tmp/hivemall.jar;
add jar /home/myui/tmp/hivemall.jar;

source /home/myui/tmp/define-all.hive;

3.4.2. [情况1]模式集合/混合

3.4.2.1. 训练
SET hive.exec.parallel=true;
SET hive.exec.parallel.thread.number=8;
SET mapred.reduce.tasks=4;

drop table news20mc_ensemble_model1;
create table news20mc_ensemble_model1 as
select 
 label, 
 -- cast(feature as int) as feature, -- hivemall v0.1
 argmin_kld(feature, covar) as feature, -- hivemall v0.2 or later
 voted_avg(weight) as weight
from 
 (select 
     -- train_multiclass_cw(addBias(features),label) as (label,feature,weight)      -- hivemall v0.1
     train_multiclass_cw(addBias(features),label) as (label,feature,weight,covar)   -- hivemall v0.2 or later
  from 
     news20mc_train_x3
  union all
  select 
     -- train_multiclass_arow(addBias(features),label) as (label,feature,weight)    -- hivemall v0.1
     train_multiclass_arow(addBias(features),label) as (label,feature,weight,covar) -- hivemall v0.2 or later
  from 
     news20mc_train_x3
  union all
  select 
     -- train_multiclass_scw(addBias(features),label) as (label,feature,weight)     -- hivemall v0.1
     train_multiclass_scw(addBias(features),label) as (label,feature,weight,covar)  -- hivemall v0.2 or later
  from 
     news20mc_train_x3
 ) t 
group by label, feature;

-- reset to the default
SET hive.exec.parallel=false;
SET mapred.reduce.tasks=-1;
3.4.2.2. 预测
create or replace view news20mc_ensemble_predict1 
as
select 
  rowid, 
  m.col0 as score, 
  m.col1 as label
from (
select
   rowid, 
   maxrow(score, label) as m
from (
  select
    t.rowid,
    m.label,
    sum(m.weight * t.value) as score
  from 
    news20mc_test_exploded t LEFT OUTER JOIN
    news20mc_ensemble_model1 m ON (t.feature = m.feature)
  group by
    t.rowid, m.label
) t1
group by rowid
) t2;
3.4.2.3. 评测
create or replace view news20mc_ensemble_submit1 as
select 
  t.label as actual, 
  pd.label as predicted
from 
  news20mc_test t JOIN news20mc_ensemble_predict1 pd 
    on (t.rowid = pd.rowid);
select count(1)/3993 from news20mc_ensemble_submit1 
where actual == predicted;
0.8494866015527173
3.4.2.4. 清理
drop table news20mc_ensemble_model1;
drop view news20mc_ensemble_predict1;
drop view news20mc_ensemble_submit1;

不幸的是,在这种情况下,很多都会失败。

算法 准确性
一排 0.8474830954169797
SCW2 0.8482344102178813
合奏(模型) 0.8494866015527173
CW 0.850488354620586

3.4.3. [情况2]预测合奏

3.4.3.1. 预测
create or replace view news20mc_pred_ensemble_predict1 
as
select 
  rowid, 
  m.col1 as label
from (
  select
    rowid, 
    maxrow(cnt, label) as m
  from (
    select
      rowid,
      label,
      count(1) as cnt
    from (
      select * from news20mc_arow_predict1
      union all
      select * from news20mc_scw2_predict1
      union all
      select * from news20mc_cw_predict1
    ) t1
    group by rowid, label
  ) t2
  group by rowid
) t3;
3.4.3.2. 评测
create or replace view news20mc_pred_ensemble_submit1 as
select 
  t.label as actual, 
  pd.label as predicted
from 
  news20mc_test t JOIN news20mc_pred_ensemble_predict1 pd 
    on (t.rowid = pd.rowid);
select count(1)/3993 from news20mc_pred_ensemble_submit1 
where actual == predicted;
0.8499874780866516

不幸的是,在这种情况下,很多也都会失败。

算法 准确性
一排 0.8474830954169797
SCW2 0.8482344102178813
合奏(模型) 0.8494866015527173
集合(预测) 0.8499874780866516
CW 0.850488354620586

3.5. 混合模型更好的预测收敛(MIX服务器)

在本页中,我们将介绍如何在Hivemall上使用模型混合。模型混合对于训练分类器的更好的预测性能和更快的收敛是有用的。您可以在此(http://www.slideshare.net/myu...中找到MIX协议的内部设计的简要说明。

3.5.1. 前置条件

  • Hivemall V0.3或更高版本

我们建议使用快速网络集群混合。

3.5.2. 运行混合服务器

首先,将以下文件放在可从Hadoop worker节点访问的服务器上

  • target/hivemall-mixserv.jar
  • bin/run_mixserv.sh

注意:hivemall-mixserv.jar内容比较大,因此仅用于混合服务器。

# run a Mix Server
./run_mixserv.sh

在这个例子中,我们假设Mix服务器在host01,host03和host03上运行。 Mix服务器使用的默认端口是11212,端口可以通过run_mixserv.sh的“-port”选项进行配置。

我们建议使用多个MIX服务器来获得更好的MIX吞吐量(3-5个或更多的足够用于正常的群集大小)。 Hivemall的MIX协议通过添加MIX服务器节点可以水平扩展。

3.5.3. 通过Hivemall使用Mix协议

在hive中安装Hivemall。

确保使用hivemall-with-dependencies.jar进行安装。该jar包含最小要求的jar包(netty,jsr305),用于在Hive上运行Hivemall。

现在,我们解释如何使用混合使用KDD2010a数据集的例子。

在Hivemall上启用mixing很简单,如下:

use kdd2010;

create table kdd10a_pa1_model1 as
select 
 feature,
 cast(voted_avg(weight) as float) as weight
from 
 (select 
     train_pa1(addBias(features),label,"-mix host01,host02,host03") as (feature,weight)
  from 
     kdd10a_train_x3
 ) t 

group by feature;

你仅需要做的只是添加“-mix”训练选项,如上面的查询所示。

3.5.4. 混合模式的影响

根据我的经验,MIX将32节点簇上的KDD2010a PA1训练的预测精度从0.844835019263103(w/o混合)提高到0.8678096499719774(w/mix)。

使用MIX协议的开销几乎可以忽略不计,因为使用异步非阻塞I/O有效地处理MIX通信。此外,由于混合的收敛速度更快,因此在某些设置下可以提高训练时间。

3.6. 在Amazon Elastic MapReduce上运行Hivemall

………暂无………

4. 常用的Hive/Hadoop提示

4.1. 为每行添加rowid

4.1.1. 在Hivemall提供ROWID生成器

可以使用ROWID()函数来生成Hivemall(V0.2或更高版本)的独特的rowid。

select
  rowid() as rowid, -- returns ${task_id}-${sequence_number} as string
  *
from 
  xxx;

此外,Hivemall在V0.5-RC.1或更高版本开始支持ROWNUM()

select
  rownum() as rowid, -- returns sprintf(`%d%04d`,sequence,taskId) as long
  *
from
  xxx;

4.1.2. 使用SQL其他ROWID生成方案

CREATE TABLE xxx
AS
SELECT 
  regexp_replace(reflect('java.util.UUID','randomUUID'), '-', '') as rowid,
  *
FROM
  ..;

生成rowid的另一个方式是使用row_number()。但是,对于大型数据集,因为在单个reducer上执行rowid生成,所以查询执行将变得很慢,。

CREATE TABLE xxx
AS
select 
  row_number() over () as rowid, 
  * 
from a9atest;

4.2. Hivemall的Hadoop调优

4.2.1. 前置条件

请按照下面的指导进行Hadoop调优:

http://hadoopbook.com/
http://www.slideshare.net/clo...

4.2.2. mapper的配置

当训练操作在mapper上运行时(例如,当使用rand_amplify())时,mapper配置对于hivemall很重要。

mapreduce.map.java.opts="-Xmx2048m -XX:+PrintGCDetails" (YARN)
mapred.map.child.java.opts="-Xmx2048m -XX:+PrintGCDetails" (MR v1)

mapreduce.task.io.sort.mb=1024 (YARN)
io.sort.mb=1024 (MR v1)

在上述情况下,Hivemall最多可以使用1024MB。

mapreduce.map.java.opts - mapreduce.task.io.sort.mb = 2048MB - 1024MB = 1024MB

此外,其他Hadoop组件也会占用内存空间。 Hivemall可以使用大约1024MB*0.5左右。我们建议至少为映射器设置-Xmx2048m。
所以尽可能的将mapreduce.map.java.opts - mapreduce.task.io.sort.mb设置为最大。

4.2.3. Reducer端的配置

当训练操作在Reducer端运行时(例如,当使用amplify())时,Reducer端的配置对于hivemall很重要。

mapreduce.reduce.java.opts="-Xmx2048m -XX:+PrintGCDetails" (YARN)
mapred.reduce.child.java.opts="-Xmx2048m -XX:+PrintGCDetails" (MR v1)

mapreduce.reduce.shuffle.input.buffer.percent=0.6 (YARN)
mapred.reduce.shuffle.input.buffer.percent=0.6 (MR v1)

-- mapreduce.reduce.input.buffer.percent=0.2 (YARN)
-- mapred.job.reduce.input.buffer.percent=0.2 (MR v1)

在上述情况下,Hivemall最多可以使用820MB。

mapreduce.reduce.java.opts (1 - mapreduce.reduce.input.buffer.percent) = 2048 (1 - 0.6) ≈ 820 MB

此外,其他Hadoop组件也会占用内存空间。 Hivemall可以使用大约820MB*0.5左右。我们建议至少为映射器设置-Xmx2048m。
所以尽可能的将mapreduce.reduce.java.opts * (1 - mapreduce.reduce.input.buffer.percent)设置为最大。

4.2.4. 预估Hivemall消耗内存的公式

对于密集模型,Hivemall中消耗的内存如下:

feature_dimensions (2^24 by the default) * 4 bytes (float) * 2 (iff covariance is calculated) * 1.2 (heuristics)

2^24 4 bytes 2 * 1.2 ≈ 161MB

使用了SpaceEfficientDenseModel之后,公式变化如下:

feature_dimensions (assume here 2^25) * 2 bytes (short) * 2 (iff covariance is calculated) * 1.2 (heuristics)

2^25 2 bytes 2 * 1.2 ≈ 161MB

4.2.5. Hive的执行引擎

推荐使用Apache Tez作为Hivemall查询的Hive执行引擎

set mapreduce.framework.name=yarn-tez;
set hive.execution.engine=tez;

也可以通过配置以下设置使用普通的旧MapReduce:

set mapreduce.framework.name=yarn;
set hive.execution.engine=mr;

流云
323 声望15 粉丝