Data valuation for machine learning

,

The core idea of so-called data-centric machine learning is that any effort spent on improving the quality of the data used to train a model is probably better spent than on improving the model itself. This tested rule of thumb is particularly relevant for applications where data is scarce, expensive to acquire or difficult to annotate.

Concepts of the usefulness of a datum or its influence on the outcome of a prediction have a long history in statistics and ML, in particular through the notion of the influence function. However, it has only been recently that rigorous and practical notions of value for data, and in particular data-sets, have appeared in the ML literature. The core idea is to look at data points known to be “useful” in some sense — for instance in that they substantially contribute to the final performance of a model — and focus acquisition or labelling efforts around similar ones, while eliminating or “cleaning” the less useful ones.

In a nutshell, data valuation for machine learning is the task of assigning a scalar to each element of a training set which reflects its contribution to the final performance of some model trained on it. This can be used to repair or prune corrupt or superfluous data, or for data collection, like active learning strategies when labelling is expensive.

While many exact methods have exponential time complexity in the size of the training set, recent advances provide either good approximation strategies or introduce alternative approaches which are starting to make this field relevant in practice. In this context, pyDVL is an LGPL library aiming to provide robust, parallel implementations of every relevant method for simple usage in applications and research. In this talk we showcase how it can be used to detect issues in data pipelines and to improve final performance. pyDVL is still in early stages of development but already provides over a dozen algorithms, runs in parallel using ray and supports sklearn-compatible interfaces and large pytorch models with out-of-core computation thanks to dask.

This session took place in track Data Handling & Engineering and was classified suitable for intermediate domain / intermediate 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:06]

