1. 案例介绍
- 使用到的中间件:Apache Flink + Analytics Zoo + proxima
- 开发语言:python
- 数据:通过天池平台下载小型的训练集,选手自行将训练集划分成部分训练集和测试集,并在本地训练和调试算法,生成预测结果。
在评测机器上,会给定四份数据集,分别是用于训练的历史行动数据集和标签数据集,用于测试打分的确诊病例数据集和实时行动数据集。
在历史行动数据集,确诊病例数据集和实时行动数据集中,不同的数据都可能代表同一个类(人)。历史行动数据集包括有确诊病例和非确诊病例,确诊病例数据集里只有确诊病例,并且每个确诊病例代表的人都曾经在历史行动数据集中都出现过。 - 目标:1)对确诊病例数据集中的每个确诊病例,从历史行动数据集中找出该确诊病例代表的类(人)所对应的所有记录,并输出每条记录对应的face_id。2)对实时行动数据集的每一条数据,判断该条数据的类别(人),输出该条数据的device_id和类别。
需要修改的地方主要包括:
1)tianchi_main.py:flink算子编排
2)tianchi_executor.py、python_job_excutor.py:filink算子的具体内容。前面是在线预测的stream任务,后面的是离线训练的batch任务。
3)proxima_executor.py:建立index。话说proxima不是自带很多向量压缩的方法么?
4)python_job_executor.py:自定义了一个自编码器建立index。有必要这么麻烦么……
除了flatL2直接用原向量暴力计算距离外,其他所有的方法都需要先训练建立索引,然后再执行搜索。
如何边搜索边建立索引,貌似给的demo没有涉及(话说这才很关键啊)。
2. 案例分析
2.1 目标分析
本质上是一个reid问题。历史行动数据集和标签数据集合起来用,得到如下字典:pk->[feature1, feature2,…],[device_id_1,device_id_2,…],[face_id_1,face_id_2,…],为了后面方便,考虑加上每个摄像头之下的feature和跨摄像头下的feature。
两个问题分别对应两个数据:
- 第一个是确诊病例数据,没有摄像头信息,数据为feature,从底库中找到所有的历史记录(找到pk,再输出[face_id])
- 第二个是实时行动数据,有摄像头信息,数据为(device_id,feature),找到pk
2.2 运行样例解析
所有的文件都在tianchi_ai_flow下。在~/.bash_profile中添加如下:
PATH=$PATH:$HOME/bin:/root/kafka_2.11-2.3.0/bin
export JAVA_HOME=/usr/java/jdk1.8.0_171
export FLINK_HOME=/root/flink-1.11.1
export ENV_HOME=/root/***/tianchi
export TASK_ID=1
export PATH
然后执行source ~/.bash_profile,然后依次打开三个窗口,执行:
python $ENV_HOME/tianchi_ai_flow/ai_flow_master.py
python $ENV_HOME/tianchi_ai_flow/kafka-source.py
python $ENV_HOME/tianchi_ai_flow/package/python_codes/tianchi_main.py
2.2.1 启动并行推理引擎
封装为AI flow了。配置文件如下:
启动如图:
随即同目录下出现aiflow.db文件,数据库中有如下表:
2.2.2 配置数据源
数据源见source.yaml,如下:
这里注册了两个topic,一个是read一个是write,而数据源如下:
下面是模拟生产数据的代码,从csv文件读取数据后,每隔0.1秒以key:value的形式一行行发布到bootstrap server上。
数据源使用kafka,一般来说会使用KafkaProducer,使用send方法发送信息到一个bootstrap_servers,并且可以注册多个topic,
使用python kafka-source.py启动服务。
2.2.3 启动主流程
配置文件在project.yaml中,里面仅仅指定了服务器:
第一步,读取数据,如下。这里要将下面提到的csv文件都放到data_set目录下。
第二步,将kafka的数据流等注册进并行推理引擎:
2.2.4 训练索引
首先三个是离线训练任务
job_0读取csv数据,并使用trainAutoEncoder()方法对512维特征向量进行编码压缩(变为128维)。
job_1使用AI_flow对特征向量进行分布式预测(这里其实是在分布式做向量压缩)
job_2将预测结果合并
2.2.5 预测新的数据
接下来开始是对数据流进行预测了,顾名思义,四个任务分别是:对历史数据进行特征向量压缩、对新数据建立index、查找sick的类别、在线预测。最后两个任务是本次案例的两个目标,所以有write_result节点。
3. 核心代码
3.1 训练索引
使用自编码器模型,代码使用的是keras架构,训练好的模型保存在model目录下。
3.2 分布式推理
已经封装在AI_flow里面了,调用af.cluster_serving即可。
3.3 流式算子
算子的编写工作全都放在了tianchi_executor.py中,我们举个例子看看:
这段代码是注册了一个udf算子predict2,虽然是输入一个、输出一个,但还是要包装成输入list,输出list。下面这几个是sink算子,可以参考示例代码: