[关闭]
@sambodhi 2018-01-20T00:59:28.000000Z 字数 6381 阅读 5877

ClickHouse 如何结合自家的GNDT算法库CatBoost来做机器学习

作者|Altinity
译者|Liu Zhiyong
编辑|Cai Fangfang

AI前线导语: ClickHouse是俄罗斯第一大搜索引擎Yandex开发的列式储存数据库。据测试报告,这个列式储存数据库的性能大幅超越了很多商业MPP数据库软件,比如Vertica(HP Vertica成为MPP列式存储商业数据库的高性能代表,Facebook就购买了Vertica数据用于用户行为分析。)、InfiniDB。2016年6月15日,ClickHouse由Yandex开源。
2017年7月21日,Yandex开源了CatBoost,这是一种支持类别特征,基于梯度提升决策树的机器学习方法。它是MartixNet算法的继承者。它能够在数据稀疏的情况下教机器学习。特别是在没有像视频、文本、图像这类感官性数据时,CatBoost也能根据事务性数据或历史数据进行操作。CatBoost采用了Apache许可证,它相较其他框架的最大优点是测试精准度高,而且只需少量调试,且性能良好。
今天我们就来看看Altinity前几日撰写的教程[1],给我们演示了ClickHouse如何结合自家开源的GBDT算法库CatBoost来做机器学习。Altinity是一家ClickHouse的服务供应商。

更多干货内容请关注微信公众号“AI 前线”,(ID:ai-front)

ClickHouse非常灵活,可用于各种用例。现在最有意思的技术领域之一就是机器学习,而ClickHouse非常适合作为非常快速的数据源。几个月前,ClickHouse团队实现了对机器学习算法的支持,这使得在ClickHouse数据上运行机器算法变得更容易、更快捷。他们从开源的Yandex CatBoost[2]算法开始,但它可以在未来扩展到其他算法。在本文中,我们发布了关于如何使用ClickHouse来运行CatBoost模型的教程。

CatBoost

CatBoost是最先进的开源梯度提升决策树算法库。

CatBoost是由Yandex研究人员和工程师开发的,在公司内部广泛应用于排列任务、预测和提出建议。Yandex称其是通用的,可以应用于广泛的领域和各种各样的问题。

CatBoost与传统的梯度提升决策树有什么不同?

如需获取更详细的信息,请参阅TechCrunch发布的文章《Yandex开源CatBoost》[4]。

CatBoost结合ClickHouse

现在让我们看看CatBoost如何结合ClickHouse。本文其余部分转载自GitHub上的clickhouse-presentations项目提供的教程[5],ClickHouse方面,由Yandex工程师Nikolai Kochetov负责此项目。那么让我们开始吧。

启动容器

本教程使用Docker容器。启动容器的命令如下:

  1. $ sudo docker run -it -p 8888:8888 yandex/tutorial-catboost-clickhouse

结果,您可以通过http://localhost:8888来访问Jupyter Notebook中的CatBoost和ClickHouse教程:

VirtualBox 映像

可以使用VirtualBox映像[6]替代Docker容器。在启动后,可以在http://localhost:8888上使用相同的材料。

命令提示符

您需要使用命令提示符才能使用ClickHouse。您可以使用Docker容器或VirtualBox映像中的命令提示符。另一个选项是使用jupyter notebook命令提示符。打开主页并选择New→Terminal。所有其他命令都可以直接复制到终端窗口中。

使用ClickHouse

ClickHouse支持多种不同的接口,包括用于流行编程语言的HTTP,JDBC,ODBC和许多第三方库。但是,本教程是通过TCP使用本地客户端。

命令行界面

ClickHouse服务器已经在Docker容器中运行。要连接到服务器,请键入以下命令:

  1. $ clickhouse client --host 127.0.0.1

结果,ClickHouse显示一个输入的邀请:

  1. :)

尝试写一个“Hello,world!”查询:

  1. :) SELECT 'Hello, world!'

如果一切正常,那就进入下一个步骤。

使用ClickHouse作为计算器

运行简单的计算查询:

  1. :) SELECT 2 + 2 * 2
  2. :) SELECT cos(pi() / 3)
  3. :) SELECT pow(e(), pi())

system.numbers表有一个单独的列,称为number。该列存储从0开始的整数。我们来看前10个:

  1. :) SELECT number FROM system.numbers LIMIT 10