It's great to be here and have the chance to talk a little bit about things that my team and I have been working on for a recent time. And this software that we built around it. So, data valuation. First, this needs to work. Data valuation, what is it? Let's first try to fix some ideas. What we're interested in here is in what is the contribution of training points to one of two things. We want to look at what a training point does, for instance, global accuracy of our model. So, overall model performance. We don't want to restrict ourselves to accuracy or anything, just global model performance. We can look at things globally, or just the single predictions. We're going to be talking about the two things in this talk. I will be presenting the first, and Christoph is going to be talking about the second one. for the purpose of this talk we're going to talk we will refer to the first part as global methods although this is by no means established in the literature or anything like this it's just for for the for the talk and for the second one we're going to be calling naming this local methods okay so for the global valuation methods I think it's good to have a little understanding of what this means to evaluate points or to value points so we're gonna explain just real quick what it is that a very simple way of doing this which is first defining an up first defining an object called utility and this is this comes from from cooperative game theory which is a field which started many of the methods that we're gonna be talking about so we find a utility which for us is give me some data I train my model on it a supervised model and I scored my model trained on this data on some fixed validation set okay this is my utility how good was the data for me this is for any subset of data that you give me but the validation set is fixed okay now i take one of my training points i fix it and i'm going to look at what this training point did for my for my for my score for my utility so first i compute the utility on the whole training set taking this point into account it is included then i'm going to compute the utility without this training point so I remove it and then I'm gonna compute the difference so what I just accuracy with accuracy without the training point that I'm interested in this is the little pseudocode and this intuitively I mean it's clear what's called leave one out it's a it's a just remove one point and look at the the accuracy basically the value of point X is the utility at the whole training set minus utility at T minus X so what's the intuition here if If removing my point made the utility go up, it was probably a bad point. So I want this thing to be negative on the other way around. And I did this for one training point, which means I need to retrain n times in order to compute the value of all n points. It's already pretty expensive, but it has a bigger drawback, which is that this has very low signal in the sense that if you have 10,000 points, usually removing one is not going to tell you much. So this method, leave one out, is not really used in practice. What people do is they look at subsets. Now, I am going to do this in and out thing for all possible subsets of the training set. This is some pseudocode. I just sample subsets. I score with and without. And then I compute a weighted mean. You can gloss over this. It's not so important. This gives rise to a family of methods called semi-values. One of them is Data Shapley, which started this whole thing in machine learning like four or five years ago, or maybe a little bit longer. So formula here, I mean, the key thing to look at is that we have a sum of our all subsets, which is pretty expensive, as you can imagine, and means 2 to the power n minus 1 retrainings if you do this naively. You don't do this naively, of course. So OK, we have an intuition. It's about removing points and adding them back. This is one family of methods. There are many others which don't use this approach, but this is the starting one. We have this. What can we do for you? We have this example out of our documentation, where we take the TopHit Spotify dataset. We want to predict song popularity, and we do this with a simple gradient boosting regressor. Now we do this thing of adding and removing points and all subsets with some magic in the background. I mean, it's not magic actually, but we do this for every training point. And now we sort them, right? We take the lowest value ones, the ones where we thought, hmm, removing them was good. And for those, we drop them. And what happens is in this training set for this model and this metric that we chose, we see an improvement in the accuracy just by dropping points. I mean, these numbers, take them with a pinch of salt. It was a simple model. We didn't do much. So you don't expect to just hit a button and get 10% more accuracy in everything you do. It's not going to happen, but you see these improvements. Okay, and this is done in three steps. First, load data set and define your model. We have a split here in train, validation, and test. okay now you define some scorer some scoring function that you care about in this case accuracy and this accuracy is measured over the validation set and your utility object okay done this the utility wraps the model and the score so data set model scoring utility and now you mix everything in one valuation method this is one example data sharply which is in the library, and you run it with JobLib in parallel here with one node backend. You fit this thing, and what you do now is, what I want to say now is that you can change the model for any model that supports a fit method. You can add your custom scorer that you can look at F1 or whatever. You can even not look at the validation set if you're not interested in that. And you can then pick any of the evaluation methods that we have. We have like a dozen, a little bit over a dozen right now in the evaluation part. And you can change the backend to Ray and run on 400 CPUs if you have them. So you have this. You fitted your thing. It took a while. And now what you do is you take your values. You drop the bad ones, like 100. I don't know. I just picked a number randomly. This is pseudocode of a sort. And you fit on your clean data. and this assertion works. I took a more conservative number here, 1.02, because this one is made up completely. Okay, profit. We just won. Now, a little caution here. This is our new interface that we're going to be releasing soon, like hopefully in the next couple of months. Currently it looks a bit different, so if you go to the documentation, don't be surprised. It's going to look different, a little bit more cumbersome. So, what we did, we removed bogus points and we increased accuracy. But this is, it's actually, it's better not to think of data evaluation as some kind of black box that you hit a button and do something, but how do I choose this threshold and what do I know? It's better to use this for inspection. So now I look at the worst points and I look at them, actually, and I see, hmm, this may be, this shows me patterns, this helps me answer the question of what's wrong with my my data so you can you can do you can maybe look at common features that the wrong data had and you can use them to maybe even debug your model because maybe it was looking at the wrong things so it's it's an inspection tool but it also can help you with acquisition if you have multiple data sources you can help this can help you pinpoint some some of them or one of them that is producing bogus bogus data and you can you find it among the sea of data points usually get. Attribution is another technique that works better with the inference methods that we're going to be talking later. And then in literature, there's more applications that we are not going to be talking about now. Well, maybe I can say that there's some recent work in improving fairness metrics, where your scorer and the thing they're interested in are different, and you can maybe improve the fairness of your model. This is some really recent work published recently. OK, so what do you need to do this? Well, first, any scale and model or anything that you wrap with a fit is not much. Some scoring function, which again, Scikit-Learn gives you for free. Or if you define one, you have the same. An imperfect data set, if you're perfect, what do you want this for, right? And you want to install PyDVL. We may want a better logo, I don't know, maybe. What frameworks? NumPy and scikit-learn, they work. JobLib for parallelization. We use memcached for caching results. And the second part that Christoph is going to be talking about uses mainly Torch, PyTorch. We're planning to support JAX. And we use Dask for large data sets. Parabell is still changing. So I mean, it's not alpha, but the changes to the interfaces I'm presenting the interface now. It's not published yet, so there are changes. So where's the catch here, right? Sounds like too good to be true. I mentioned computational cost. Two to the power n is pretty bad. Also, because this is too pretty bad, I'm going to do Monte Carlo, so I'm going to be doing Monte Carlo of some sort. So when have I converged? There's another question. Then how sensitive is this to the random seed, to data split, and all these things? There are multiple sources of randomness here. And then, finally, this is dependent on the model and the metric that I pick. This is tightly coupled to it. This thing is actually not a problem. This is a feature. It's not a bug. I mean, we really want to examine our model and our metric. So that's not a problem. Consistency across runs. If you think about it and I want to run 10 times and get exactly the same, yeah, it's pretty bad. But it doesn't matter because you don't want that. You want to select chunks of data points and look at them. you're not interested in absolute values that they're meaningless you're interested in the rankings that they give you and in chunks of data so the two big issues are cost and convergence and there are some solutions well we have Monte Carlo as we said there are a bunch of sampling strategies and a lot of optimizations that happen that help a lot that reduce the exponential complexity and bring it down to ON log N and things like this there are proxy models So instead of using your very expensive model that you refit a bunch of times, you use the one which is simpler, like KNN or something like this. And then there are methods that are specifically designed to exploit the local structure of some models, like KNN, for instance. If you use that, because of its locality, you can drop many of the utility evaluations. Then there are others, like data OOB, that is for bagging methods and doesn't work in this way at all. and there are more techniques that you can use. Okay, that was all for my part. Now Chris is going to be talking a little bit about his thing.

