Skip to main content

· 6 min read
Yandi LI

之前受限于hive机器上安装的python版本,只能使用py2.7默认环境,也没法安装包,导致很多复杂逻辑没法放到集群上跑。工作中需要用到scipy,redis等工具,也要使用py3.7以上的新功能。

尝试1

曾经将单独的包打包成zip后缀,打包后可以直接import进来,但是发现并不是所有的包都能跑通。一些依赖底层c库或者系统的,就会报错,比如numpy,scipy。成功的案例是redis和pymysql,见曾经的方案

尝试2

venv打包后的python并没有包含需要的全部库,venv.zip/bin/python无法运行。

尝试3

今天参考了几篇文献后,发现可以借助conda,由conda封装后,依赖的各种库都可以原封不动的使用,打的zip包可以无缝在各个linux系统中使用

1、新方案

创建conda环境

# 依赖
$ sudo yum install -y bzip2
# 安装
$ pyenv install miniconda3-4.6.14
$ pyenv shell miniconda3-4.6.14
$ conda create -n 3.7.2 python=3.7.2
$ conda init bash
# 退出后重新登录
$ conda activate 3.7.2
$ conda config --add channels https://mirrors.ustc.edu.cn/anaconda/pkgs/main/
$ conda config --set show_channel_urls yes
$ conda clean -i
$ conda install pip

pip安装需要的任何包

$ pip install scipy -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

打包python环境

进入虚拟环境所在目录

$ conda env list
# conda environments:
#
base * /usr/home/yandi/.pyenv/versions/miniconda3-4.6.14
3.7.2 /usr/home/yandi/.pyenv/versions/miniconda3-4.6.14/envs/3.7.2

$ conda deactivate
$ cd /usr/home/yandi/.pyenv/versions/miniconda3-4.6.14/envs/3.7.2

打包

$ zip -r Python-3.7.2.zip *

打包后,zip文件里面的结构应该类似

├── bin
├── compiler_compat
├── conda-meta
├── include
├── lib
├── share
├── ssl
└── x86_64-conda_cos6-linux-gnu

测试zip包是否可用

$ mv Python-3.7.2.zip /data0/users/yandi/modules/
$ cd /data0/users/yandi/modules/
# 解压为指定的名称
$ unzip Python-3.7.2.zip -d Python-3.7.2
$ ./Python-3.7.2/bin/python --version
Python 3.7.2
$ ./Python-3.7.2/bin/python -c "import scipy; print(scipy.__version__)"
1.7.3

把pyhton环境的压缩包上传到HDFS上

$ hadoop fs -put Python-3.7.2.zip ${hfds_path}/udf/

在hive中调用

a.py

import sys
import scipy

for line in sys.stdin:
print(line.strip() + "\t" + scipy.__version__)

在hive中,add archive类似于add file,帮助我们解压成一个XXX.zip/的目录,不像pyspark那里可以加一个#Python来重命名解压后的目录

hive -e "
add archive ${hdfs_path}/udf/Python-3.7.2.zip;
add file a.py;
select
transform(*)
using 'Python-3.7.2.zip/bin/python a.py'
from short_interest_rd_info
"

输出

李XX	1088393930	机器学习算法	1.7.3
赵XX 1071650555 机器学习算法 1.7.3
吴XX 1074691870 机器学习算法 1.7.3

2、拓展问题:打包项目的方法

拓展上面的方法,在预测阶段也可以不限于只使用一个a.py脚本,我们可以把整个python项目加载到hive上运行。举例来说,一个项目类似下面的结构,不同代码之间有存在相互引用,

.
├── app2vec
│   ├── feature.py
│   ├── inference.py
│   ├── loss.py
│   ├── model.py
│   └── train.py
└── utils
├── dataset.py
├── model.py
└── tokenizer.py

如果直接使用add file XX.py,类似下面这样,

    add archive ${hdfs}/udf/Python-torch-1.13.1.zip;
add file app2vec/inference.py;
add file app2vec/dataset.py;
add file app2vec/model.py;
add file app2vec/tokenizer.py;
add archive codebooks.zip;
add archive checkpoints.zip;

会存在两个问题,

  • 加载很麻烦,对于hive来说,python代码失去了封装,需要写很多无用代码
  • 多层目录结构就行不通了,这个写法会把所有的文件都加载到同一个目录下;相当于失去了现有的目录结构,变成平层结构