现在计算前100个整数的平方和:

  1. :) SELECT sum(pow(number, 2))
  2. FROM
  3. (
  4. SELECT *
  5. FROM system.numbers
  6. LIMIT 101
  7. )

最后一个例子是使用system.numbers表中的子查询创建的。首先选择数字从0到100的单数列,然后计算平方,并使用求和聚合函数计算平方和。

创建一个表并插入数据

为训练样本创建一个表格:

  1. :) CREATE TABLE amazon_train
  2. (
  3. date Date MATERIALIZED today(),
  4. ACTION UInt8,
  5. RESOURCE UInt32,
  6. MGR_ID UInt32,
  7. ROLE_ROLLUP_1 UInt32,
  8. ROLE_ROLLUP_2 UInt32,
  9. ROLE_DEPTNAME UInt32,
  10. ROLE_TITLE UInt32,
  11. ROLE_FAMILY_DESC UInt32,
  12. ROLE_FAMILY UInt32,
  13. ROLE_CODE UInt32
  14. )
  15. ENGINE = MergeTree(date, date, 8192);

为了将数据插入到ClickHouse中,您需要使用Linux命令行。使用Crtl+C来退出ClickHouse(或者,键入“quit”、“logout”、“exit”、“quit”、“q”或等价命令)。然后运行以下命令:

  1. $ clickhouse client --host 127.0.0.1 --query 'INSERT INTO amazon_train FORMAT CSVWithNames' < ~/amazon/train.csv

检查数据是否被插入:

  1. $ clickhouse client --host 0.0.0.0
  2. :) SELECT count() FROM amazon_train

计算ACTION列的平均值:

  1. :) SELECT avg(ACTION) FROM amazon_train

使用已训练的模型

用模型配置创建一个配置文件:

  1. <models>
  2. <model>
  3. <!-- Model type. Now catboost only. -->
  4. <type>catboost</type>
  5. <!-- Model name. -->
  6. <name>amazon</name>
  7. <!-- Path to trained model. -->
  8. <path>/home/catboost/tutorial/catboost_model.bin</path>
  9. <!-- Update interval. -->
  10. <lifetime>0</lifetime>
  11. </model>
  12. </models>