Speaker 2 [12:00]

Yeah, so hi everyone. So Miguel told you something about getting a quality metric for your data, like from a global viewpoint, and I would like to tell you something more about point-to-point evaluation. So having an answer to the question, what is the influence of a specific training point on the output of my model on a specific test point or on a set of test points? And for this, we use a different approach in the library. So what would be a naive thing to ask? So if I have a data and I would delete one data point from training, how does the loss on the test point change? And then you can compare those two terms. well okay but what's the problem we would have to do again a retraining for every training point right which you don't want to do i think of like a large vision model or something comparable and complexity and you have like thousands millions of training points you don't want to retrain a model, not just for one leave-out training point, right? Okay, but still you want to have an answer to the question, okay, what is my influence from point to point? Well, what can we do? There's a concept from robust statistics known as influence functions and you can somehow get an approximate answer to this question using an expression like this what's what is this so somehow this is an approximation of the change of the loss of the train test point given the training point up waiting yeah changing so it's an infinitesimal um measurement yeah sign flipped so if this expression is negative um your loss would go up. This is like, there's a mathematical derivation behind it, which has some prerequisites which are not always fulfilled, but at least you can try to compute this. And sure, what you get is it's way faster than doing a full model retraining, but still, what you have here is the inverse of a Hessian matrix, so this is the dimension of the parameters of your model. So you get memory consumption like n squared, and you would have complexity to actually compute the inverse n cubed, which is not doable. So what you do, you approximate these inverse Hessian vector products with something which is not computing the Hessian directly using implicit auto diff computation plus approximations of the metrics like low rank approximations, stochastic approximations of this and hopefully you end up in an almost linear runtime. If you do this you can ask the question is this a good idea? Can I somehow get value from this? And is the approximation quality actually the right question? And this is like an ongoing research topic to what extent the precise computation of these values is really meaningful and stable. But I would like to show you an example, like what we computed with our PyDVL package, how you could use it on your daily life. So we took a data set from NIH which is a malaria, so blood cells infected with malaria or not, so it's a binary classification vision problem and the reason we took this is we would like, we didn't want to like artificially switch labels and show you how we can do like detect our own switch labels but there was a discussion in the forum saying like in this data set there could be some mislabeled images and how do they look like so you have like this red circles dots in the cell which is a marker for infection so this is a blood image of a blood cell and if you have like these red circles dots inside it's infected and if not it's uninfected And the goal is now to, like, given the values, like, you have training points which are labeled infected or uninfected, you have test points which are labeled uninfected, infected, right, you compute these values which give you, like, the point-to-point expression for the one One has a positive or negative influence to the other one, and this you want to compute. So what you do, you have your model, by now it's Torch-based, but we like to include the JAX-defined models as well. You train, you normally train your model, you have your train, your test data, and then define your approximation in this case like this would be the naive implementation that you really like compute given your model given your your training data compute the inverse Hessian directly yeah so this happens here in the fifth step and as i said it's it's a you then you get like this point to point value right which you can batched somehow but if you have a large data set you would like to map this right over combinations of batches for training and test data so we have an additional concept that we somehow map this over batches of data yeah and then you compute these so this uh the highlighted line the last highlighted line is actually the this value and this product you have seen with the approximation of this product you have seen well and then you can write it to disk map mapped whatsoever so as i said um you don't want to actually compute um the the the session matrix or this inverse inverse you can do different approximations so this is like a low rank approximation which is projection, single value based projection, you can use randomized projections. Then you can use a different mapping model. Instead of doing sequentially, you can do it in parallel. If you have a large cluster, you map this to more worker nodes. And then again, you can calculate the influences and map them to disk. What we would like to do is to provide a library which implements recent algorithms, like preconditioned conjugate gradient, stochastic estimation, and so on and so on, and this is still growing. The hope is that it helps researchers to benchmark their new approximations on their data sets and practitioners to easily choose out of the box a grid computation model. So we get these train-to-test values. What can we do for this? Think of this for every training point, we get a vector with the influences for every test point. This is somehow a feature for a training point. Think of this in this way. this feature vector you can do like anything you like to in this case we we computed the 20 like 0.25 quantile of this values right and um i said we were looking for the negative ones like on this side so now choose like threshold look to the left right and inspect your data and what you then get so this is like when you look from the training labels which are the training data which are labeled as healthy to the healthy test data set you get something like this in this low value quantile yeah so maybe at least you could you can have a look at it and say maybe these are mislabeled data. Same for parasitized. So other way around, you're looking into the parasitized training data and the influence on the parasitized test data. And did you get maybe mislabeled data? But you could also get training points which could be just confusing. Like the one on the right it's like somehow concentric circle which is maybe confusing for the vision model to be identified as a infected as a parasitized one but it's not a yeah it's not a silver bullet you have to inspect this one and shortly what are the problems yeah so the computational complexity is this one yeah so you have to somehow come up with a method to compute these preconditioned gradients in an effective way, then you have to fit all these gradients into memory, right? And this is the restriction you have from the memory side. What can you do? Well, sure, the first thing you should think of is really from the algorithmic side to To approximate this product and for the member complexity parallelization plus out-of-core computation because it's completely parallelizable. We said it's point-to-point, it's independent, so it's completely parallelizable. And then change your approximation, change your mapping, your calculation. So for example, if you have a workstation like a DJX with several GPUs, then you could compute it like this, providing the client with a local cluster. Right and now the last question you have to ask is when to choose which scheme. So the inference functions are a good way to at least get a rough intuition. If you have large models, in this case you see they have to be smooth. So all this is based on autograd differentiation, and so this is like a prerequisite you have for the inference functions, which you might not have for the data variation. Here you see there was a gradient boosting regressor, which would not be possible for this inference function scheme. You get a point-to-point variation, so like in our example, for simplicity we computed a quantile, but you could have computed a representation of a training point given the influence features, like, for example, build a second classifier for mislabeled data points. For example, if you know a test data set which is clean, like really clean, and you have some systematic errors you know, you've collected, you could train, given these features on the the test set, you could train a classifier for your labelled data rate. For the data valuation, smaller models, it's the AskLearn interface and you get more global questions, like a simpler answer to is the point good or not. And the last thing to say, it's not a silver bullet, it's an active process, it helps you debugging your data, but it's not like automatically. It gives you support, like well-founded support, but you still have to do work. It's not an automatic process. Did I forget something? Oh yeah, so this is our team and we'll be happy to get some feedback from you and or even contributions to our open service package

