在标签查询服务中,T日所灌入的是T-1日的离线标签数据,其面临的主要问题是:无法获取当日新增用户的标签数据。标签实时预测服务支持实时挖掘用户的标签值,可以覆盖新增用户标签查询,从而弥补离线标签数据缺失从而提高标签覆盖率。
实时预测服务针对的是挖掘类标签,是将离线标签挖掘模型在线化的过程,其可以提供实时预测用户标签值的能力。图4-13展示了挖掘类标签离线模型和在线服务的关系,由图可知,实时预测服务分为离线阶段和在线阶段。离线阶段即第3章提到的挖掘类标签生产流程,在线阶段是将离线阶段产出的算法模型服务化,通过获取用户实时特征可以借助算法模型即时计算出预测结果。
实时预测服务主要应用在新用户场景下。比如在短视频冷启动业务中,为了提高新用户使用体验从而提升留存率,在用户进入App后需要推荐一些优质短视频内容。此时能够获取到的用户画像标签越丰富,短视频推荐的准确率会越高。由于大部分标签是离线标签,新增用户还没有标签数据,此时可以借助实时预测服务来即时预测用户标签并补充到推荐模型中,最终提高冷启动阶段的推荐效果。实时预测也可用于回流用户场景,回流用户指的是已经流失了一段时间的用户再次使用当前应用,由于用户流失了一段时间,其挖掘类标签数值已经失去了时效性,可以借助实时预测服务计算出当前更准确的标签值来替代离线标签数值。
实时预测服务的重点是模型在线化部署以及实时特征获取。模型在线部署的方式取决于模型训练所使用技术和框架,比如通过Spark MLlib生产的模型,可以借助其自带的工具包实现模型在线部署;使用TensorFlow,PyTorch开发的深度学习模型,可以借助其自带的Serving方法进行模型在线化;如果使用的是XGBoost训练模型,可以借助XGBoost4J在Java中实现模型实例化;有些公司也会自研模型实例化平台,比如百度的双塔模型,将复杂的离线模型训练转换为Embedding加轻量级模型,可以快速实现模型上线;JPMML(预测模型标记语言)将模型与在线服务化解耦,各种模型都可以使用JPMML表达,最终可通过不同语言解析JPMML并实例化模型。
实时特征获取的方式主要有两种。第一种是业务在调用实时预测服务时附带上所有所需实时特征,这些特征可以直接从客户端实时获取,比如设备类型、操作系统、IP地址等。第二种是集中式管理实时特征,即通过消费各种实时数据流生成实时特征并存储到缓存中,在实时预测过程中直接查询使用该实时特征数据。第一种方式调用方的工作量较大,需要预先获取各类特征数据,而实时预测服务提供方的工程逻辑简单,维护成本较低;第二种方式调用方的使用服务的成本较低,而实时预测服务提供方需要维护一套实时特征库,开发量和资源需求量较大。图4-14展示了模型实例化和特征获取的流程图。
标签实时预测服务是算法模型在线化的一种特殊情况,不仅要求模型需要提供在线服务,而且需要传入实时特征。从技术的角度,所有的挖掘类标签的算法模型都可以提供预测服务,但是用户画像场景下,离线挖掘类标签基本可以满足业务要求,实时预测是在特殊情况下对离线标签数据的一种补充。
本节以“是否已婚”标签为例介绍标签实时预测实现方案。该标签使用XGBoost算法实现,其模型产出主要包括模型文件和特征文件。可以借助xgboost4j工具包实现模型加载和实时预测功能,其核心代码如下所示。
// 存储特征映射关系
private static Map<String, Integer> featureMap = new HashMap<>();
private static Booster booster;
// 读取并加载特征文件数据,特征文件第一列是特征ID,第二列是特征数值
// 示例:100 phone_brand:iphone
private static void loadFeature(List<Resource> featurePath) throws IOException {
for (Resource input : featurePath) {
BufferedReader reader = new BufferedReader(new InputStreamReader(input.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
String[] items = line.split("\t");
featureMap.put(items[1].toLowerCase(), Integer.valueOf(items[0]));
}
reader.close();
}
}
@Data
@AllArgsConstructor
public static class FeatureElement {
private String featureName; // 特征名称
private float featureValue; // 特征数值
}
// 加载模型文件
private static void loadModel(Resource modelPath) throws XGBoostError, IOException {
booster = XGBoost.loadModel(modelPath.getInputStream());
}
public static void main(String[] args) throws IOException, XGBoostError {
byte[] featureBytes = null; // 特征文件bytes
byte[] modelBytes = null; // 模型文件bytes
Resource featureResource = new ByteArrayResource(featureBytes);
Resource modelResource = new ByteArrayResource(modelBytes);
// 加载模型文件和特征文件
loadFeature(Lists.newArrayList(featureResource));
loadModel(modelResource);
// 构建特征数据,特征数据来源自调用方或者从实时特征库中查询获取
List<FeatureElement> marrayOrNotFeature = Lists.newArrayList();
marrayOrNotFeature.add(new FeatureElement("特征1", 100.0f));
marrayOrNotFeature.add(new FeatureElement("特征1", 20.0f));
// 构建预测使用的特征数据
List<Integer> featureIds = Lists.newArrayList();
List<Float> featureValues = Lists.newArrayList();
for (FeatureElement element : marrayOrNotFeature) {
String featureName = element.getFeatureName().toLowerCase();
float featureVal = element.getFeatureValue();
Integer featureId = featureMap.get(featureName);
if (featureId != null) {
featureIds.add(featureId);
featureValues.add(featureVal);
}
}
// 通过模型预测结果数值
int numColumn = featureIds.size();
int[] colIndex = featureIds.stream().mapToInt(i -> i).toArray();
long[] rowHeaders = new long[] {0, colIndex.length};
float[] data = Floats.toArray(Doubles.asList(featureValues.stream().mapToDouble(i -> i).toArray()));
DMatrix dmat = new DMatrix(rowHeaders, colIndex, data, DMatrix.SparseType.CSR, numColumn);
// predicts即不同预测结果概率值,根据概率值大小即可确定预测结果
float[][] predicts = booster.predict(dmat, false, 0);
dmat.dispose();
}
代码中首先获取特征文件和模型文件的字节数组,然后封装成Resource对象后分别进行加载;其次构建特征数据,特征数据来自请求方或者从实时特征库查询获取;最后构建XGBoost预测所需的数据结构DMatrix并最终获取预测结果predicts。是否已婚标签预测结果包含在二维数组predicts中,该数据包含已婚和未婚的概率,业务可以根据约定的阈值大小确定是否已婚。比如已婚的预测概率是0.68,超过约定的阈值0.65,则可以认为该用户已婚。
实际项目中同时支持实时预测服务的算法模型较多,而且每一个模型的文件大小、计算复杂度和线上调用量都不相同,在资源有限的情况下需要设计合理的架构来支持更多的实时预测模型,图4-15展示了一个可行的实时预测服务架构。
为了调用方使用方便,实时预测服务需要对外提供统一的接口,但是由于其模型实例化的方式不同,所以需要一个代理层来封装多种不同的实现逻辑。所有的请求统一接入代理层并根据标签配置路由到不同模型服务,不同服务返回的结果也要经过代理层封装后按统一格式返回。以XGBoost模型实例化为例,针对不同的业务可以部署多个模型实例化集群,按业务需求可以实现个性化标签配置和服务性能拓展。在同一个业务集群内,不同模型根据其资源消耗情况被分配到不同的服务节点(物理机或者容器实例),保证资源利用率最大化。模型文件和特征文件更新后可以自动更新到实时预测服务中,保证了服务能力的迭代升级。
本文节选自《用户画像:平台构建与业务实践》,转载请注明出处。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有