ClickHouse配置文件应该已经有这样的设置:

  1. <models_config>/home/catboost/models/*_model.xml</models_config>

要验证一下,运行以下命令:

  1. tail /etc/clickhouse-server/config.xml

让我们确保模型正在工作。计算表中前10行的预测值:

  1. :) SELECT
  2. modelEvaluate('amazon',
  3. RESOURCE,
  4. MGR_ID,
  5. ROLE_ROLLUP_1,
  6. ROLE_ROLLUP_2,
  7. ROLE_DEPTNAME,
  8. ROLE_TITLE,
  9. ROLE_FAMILY_DESC,
  10. ROLE_FAMILY,
  11. ROLE_CODE) > 0 AS prediction,
  12. ACTION AS target
  13. FROM amazon_train
  14. LIMIT 10;

现在我们来预测一下概率:

  1. :) SELECT
  2. modelEvaluate('amazon',
  3. RESOURCE,
  4. MGR_ID,
  5. ROLE_ROLLUP_1,
  6. ROLE_ROLLUP_2,
  7. ROLE_DEPTNAME,
  8. ROLE_TITLE,
  9. ROLE_FAMILY_DESC,
  10. ROLE_FAMILY,
  11. ROLE_CODE) AS prediction,
  12. 1\. / (1 + exp(-prediction)) AS probability,
  13. ACTION AS target
  14. FROM amazon_train
  15. LIMIT 10;

计算样本上的LogLoss:

  1. :) SELECT -avg(tg * log(prob) + (1 - tg) * log(1 - prob)) AS logloss
  2. FROM
  3. (
  4. SELECT
  5. modelEvaluate('amazon',
  6. RESOURCE,
  7. MGR_ID,
  8. ROLE_ROLLUP_1,
  9. ROLE_ROLLUP_2,
  10. ROLE_DEPTNAME,
  11. ROLE_TITLE,
  12. ROLE_FAMILY_DESC,
  13. ROLE_FAMILY,
  14. ROLE_CODE) AS prediction,
  15. 1\. / (1\. + exp(-prediction)) AS prob,
  16. ACTION AS tg
  17. FROM amazon_train
  18. );

与CatBoost集成

我们不需要为测试样本创建一个表,而是使用catBoostPool表函数。列描述在/home/catboost/tutorial/amazon/test.cd文件中,它看起来像这样:

  1. 0 DocId id
  2. 1 Categ RESOURCE
  3. 2 Categ MGR_ID
  4. 3 Categ ROLE_ROLLUP_1
  5. 4 Categ ROLE_ROLLUP_2
  6. 5 Categ ROLE_DEPTNAME
  7. 6 Categ ROLE_TITLE
  8. 7 Categ ROLE_FAMILY_DESC
  9. 8 Categ ROLE_FAMILY
  10. 9 Categ ROLE_CODE

看看从catBoostPool返回的临时表结构:

  1. :) DESCRIBE TABLE catBoostPool('amazon/test.cd', 'amazon/test.tsv')
  2. ┌─name─────────────┬─type───┬─default_type─┬─default_expression─┐
  3. │ Categ0 │ String │ │ │
  4. │ Categ1 │ String │ │ │
  5. │ Categ2 │ String │ │ │
  6. │ Categ3 │ String │ │ │
  7. │ Categ4 │ String │ │ │
  8. │ Categ5 │ String │ │ │
  9. │ Categ6 │ String │ │ │
  10. │ Categ7 │ String │ │ │
  11. │ Categ8 │ String │ │ │
  12. │ DocId │ String │ │ │
  13. │ id │ String │ ALIAS │ DocId │
  14. │ RESOURCE │ String │ ALIAS │ Categ0 │
  15. │ MGR_ID │ String │ ALIAS │ Categ1 │
  16. │ ROLE_ROLLUP_1 │ String │ ALIAS │ Categ2 │
  17. │ ROLE_ROLLUP_2 │ String │ ALIAS │ Categ3 │
  18. │ ROLE_DEPTNAME │ String │ ALIAS │ Categ4 │
  19. │ ROLE_TITLE │ String │ ALIAS │ Categ5 │
  20. │ ROLE_FAMILY_DESC │ String │ ALIAS │ Categ6 │
  21. │ ROLE_FAMILY │ String │ ALIAS │ Categ7 │
  22. │ ROLE_CODE │ String │ ALIAS │ Categ8 │
  23. └──────────────────┴────────┴──────────────┴────────────────────┘

该表包含了列描述文件中的每个特性和别名的列。计算前10行的概率:

  1. :) SELECT
  2. id,
  3. modelEvaluate('amazon', *) AS prediction,
  4. 1\. / (1\. + exp(-prediction)) AS probability
  5. FROM catBoostPool('amazon/test.cd', 'amazon/test.tsv')
  6. LIMIT 10;

在从catBoostPool读取数据时,可以使用*代替modelEvaluate的参数。计算测试样本的答案并将结果写入文件:

  1. SELECT
  2. toUInt32(id) AS Id,
  3. 1\. / (1 + exp(-modelEvaluate('amazon', *))) AS Action
  4. FROM catBoostPool('amazon/test.cd', 'amazon/test.tsv')
  5. INTO OUTFILE 'submission.tsv'
  6. FORMAT CSVWithNames;

在Kaggle[7]上提交结果(您可以使用jupyter notebook界面从Docker容器中下载submission.tsv)看看你在排行榜上排名如何?


[1] ClickHouse for Machine Learning
https://www.altinity.com/blog/2018/1/18/clickhouse-for-machine-learning ↩
[2] CatBoost
https://tech.yandex.com/catboost/ ↩
[3] CatBoost is an open-source gradient boosting library with categorical features support
https://catboost.yandex/#benchmark ↩
[4] Yandex open sources CatBoost, a gradient boosting machine learning library
https://techcrunch.com/2017/07/18/yandex-open-sources-catboost-a-gradient-boosting-machine-learning-librar/ ↩
[5] clickhouse-presentations/tutorials/catboost_with_clickhouse_en.md
https://github.com/yandex/clickhouse-presentations/blob/master/tutorials/catboost_with_clickhouse_en.md ↩
[6] tutorial_catboost_clickhouse.ova
https://yadi.sk/d/htNTv2VK3Q9RQ7 ↩
[7] Amazon.com - Employee Access Challenge
https://www.kaggle.com/c/amazon-employee-access-challenge/leaderboard ↩
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注