How to split dataset into subset with non-uniform distribution of labels

I’m experimenting with federated learning and i need non-iid data but using torch.utils.data.random_split() splits my mnist dataset into subsets with uniformed label distribution

Server Label Distribution
0 : 2930 | 1 : 3371 | 2 : 3004 | 3 : 3079 | 4 : 2866 | 5 : 2695 | 6 : 2962 | 7 : 3150 | 8 : 2966 | 9 : 2977 |
Clients Label Distribution
0 : 263 | 1 : 290 | 2 : 269 | 3 : 268 | 4 : 277 | 5 : 247 | 6 : 271 | 7 : 276 | 8 : 272 | 9 : 267 |
0 : 218 | 1 : 263 | 2 : 192 | 3 : 214 | 4 : 208 | 5 : 181 | 6 : 216 | 7 : 198 | 8 : 222 | 9 : 188 |
0 : 76 | 1 : 70 | 2 : 63 | 3 : 65 | 4 : 68 | 5 : 34 | 6 : 44 | 7 : 57 | 8 : 68 | 9 : 55 |
0 : 448 | 1 : 490 | 2 : 430 | 3 : 469 | 4 : 443 | 5 : 414 | 6 : 448 | 7 : 470 | 8 : 437 | 9 : 451 |
0 : 746 | 1 : 829 | 2 : 784 | 3 : 768 | 4 : 737 | 5 : 693 | 6 : 758 | 7 : 778 | 8 : 666 | 9 : 741 |
0 : 95 | 1 : 100 | 2 : 83 | 3 : 94 | 4 : 95 | 5 : 80 | 6 : 85 | 7 : 94 | 8 : 80 | 9 : 94 |
0 : 77 | 1 : 97 | 2 : 110 | 3 : 93 | 4 : 74 | 5 : 97 | 6 : 85 | 7 : 91 | 8 : 86 | 9 : 90 |
0 : 244 | 1 : 302 | 2 : 269 | 3 : 266 | 4 : 268 | 5 : 248 | 6 : 264 | 7 : 292 | 8 : 284 | 9 : 263 |
0 : 770 | 1 : 859 | 2 : 703 | 3 : 738 | 4 : 739 | 5 : 678 | 6 : 728 | 7 : 803 | 8 : 712 | 9 : 770 |
0 : 56 | 1 : 71 | 2 : 51 | 3 : 77 | 4 : 67 | 5 : 54 | 6 : 57 | 7 : 56 | 8 : 58 | 9 : 53 |

any idea how to make the data skewed?

You could use e.g. sklearn.model_selection.train_test_split and use the stratify argument to create the imbalanced split. Once you have the indices you could then use these to create torch.utils.data.Subsets.

do you know how to do that with the torchvision datasets?

You would need to access or load the internal targets from the desired dataset and pass it to train_test_split and stratify. If your dataset is preloading the data, check its internal attribute for e.g. .targets, else iterate the dataset once to load the targets and use them afterwards.