Speaker 3 [25:54]

All right, thank you great talk. Are you ready to take some questions? So here comes the first question. How do you ensure that you are dropping bad data and not just difficult underrepresented data?

Speaker 2 [26:06]

Yeah, so we drop we're not dropping anything. All right. It's just Like you compute scores or like features for your training set So that helps you to like decide what to drop but we do not drop automatically It's like for the example we have shown like for the cell example It was really like the top three like the smallest three quantile values Now we just plot it. But what you would do is like get like 100 examples from a quantile of this distribution, right? And inspect this manually. This is what you actually would do.

Speaker 3 [26:43]

All right, thank you. Next question. Isn't there a concern regarding out-of-distribution performance or generalization? This seems a little like the opposite of regularization.

Speaker 2 [26:57]

I'm not sure what's meant with opposite of regularization but

Speaker 1 [27:03]

they might mean that if what the same question as the first one I think like if you drop data automatically just looking at these are bad so I throw them away the thing is bad is quote-unquote bad is I don't know we don't know if it's bad you just need to look at it because it's hurting your performance maybe it's out of distribution maybe your model is not good enough yeah you need just you just need to look at it and maybe there's a pattern that emerges or maybe or maybe you need to look at it it's not I mean I maybe the first example was a bit misleading because all you drop things and magic happens it's not that can't happen but

