首页 > 其他分享 >解析机器学习中的数据漂移问题

解析机器学习中的数据漂移问题

时间:2023-05-21 11:03:51浏览次数:52  
标签:gt 机器 模型 drift 解析 data obs 漂移


编者按:当模型在生产中呈现的输入与训练期间提供的分布不对应时,通常会发生数据漂移。

Vatsal P.的这篇文章,介绍了如何通过漂移指标直观了解数据漂移程度,并n通过一个使用合成数据的例子来展示如何利用Python计算数据随时间的漂移指标。

以下是译文,Enjoy!

作者 | Vatsal P.

编译 | 岳扬

解析机器学习中的数据漂移问题_深度学习

由涌现AIGC引擎生成

本文主要介绍了数据漂移的基本概念以及如何利用Python处理数据漂移问题。本文涉及两种计算漂移指标的方法,即交叉熵和KL散度的实现和区别。

以下是这篇文章的大纲:

  1. 什么是数据漂移?
  2. 漂移指标2.1 交叉熵2.2 KL散度
  3. 解决方案架构程序依赖要求
  4. 程序实现4.1 生成数据4.2 训练模型4.3 生成观察结果4.4 计算漂移指标4.5 随时间变化的漂移可视化
  5. 计算漂移指标的障碍
  6. 结语

1 什么是数据漂移?

MLOps是构建机器学习模型并将其部署到生产环境中的一个组成部分。数据漂移可以属于MLOps中模型监控的范畴。它指的是量化观察数据相对于训练数据的变化,这些变化随着时间的推移,会对模型的预测质量产生巨大的影响,而且往往是更糟的影响。跟踪与训练特征和预测有关的漂移指标应该是模型监测和识别模型何时应该重新训练的重要组成部分。