feature.py inference.py ...

解决方案

首先,对整个python项目代码打包,

zip -r app2vec.zip app2vec

然后,在hive中add archive

    add archive ${hdfs}/udf/Python-torch-1.13.1.zip;
add archive app2vec.zip;
add archive codebooks.zip;
add archive checkpoints.zip;

transform的语句为

      select 
transform(uid, feature)
using 'Python-torch-1.13.1.zip/bin/python app2vec.zip/app2vec/app2vec/inference.py\
--batch_size=32 \
--model_path=checkpoints.zip/checkpoints/ \
--token_path=codebooks.zip/codebooks/'
as (
uid, cat, tag, obj
)
from yandi_tmp_1

最后,python入口文件需要修改启动位置(相当于从很高的父节点处用绝对路径启动,而不是本地目录,因此需要修改path)

import sys
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, '')

线上实践就可以跑通了,感觉稳定性和本地启动差不多,整套python代码不用做任何适配修改,就可以运行了,还是比较满意的

3、曾经的方案

$ cd .venv/lib/python3.6/site-packages/pymysql
$ zip -r pymysql.zip *
$ hadoop fs -get ${hdfs_path}/udf/pymysql.zip
try:
import pymysql
except ImportError:
import zipimport
importer = zipimport.zipimporter('pymysql.zip')
pymysql=importer.load_module("pymysql")

参考链接

· 18 min read
Yandi LI

@作者: 机器学习算法 @迪吉老农

最近使用GBDT时,想通过分布式进行训练,尝试了一些框架,但原理不太了解。有些东西与同事讨论后,也还不甚明了,于是专心看了一下文档,在此记录一下。

1、分布式原理

常用分布式训练方式,应该是参数服务器。worker把sample的统计结果推送到单台参数服务器机器上,参数服务器汇总后,再推送到worker端。有点类似于单reducer的方式。

相比于参数服务器的中心化方案,这里提到的都是去中心化方案。

· 6 min read
Yandi LI

AUC这个指标在排序问题里经常用到,之前也有个模糊的印象,就是一个排序正确的比例。

这个模糊印象是,

  • 分母是选两个例子的的方式数
  • 分子是这两个例子的预测顺序正确的次数

但是今天看了一个python的实现,发现不是很能理解里面的公式,于是查了一下维基百科的定义,

· 13 min read
Yandi LI

@作者: 机器学习算法 @迪吉老农 代码地址:https://github.com/yandili/forge_load

1. 背景需求

最近组内的GPU利用率一直被警告,说是利用率过低。其实GPU这件事和CPU还是有区别的。

第一个问题是内存限制。CPU的话,可以平行的跑很多程序,这样利用率就上去了。但GPU很大程度上受限于内存。如果内存只能装2个进程,再想运行更多的程序也没有办法。

第二个问题是,CPU一般可以通过复制进程来提高利用率,每个进程占用一个CPU核,就可以按任意的比例提高总体利用率。但是GPU的训练任务跑起来的时候,经常一个程序就100%占用了。如果用这种方式占用空闲GPU,别的正常的程序就只能等待了。

不过既然上面要求了,我们也得做。就考虑两个方面的要求,

  • 占用尽可能小的内存。
  • 控制单进程的GPU资源占用比例。

· 11 min read
Yandi LI

作者:微博研发中心算法平台

今天是春节前一天,作为目前在公司内数一数二的选手,感觉可以和大家分享一下桌上足球这项运动的精髓。

1. 背景

桌上足球的英文是foosball(和足球football很像),法国人管他叫它baby-foot。由于名字很奇葩,各地叫法不同,我以前经常迷惑应该如何称呼它。

虽然不同地方的基本操作和规则类似,但是桌子规格的些许变化,比如球员间距、球员的制作材料,都会对比赛产生非常大的影响。所以即使是我这样的老司机,也很难能够在各种桌子上都称霸。

· 24 min read
Yandi LI

最近被组里的老大要求,分享一些自己在微博工作中实践的一些机器学习算法。由于自己也是菜鸟,很多实验其实都是简单尝试,希望给大家提供一些启发就好了。

一. 问题的定义

“标题党”作为一个新近才出现的名词,并没有明确的定义。根据华东师范大学雷启立的观点,“标题党”是这样一些信息发布者和转发者的总称,《注意,这些都是“标题党”的套路!》