Speaker 2 [27:40]

For example, just to add to this, these values heavily depend on the optimization state of your model. If you're close to an actual minimum of your loss, they might work more stable, but if you're far away, which depends on your training process. The influence of this, not the influence values, but the influence of this model not being completely optimized to the local minimum has an effect as well and you this you can't automatically say or quantify in a in a good way at least we are not aware of this

Speaker 3 [28:21]

And then there's the next question regarding another package, which is called CleanLab in that case. Maybe if you heard of that package, can you contrast PyDVL and CleanLab?

Speaker 1 [28:33]

CleanLab. So I'm not very experienced with CleanLab, but I think it's more looking at changes in your data distribution when you train, right? So it takes some statistics of your data and then looks at changes in those. Data evaluation is not about that. It's more about inspecting and looking at the data, at least the methods that we present here. It can be used in other applications, but I think it might make sense to include some of the methods of PyDVL into CleanLab, and we've been thinking about that a little bit.

Speaker 3 [29:04]

How do you avoid overfitting your scoring function, likely the validation set? Would you recommend nested X validation and increase the cost even further? How to avoid overfitting?

Speaker 1 [29:19]

the scoring function can you how to avoid um yeah i mean yeah that's a problem of course there is a dependence on you on the on the validation set that you pick and if you're scoring on that so there's the assumption that is a good one uh uh and but again this would be a major problem if you were reporting errors based on this or if you were automatically doing some decision based on this, but you're not. You're just helping yourself. You're debugging your data and you're debugging your model. That's how I've used it successfully in the past, not as some part of a black box pipeline with some magic. And it is helpful for that.

Speaker 3 [30:02]

There are still questions coming in. I think we do two more questions and then people will probably rush to the lunch maybe.

Speaker 1 [30:09]

We are also happy to take questions in our GitHub, there's a discussions page where you can ask.

Speaker 3 [30:15]

so maybe two more questions can inference functions also be used for tasks other than classification for example segmentation inference function for other tasks like segmentation

Speaker 1 [30:29]

Yeah, there's no... Yes.

Speaker 3 [30:35]

And PyDVL scores sample contributions. Other packages such as SHAP are scoring feature contributions. Yeah. Can I also use PyDVL for that?

Speaker 1 [30:47]

Yes, you can. You can change that. We even have a notebook, I think, that does this. One can use it for that. It's an interesting question because you can think of feature attribution in this direction in your matrix, in your design matrix like this, or you can go data evaluation like this.

Speaker 3 [30:47]

Yes.

Speaker 1 [31:05]

And there's some recent work that does it in blocks, even. It's a 2D Shapley, something like this. So we're thinking of generalizing a little bit our interfaces to be able to do all of it.

Speaker 3 [31:20]

So, we are running over time. Next is the lunch break. If you have still open questions, come here to the front. The room is free, so you can still ask them.

Miguel de Benito Delgado

After several years working as a software developer, Miguel pursued studies in pure mathematics in Madrid and Munich. After finishing his PhD in mathematics, and a short research stay in machine learning, he finally transitioned into the field and ended up working as an applied researcher at the appliedAI Initiative, where he went on to found and head the TransferLab.

Kristof Schröder

After completing his PhD in applied mathematics, specializing in applied harmonic and numerical analysis, Kristof developed a keen interest in the rapidly evolving field of artificial intelligence. This interest inspired him to transition his career towards AI engineering, where he spent the next five years working on various machine learning projects. In May 2023, he joined the TransferLab team at appliedAI Institute.

Social card for talk: Data valuation for machine learning