Detecting drift: how to evaluate and explore data drift in machine learning systems
When your ML model is in production, you might observe data and prediction drift: a meaningful change in the input data distributions and model output. In cases where you don't get the true labels or actual values fast, this drift might be the only proxy for the model performance. Drift analysis can also be helpful in debugging the model performance drop. But how exactly to evaluate it in practice? Should you look at descriptive feature statistics, apply statistical tests to compare distributions, and which exactly? In this talk, I will give an overview of the possible approaches to drift detection, and how to implement and visualize the results.
This session took place in track Machine Learning & Stats and was classified suitable for some domain / some python by the speaker.
Transcript (auto)
Auto-generated from the recording utilizing Open-Source AI. Speaker labels (Speaker 1, Speaker 2) reflect diarization, not identity. Timestamps refer to the recording.
Speaker 1 [00:02]
Hi there! I'm very happy to be part of PyCon and PyData conference Berlin. I want to thank all of you who joined. I hope this will be a useful and interesting time. Today we're going to discuss detecting drift. We're going to tackle the question how to evaluate and explore data drift in machine learning systems. My name is Emilia Djal. I am co-founder and CTO of Evidently AI. At Evidently we build an open source tool to evaluate, test, and monitor machine learning models in production. Prior to Evidently, I helped industrial companies to build and deploy machine learning-based services in production, so the experience I gained over this time influences the way how we built this tool in Evidently. So, everybody knows that building a successful machine learning-based service is a pretty hard task by itself, because we had to run a bunch of experiments, then develop the service, and then deploy it in production but unfortunately the job hasn't stopped there because model starts to interact with the real world environment this environment is often unstable and with time model's quality tends to decrease when model operates in production each way failure can cost something because well it's already influenced the business or technological process so we had to do something with that and the standard answer is monitoring. Basically when we monitor machine learning models we either measure model quality or error and it's even better when we understand how exactly model interact with the business process. In this case you can also monitor things like product metrics, like purchases, peaks, views, etc. But it's not always enough and I'm going to drop a couple of examples where we cannot just rely on standard machine learning monitoring which is quite nice for a lot of cases but not all pretty often we deal with some forecasting services for example demand forecast for some products or services and here we can have a solid horizon of our predictions it can be weeks it can be months and here we just cannot rely on the standard performance monitoring because for calculating some quality metrics you need to wait for this weeks or months in order to get our feedback or ground truth to calculate the metric. So this is the first example. The second is the volatile target function which we're trying to estimate with the help of machine learning. In this case where when function is tend to change its values very often it's hard to miss the moment when the quality starts decreasing because just the function is very volatile. When we deal with the big amounts of objects and we have different object segments, for example, different segments of users, it can be as well a problem because, well, if you work with regression problem, model can underestimate the target function on some segments, it can overestimate the target on another segment, and when we aggregate the quality, the zeros can overcompensate one another. One can say okay you can just analyze the model's quality separately on different segments and this is true but became a bit complicated when you have like really a lot of segments like tens or fifties or more. And the last example I want to bring here is the cases where we have a delay before we get the feedback or ground truth but this delay is not that high. For example, it can be just hours or days, and in this case, we can just rely on the past quality in order to monitor the model's performance. And sometimes it's enough, but sometimes not, because we can just miss the moment when the quality dropped. So what can we do? And the answer is, let's take data we have at hand now and try to calculate something. And let's call it early monitoring. There are basically several things which you can calculate when you have only input data and probably models output. This is data quality, data drift, and output drift. Let's discuss them in more details. So data quality is something that I would say we need to measure almost always because in most cases when something is wrong with the model that's because input data is wrong. And even if we do not have any reference data which we can use as the basis for comparison to our current data, we can still calculate something. For example, we can always calculate statistics like share of missing values, share of constant features. We can explore correlations between pairs of features and correlations between features and models output because we want to, for example, have only features in our dataset which correlates between each other less than some specific values. Or we can prefer to keep correlations between models' output and features under some thresholds. We can also measure the ranges for each feature, and we can come up on some expectations just based on our domain knowledge or feature concepts, like prefer to have non-negative age, non-negative salaries, and things like this. So there are a lot of things you can calculate even not having reference data. When you have reference data it's much easier because because we can compare, right? So we can take the data from the training stage or we can use the previous model batch and we can compare our current data with this reference data. So here I can easily compare distributions and other statistics. For example, some descriptive statistics like means, medians, quantiles, mean marks between features from reference and current, right? And here there are basically two ways how we can do that. First is simple, let's say, pointwise estimation, where you can calculate, for example, median on top of reference dataset, then median for the same feature on current data, and then you just calculate difference, and that's it. You can then set up some threshold on this difference and alert when it's too high, for example. But everybody knows that this is not robust enough, let's say, because if you have some outliers or the sample sizes are different, then these statistics can be quite different, right? But maybe for medians it's not that correct because medians are pretty a stable right but for means and other statistics it is and in this case you can use some interval estimation for example with help of some statistical tests or other statistical procedure calculate the confidence intervals for your descriptive statistics and compare them into on base basis on top of these intervals right so we compare not just means but interval around it and set some alarms on top of this information. At Evidently, you have a pre-built dashboard that helps you to analyze data quality. And if you have reference and current or just current data, you can easily create the Evidently dashboard, either interactive one or in JSON format and see a lot of descriptive statistics or results of comparison and see whether the data quality is good enough. Together with data quality, you can measure more complicated things like data drift, which is basically a comparison between feature distribution. Data drift can be with and without performance decay, right? But sometimes if very important features are drifting and there is no very logical explanation apply this can be an issue and the signal of the early um early signal of the potential problems let's say so uh there are several important things that we should take into account when we calculate such drifts like which exact statistical test we use what are the reasonable confidence for the drift detection and what are alert conditions and we're going to discuss it but um before we are going into this discussion i just want to say that all this works for models output as well so we can calculate not only drift for input features but also drift for models output which is quite nice because if you have results of the previous models run on previous batches of data right you can compare the models output on the current batch of data with the previous one and come up with some conclusions which are very nice and yeah now the question how exactly do we define that data has drifted. So well, we need to choose a specific test, come up with the confidence level, and then set up some thresholds for our alarms. And there are a lot of different approaches to how you can measure data drift. Let's say that the standard one is using statistical tests. And here you can go for parametric tests or non-parametric tests. tests. It evidently builds and uses both approaches, and there are some considerations on which approach to choose. So I believe parametric tests are very nice when you have some subset of golden features, I mean key performance, which you know, and you know the meanings, and you can come up with some expectations on the future distributions and some parameters these distributions like mean values, mean distribution value, standard graduation, and things like that. So if you have only one sample, you can generate these expectations. For example, you want the age feature being normally distributed around 25 years or things like this. It's just an example. And in this case, if you can come up with some expectations, you can use one-sample tests like Z-test or more often T-test and compare the observed mean with the expected one. Or for binary features, you can use one-proportional test, so a lot of things like this. If you have two distributions, mainly you have reference data, it became even easier because you can use two-proportional, two-samples tests like two-proportional test for binary features or two-sample t-test for means, things like this. So the advantages of the parametric tests are that they are more sensitive, which means that you can detect drift earlier if you have some parametric tests. But there are some disadvantages which are, first is that these parametric tests are more demanding because, well, we need to have the data which has some specific distributions, right? And we need to choose and fine-tune the test for each individual feature, which is time-consuming. And if you have really a lot of features, probably you don't want to select specific tests for each feature. But if you have a small amount of very important ones, why not to do that? And an alternative approach is using non-parametric tests. These non-parametric tests are much less demanding, right? So you can probably select the non-parametric tests based on just feature type. I mean numerical, categorical, binary, and some sample configurations like sample size for categorical features. It makes sense to make sure that for each category you have not less than, let's say, five values for each bucket for k-squared tests. So there are actually some limitations, but they are not that strict as in parametric tests. So probably here you can just easily optimize the select of each specific test for each feature and go for these automated estimations. For example, you can set the Kolmogorov-Smirnov test for all of numerical features or maybe a case sample Anderson test if you prefer to get more sensitive, to have more sensitive procedure for drift detection and for categorical features you can use for example Pearson k-squared test and if you have like very small data set maybe think about some exact tests but for very small samples in most cases when we apply machine learning model in production we have big enough case samples to use other tests but why not to consider that and actually to add to it, I believe you shouldn't limit your estimation only for statistical tests in some senses. You can perfectly use any procedure to compare distributions and some distances, like Westerstein distance is the perfect example of such evaluation procedure. So you can use distances between probability distributions, you can use some indexes, it all works very well. So the only consideration here is these non-parametric tests are in most cases less sensitive to drift comparing to parametric tests, which means probably we will detect this drift a bit later, but it's easier to apply and it's much easier to choose between different tests. So evidently, as I said before, we use both parametric and non-parametric tests. We use distances, we use indexes, and moreover, Evidently can automatically select the right statistical test for each of your features. So if you want to quickly get the dashboard with the information about data drift, p-values, distances between your features, you can just collect the reference and current data, pass this data to Evidently, and get the dashboard in HTML or JSON format to explore the drift. so it's open source and why not to try if you're interested in drift. There are more questions I wanted to tackle considering data drift estimation and first is large data sets. In most cases when we deal with large data sets we can get over sensitive results so we always can find some places where our features are different and the statistics will often say that here is a drift And here I want to make one note. Initially, the statistics was made to work with samples, right? Not with the whole general population, because if you have the whole population, you can just directly measure whatever you want, right? And for machine learning, it's pretty important in duration because it doesn't make a lot of sense to apply your statistical tests for hundreds and thousands of objects. It makes sense to go for more practical solution and either do sampling or bucketing. So sampling helps us to select some subsamples from our reference and current data and apply statistical tests to these subsamples. If you have a lot of data the random sampling strategy will work perfectly in this case but if you have let's say non-balanced classification problem then it makes sense to explore other sampling strategies like stratification, right? And in this case, you have just better samples. And alternative to sampling solution is bucketing. Here you just split your data into some buckets, then you calculate the statistics individually for each bucket, for example, mean feature value, and then you compare means using statistical tests. In other words, you aggregate some value over your buckets, and then you compare this aggregated value between each other and by doing this you reduce the data size. The advantage is that you do not need to think over the right sampling strategy, but the downside is that it's maybe potentially heavier and you still need to like come up with the amount of buckets, right? So whether you use 20 or 30 or 100, but if you have historical data you can experiment on top of that and find the optimal amount of buckets and other parameters of your calculation procedure. So historical data always helps to like decrease the amount of uncertainty and come up with the right evaluation procedure. The second question I want to tackle here is non-batch models because for batch models it's pretty straightforward. You just always have batches which are like data samples and you can compare distributions between different batches. But when it comes to continuous data stream, it's hard to compare something. And here I suggest to pick some window function and generate samples by these windows. The questions here are what are the size of these window functions? What are the steps for moving this feature? But again, if you have historical data, you can experiment over there and then decide whether you have the window function with the window size equal to one hour or equal to one day. It just depends on the case and the data you have. And finally, how to specify all the tests and metrics and thresholds for alerts. There are basically two strategies. The first one is go with default. In this case, you can just pick the tests based on the feature values, and, for example, start your monitoring using tools like Evidently, where you have everything predefined. Start monitoring, and then based on the alarms, like false alarms and the right alarms, adjust some parameters. For example, adjust some thresholds for different features and maybe for models output. This is the option one and I really suggest to go for this option if you need to set up monitoring earlier and start monitoring what has happened with your production model. The second option is a bit more complicated but if you have some historical data and some time resources I would go for that option. Here the idea is to use your historical data to specify all the suitable tests and drift conditions. So what you can do here is for example select the amount, the moment in time where you had no drift, define the candidate test, and apply them over that time. Then you can pick the most sensitive test, mainly with the lowest p-value, but one that still does not detect drift. So this test works well because there is no drift and it does not detect that, but it's very sensitive and if the data will differ a bit much, it will say that this is the data drift here. And then you can, it's even better if you have a period in time from your historical data where you have drift, because you can test your selected statistical test against this drift and make sure that it detects this moment. Or you can like create some synthetic data with the drift and see whether your test works or not. And then after you do some experiments, you can just reuse this architecture for your production data. So again, a bit more complicated, but you will specify and adapt your test to your specific model based on the historical data. And finally, I want to mention some nuances into the drift interpretation, because as I said before, data drift and prediction drift are not always good. It's highly dependent on the context. And here are two examples. Let's say we detected data drift and not detecting prediction drift. It can be a positive interpretation because if we detected drift like for non-important features, so important features did not drift, and model is robust enough so model's output did not drift, then probably there is no need to intervene and and model can survive it. It can be vice versa. For example, this drift, which were detected, were detected on top of very important features. And probably model should have reacted on that because something important has changed, but model didn't, which means that model probably does not extrapolate that well. In this case, it makes sense to do some ad hoc analysis and intervene. And vice versa, right? If you detected both data drift and prediction drift, one can say this is definitely a problem, but it might be and might not. Let's say our important features has changed and model's output also has changed, but it has changed in a very predictable and logical way. For example, the prices go down and model started to predict higher sales. So probably model extrapolated pretty well and there is no need to intervene. Model can survive that. But the negative scenario is that our important features changed, model behavior is unreasonably changed, and in this case, it makes sense to intervene and maybe even stop model for further analysis. Finally, what we do if we have some issues and alerts in our early monitoring. So first will be fix all the data quality issues because when the input data is changed or corrupted, then almost definitely you'll have some problem with machine learning models, right? So first run data quality and fix all the issues with data quality and integrity. Then if you see some prediction and data drift, as we just discussed before, it highly depend on the context, right? It can be problem, it cannot be problem. And here, I suggest to go for some more complicated interpretation, which takes into account the context around of this drift, and the reaction can be from something pretty straightforward, like just retraining the model on top of new batch of data and continue to apply that to something more complicated, like calibrating or rebuilding model totally like experimenting with different algorithms and approach or even changing business logic on top of the model's outputs like maybe using some higher decision threshold maybe exclude certain segments from the analysis and send some objects to manual review maybe using some fallback system which is not rely on machine learning models but more robust and rely on some rule-based systems so there are a lot of things that we can do But anyway, it makes sense to first detect that something has changed. This is why early monitoring makes a lot of sense for production systems. So this is all I wanted to share with you today. I want to thank you for your time and your attention. And I'm happy to discuss anything related to early monitoring and answer any of your questions. Thank you so much.
Speaker 2 [23:13]
Thank you so much Emily. Now welcome live here. So we have some questions from the audience. I'm going to check them here. The first one is with too many input tests there will be many false positives due to noise or poorly defined thresholds which can lead to alarm hell. How to prevent that?
Speaker 1 [23:37]
Hi there, and thank you so much for a very important question. Yes, I personally saw such cases, and it's really important to set up the, let's say, the rule of how you're going to send alarms and operate on top of these messages about drift. So I suggest to use different threshold and test with different sensitivity for different features. And, for example, like use maybe higher thresholds for more important features, right? So to avoid these false alerts. And second is maybe play around with some sampling strategy. and for decreasing the sensitivity of tests, use the smaller samples where you like selected the objects maybe randomly. Yeah, randomly for bigger data sets is enough. So the main idea is to play with the parameters of your drift detection systems, select specific tests, select the way how you generate the sample and maybe have different thresholds for different features based on their importance.
Speaker 2 [24:56]
Thank you very much. The next question is, do you count change of standard deviation as drift? Do you have tests for that?
Speaker 1 [25:06]
Currently, no, and evidently it's not implemented, but what we definitely have is the way how we can use the custom Python function as the data drift metric. Let's say that we can implement a Python function that's taken as an input to the data frame CRS, I mean Pandas data frame, and returns a numerical value. And if you're interested in comparing standard durations, it can be the implementation of such tests. But out of the box, unfortunately, we don't have that. Maybe it's a good idea to add. Thank you so much for this question.
Speaker 2 [25:45]
evidently plan to integrate with established monitoring systems such as Grafana or Datadog.
Speaker 1 [25:52]
Well, that's again a very nice question and we are now in the process of considering different integration options. Right now we have just an example of such integration. So we just manually created the Grafana dashboard for data drift and a couple of more dashboards, data drift, model performance and things like that. And we showed it to our users to get information what they think. There are quite a lot of people who really like it. So now this is for us a good signal to start work in this direction. So right now we have an example, which is easily customizable for different machine learning models. And later this year, I believe it will be like better integration.
Speaker 2 [26:37]
interesting so next question is how is your architecture set up do you store the original metrics eg mean of column in a bucket or loaded from there
Speaker 1 [26:50]
Right now we have different analyzers, so this is like code modules, which makes the calculations and one of these analyzers is data quality. And in data quality, we store things like amount of columns and rows and column names, the descriptions of the data, right? But when it comes to monitoring and, for example, those integration with Grafana, I mean the example, we do not pass this data to Prometheus and we do not have any dashboards in Grafana related to this descriptive information. So we have different types of reports in evidently it's dashboards, HTML, and we have also JSON profiles. And in JSON profiles, we store all this information. So we do not read it from anywhere. We just read it from the data and we read config. If something useful is written in config, we also can copy it in profile. So I hope this answered the question.
Speaker 2 [28:06]
Great. One last question for the time being. Instead of asking, has significant drift occurred, would a more central question be, has drift occurred that impact the usefulness of the model?
Speaker 1 [28:21]
Yes, I think it makes a lot of sense, actually. And we're really thinking about moving to this direction. Technically, it's a bit more complicated because for drift analysis, you only need to have data about your features and maybe models output and target. But if you want to really see how much drift or just any changes in input data impact your model, it makes sense to have an access to model to like play around with such changes in features and see how the model's output changes and whether it really affects your business process it's even better when you can play around with such things but it definitely takes more complicated integration and an access to the model this is like the main reason why we now limit our calculations only to the detection of drift but that's a very wise question to like explore more whether this drift it's really correct something or not.
Speaker 2 [29:19]
Great, thank you very much and let's thank all Emily again for the great talk. Thank you
Speaker 1 [29:25]
This is so much of a pleasure.