可以参考作者的另一篇文章(https://pub.towardsai.net/monitoring-machine-learning-models-in-production-1633f23d1e0b),了解在生产环境中监控ML模型相关概念和架构的更多细节。

https://pub.towardsai.net/monitoring-machine-learning-models-in-production-1633f23d1e0b

你可能不想监测与你的模型预测或模型特征相关的漂移,比如当你在进行模型预测的基础上定期重新训练模型。此为一种与时间序列模型的应用相关的常见情况。然而,你可以去追踪其他指标,以确定你所生成的模型质量。本文将主要关注那些与经典机器学习(分类、回归和聚类)相关的模型。

2 漂移指标

下文概述的两种指标都是量化概率分布相似程度的统计方法。

2.1 交叉熵

交叉熵可以通过以下公式定义:

解析机器学习中的数据漂移问题_人工智能_02

交叉熵计真实的概率分布

  • p:真实的概率分布
  • q:估计的概率分布

从信息论的角度来看,熵反映了消除不确定性所需的信息量[3]。请注意,分布A和B的交叉熵将与分布B和A的交叉熵不同。

2.2 KL散度

Kullback Leibler散度,也称为KL散度,可以通过以下公式定义:

解析机器学习中的数据漂移问题_深度学习_03

  • P:真实的概率分布
  • Q:估计的概率分布

然后,Kullback-Leibler散度是使用针对Q优化的编码而不是针对P优化的编码对P的样本进行编码所需的比特数的平均差[1]。请注意,分布A和B的KL散度与分布B和A的KL散度不同。

这两种度量都不是距离度量(distance metrics),因为这些度量缺乏对称性。

entropy / KL divergence of A,B != entropy / KL divergence of B,A

3 解决方案架构

下图概述了机器学习生命周期的运行方式,同时也包括了模型监控。正如上文说明,为了监测模型的性能,应该在训练阶段保存各种数据,也就是用于训练模型的特征和目标数据。这样就可以提供一个真实的基础数据源,以便与新的观察结果进行比较。

解析机器学习中的数据漂移问题_ai_04

图片模型监测架构,图片由作者提供

3.1 程序依赖要求

以下Python模块及其版本是下文源代码运行的依赖。这些都是著名的数据科学/数据分析/机器学习的库,所以对大多数用户来说,安装特定的版本应该不是什么大问题。

Python=3.9.12
pandas>=1.4.3
numpy>=1.23.2
scipy>=1.9.1
matplotlib>=3.5.1
sklearn>=1.1.2

4 程序实现

下面将通过一个使用合成数据的例子来展示如何计算数据随时间的漂移指标。请注意,该示例生成的值不会与你操作生成的值一致,因为它们是随机生成的。此外,由于是随机生成的,所以从提供的可视化图像和数据中并不能解释结果。我们的目的是提供可重复使用和可重新配置的代码供你使用。

4.1 生成数据

import uuid
import random
import pandas as pd
import numpy as np
from scipy.stats import entropy
from matplotlib import pyplot as plt
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
# generate data
def generate_data(n):
    """
    This function will generate n rows of sample data.
    
    params:
        n (Int) : The number of rows you want to generate
        
    returns:
        A pandas dataframe with n rows.
    """
    data = {
        'uuid' : [str(uuid.uuid4()) for _ in range(n)],
        'feature1' : [random.random() for _ in range(n)],
        'feature2' : [random.random() for _ in range(n)],
        'feature3' : [random.random() for _ in range(n)],
        'target' : [sum([random.random(), random.random(), random.random()]) for _ in range(n)]
    }
    return pd.DataFrame(data)
  
sample_df = generate_data(1000)

上述代码将生成一个合成数据集,该数据集由1000行和列uuid、feature1、feature2、feature3、target组成。这是我们的基础数据,模型将在此基础上进行训练。

解析机器学习中的数据漂移问题_ai_05

 

4.2 训练模型

# train model
ft_cols = ['feature1', 'feature2', 'feature3']
X = sample_df[ft_cols].values
Y = sample_df['target'].values

X_train, X_test, y_train, y_test = train_test_split(
    X, Y, test_size=0.3
)

rfr = RandomForestRegressor().fit(X_train, y_train)

为了本教程的目的,上述代码允许使用者根据我们上面生成的特征和目标创建一个随机森林回归模型。假设这个模型会被推送到生产环境中,并且每天都会被调用。

4.3 生成观察结果

# generate observations
obs_df = generate_data(1500)
obs_df.drop(columns = ['target'], inplace = True)

# generate predictions
obs_df['prediction'] = obs_df[ft_cols].apply(lambda x : rfr.predict([x])[0], axis = 1)

obs_df = obs_df.rename(columns = {
    'feature1' : 'obs_feature1',
    'feature2' : 'obs_feature2',
    'feature3' : 'obs_feature3'
})

上面的代码将生成第一天与模型投入生产并被调用的特征相关观测数据。现在我们可以直观地看到真实训练数据与观测数据之间的差异。

plt.plot(sample_df['feature1'], alpha = 0.5, label = 'Ground Truth')
plt.plot(obs_df['obs_feature1'], alpha = 0.5, label = 'Observation')
plt.legend()
plt.title("Visualization of Feature1 Training Data vs Observations")
plt.show()

解析机器学习中的数据漂移问题_数据_06

图片训练数据与feature1的观测数据可视化,图片由作者提供

从上图可以看出,在模型投入生产的第一天,该特征的观测值比实际情况要多。这是一个比较麻烦的问题,因为我们不能去比较两个长度不一样的数值列表。如果我们比较两个长度不同的数组,就会产生错误的结果。现在,为了计算漂移指标,我们需要使观测值的长度与真实数据的长度相等。我们可以通过创建N个buckets,并确定每个bucket中的观测值的频率来实现这一需求。其实本质上这是创建一个直方图,下面的代码片段可以显示这些分布的相互关系。

plt.hist(sample_df['feature1'], alpha = 0.5, label = 'Ground Truth', histtype = 'step')
plt.hist(obs_df['obs_feature1'], alpha = 0.5, label = 'Observation', histtype = 'step')
plt.legend()
plt.title("Feature Distribution of Ground Truth Data and Observation Data")
plt.show()

解析机器学习中的数据漂移问题_ai_07

图片真实数据的特征分布与feature1的观测数据,图片由作者提供

现在两个数据集的规模相同,我们可以比较两个分布的漂移情况。

4.4 计算漂移指标

def data_length_normalizer(gt_data, obs_data, bins = 100):
    """
    Data length normalizer will normalize a set of data points if they
    are not the same length.
    
    params:
        gt_data (List) : The list of values associated with the training data
        obs_data (List) : The list of values associated with the observations
        bins (Int) : The number of bins you want to use for the distributions
        
    returns:
        The ground truth and observation data in the same length.
    """

    if len(gt_data) == len(obs_data):
        return gt_data, obs_data 

    # scale bins accordingly to data size
    if (len(gt_data) > 20*bins) and (len(obs_data) > 20*bins):
        bins = 10*bins 

    # convert into frequency based distributions
    gt_hist = plt.hist(gt_data, bins = bins)[0]
    obs_hist = plt.hist(obs_data, bins = bins)[0]
    plt.close()  # prevents plot from showing
    return gt_hist, obs_hist 

def softmax(vec):
    """
    This function will calculate the softmax of an array, essentially it will
    convert an array of values into an array of probabilities.
    
    params:
        vec (List) : A list of values you want to calculate the softmax for
        
    returns:
        A list of probabilities associated with the input vector
    """
    return(np.exp(vec)/np.exp(vec).sum())

def calc_cross_entropy(p, q):
    """
    This function will calculate the cross entropy for a pair of 
    distributions.
    
    params:
        p (List) : A discrete distribution of values
        q (List) : Sequence against which the relative entropy is computed.
        
    returns:
        The calculated entropy
    """
    return entropy(p,q)
    
def calc_drift(gt_data, obs_data, gt_col, obs_col):
    """
    This function will calculate the drift of two distributions given
    the drift type identifeid by the user.
    
    params:
        gt_data (DataFrame) : The dataset which holds the training information
        obs_data (DataFrame) : The dataset which holds the observed information
        gt_col (String) : The training data column you want to compare
        obs_col (String) : The observation column you want to compare
        
    returns:
        A drift score
    """

    gt_data = gt_data[gt_col].values
    obs_data = obs_data[obs_col].values

    # makes sure the data is same size
    gt_data, obs_data = data_length_normalizer(
        gt_data = gt_data,
        obs_data = obs_data
    )

    # convert to probabilities
    gt_data = softmax(gt_data)
    obs_data = softmax(obs_data)

    # run drift scores
    drift_score = calc_cross_entropy(gt_data, obs_data)
    return drift_score
    
calc_drift(
    gt_data = sample_df, 
    obs_data = obs_df, 
    gt_col = 'feature1', 
    obs_col = 'obs_feature1'
)

上面的代码概述了如何计算观察数据相对于训练数据的漂移(使用scipy中的entropy实现)。首先通过matplotlib中的hist方法将输入向量的大小归一化为相同的长度,通过softmax函数将这些值转换为概率,最后通过熵函数计算出漂移指标。

4.5 随时间变化的漂移指标可视化

drift_scores = {k:[] for k in ft_cols}
days = 5
for i in range(days):
    # calculate drift for all features and store results
    for i in ft_cols:
        drift = calc_drift(
            gt_data = sample_df, 
            obs_data = generate_data(1500), 
            gt_col = 'feature1', 
            obs_col = 'feature1'
        )
        drift_scores[i].append(drift)
        
drift_df = pd.DataFrame(drift_scores)

# visualize drift
drift_df.plot(kind = 'line')
plt.title("Drift Scores Over Time for Each Feature")
plt.ylabel("Drift Score")
plt.xlabel("Times Model Was Used")
plt.show()

解析机器学习中的数据漂移问题_ai_08

 

图片与模型中每个特征相关的漂移指标可视化,随模型在生产中的使用时间而变化,图片由作者提供

对基于数据集产生的结果可以设定阈值,如果模型的大多数重要特征的漂移分数超过该阈值,这将是重新训练模型的一个重要指标。对于基于树的模型,可以通过sklearn或SHAP来识别每一个特征的重要性。

5 计算漂移指标的障碍

在计算机器学习模型的数据漂移指标时,可能会遇到各种障碍:

  1. 处理值为0的特征值或预测值。这将产生与两个漂移实现相关的除以0的错误。对于该问题,一个快速而简单的解决方法是用一个非常接近于零的极小值来代替零。由于监测到的数据漂移可能是一种别人没有遇到的情况,所以要了解这对你正在处理的问题会产生什么影响。
  2. 比较一对长度不相同的分布。假设你在与每个特征和目标相关的1,000个观测值上训练模型,而每天生成预测时,根据平台获得的流量显示特征和目标的观察量从1,000到10,000不等。这明显是有问题的,因为你不能比较两个不同长度的分布。为了解决这个问题,可以使用上文代码实现中所做的分选方法,将训练数据和观测值分选成相同大小的组,然后在这些数据之上计算漂移。这种情况可以通过matplotlib库中的histogram方法轻松完成。
  3. 在使用softmax函数将频率转换为概率时得到NaN值。这是因为softmax函数依赖指数,在softmax的输出中得到NaN的结果是因为计算机无法计算一个大数字的指数。对于这种情况,需要另一种不使用softmax的实现方法,或者研究怎样将你传入的数值规范化,以便softmax能够工作。

6 结语

这篇文章的重点是详细介绍如何在经典机器学习的应用中计算数据漂移。本文回顾了常见的漂移计算指标(如KL Divergence和Cross Entropy)相关的原理和实现。

此外,这篇文章还概述了我们在尝试计算漂移时遇到的一些常见问题。比如当有零值时,除以零的错误和关于比较一对大小不一样的分布的问题。需要注意,这篇文章主要对那些不经常重新训练模型的人有帮助。模型监测将作为一种重要手段来衡量一个模型是否成功,并确定它的性能何时因漂移而出现退步。这两者都是重新训练或重新进入模型开发阶段的指标。

欢迎在我的GitHub页面上查看与本教程相关的资源库。(https://github.com/vatsal220/medium_articles/tree/main/data_drift)

参考资料

https://en.wikipedia.org/wiki/Kullback-Leibler_divergence

https://en.wikipedia.org/wiki/Cross_entropy

https://stats.stackexchange.com/questions/357963/what-is-the-difference-cross-entropy-and-kl-divergence

https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.entropy.html

本文经原作者授权,由Baihai IDP编译。如需转载译文,请联系获取授权。


标签:gt,机器,模型,drift,解析,data,obs,漂移
From: https://blog.51cto.com/u_15525866/6318742

相关文章

  • 机器人手眼标定Ax=xB(eye to hand和eye in hand)及平面九点法标定
    一、背景Calibration是机器人开发者永远的痛。虽然说方法说起来几十年前就有,但每一个要用摄像头的人都还是要经过一番痛苦的踩坑,没有轻轻松松拿来就效果好的包。机器人视觉应用中,手眼标定是一个非常基础且关键的问题。简单来说手眼标定的目的就是获取机器人坐标系和相机坐标系的关......
  • 2023中国重庆医疗器械博览会|医疗器械影像展|医疗自动化机器人设备展览会
    2023中国重庆医疗器械博览会|医疗器械影像展|医疗自动化机器人设备展览会时间:2023年11月8~10日  地点:重庆国际博览中心(悦来) 展会前景:医疗器械行业涉及医学、机械、电子及控制、材料科学等多个学科,是一个多学科交叉、知识密集、资金密集的高技术产业。而高新技术医疗设备的基......
  • 互联网医院系统源码解析:实现在线问诊、挂号和支付功能
    互联网医院系统为大家的日常看病提供了更加便捷的服务,近期热度极高。本篇文章,小编将从互联网医院系统源码的角度,解析其如何实现在线问诊、挂号和支付功能。一、基本架构1. 前端前端主要由HTML、CSS和JavaScript等技术实现,通过浏览器与用户进行交互。互联网医院系统源码的前端的主......
  • 知识库AI机器人训练接口对接-唯一客服系统文档中心
    如果你的需求仅仅是对接自训练的ChatGPT接口,实现自己的个性化机器人,那么可以看看下面的个性化ChatGPT调用接口前提条件是已经搭建好了知识库服务,该服务默认监听端口8083文件上传训练接口地址POST http://127.0.0.1:8083/{集合名称}/uploadDoc该接口支持上传docx、txt、xlsx、p......
  • linux DNS域名解析
    目录 一、DNS概念二、域名格式类型三、查询类型四、解析类型五、配置DNS六、dns解析实验1.配置正向解析2.反向解析3.主从解析             一、DNS概念概念:域名和IP地址的相互映射的分布式数据库,可以更好的访问互联网。......
  • Python request请求 解析
    importloggingimporthttp.clienthttpclient_logger=logging.getLogger("http.client")defhttpclient_logging_patch(level=logging.DEBUG):"""EnableHTTPConnectiondebugloggingtotheloggingframework"""......
  • C#Xml文档的解析
    1<?xmlversion="1.0"encoding="utf-8"?>2<skills>3<skill>4<id>1</id>5<namelang="cn">a</name>6<damage>100</damage>7</skill>......
  • 基于机器人自主移动实现SLAM建图
    博客地址:https://www.cnblogs.com/zylyehuo/基于[移动机器人运动规划及运动仿真],详见之前的博客移动机器人运动规划及运动仿真-zylyehuo-博客园参考链接Autolabor-ROS机器人入门课程《ROS理论与实践》环境配置ubuntu18.04成果图step1:编写launch文件......
  • 模块与包,反序列化源码解析,drf请求响应,视图组件两个视图基类
    0模块与包的使用#模块与包 -模块:一个py文件,被别的py文件导入使用,这个py文件称之为模块,运行的这个py文件称之为脚本文件-包:一个文件夹下有__init__.py#模块与包的导入问题 '''0导入模块有相对导入和绝对导入,绝对的路径是从环境变量开始的1......
  • 横向对比 11 种算法,多伦多大学推出机器学习模型,加速长效注射剂新药研发
    内容一览:长效注射剂是解决慢性病的有效药物之一,不过,该药物制剂的研发耗时、费力,颇具挑战。对此,多伦多大学研究人员开发了一个基于机器学习的模型,该模型能预测长效注射剂药物释放速率,从而提速药物整体研发流程。关键词:长效注射剂机器学习嵌套交叉验证本文首发自HyperAI超神经......