Balance data using different criteria I have a dataset of audio and text files that I want to balance using different criteria to train a neural network. The text and matching audio file are grouped under one ID. 

For each ID, I have a number of words and some metadata.

Let's say my data have three metadata/criteria that need to be balanced (well... kind of, I want to be able to choose the percentage for some criteria values) :


The name of the speaker, each speaker should have approximately the same number of words.
The status of the speaker (active if the speaker is still in activity or inactive if not), where I want approximately 70 % active speakers and 30 % inactive. 
The gender of the speaker, where I want approximately 50 % male and 50 % female.


Example : ID12345 with 10,000 words. Metadata : John, male and active 

If I balance one of the criteria, then another, I will surely unbalance the previously balanced one.
Moreover, if I balance using only one criterion at a time, I could throw away data that could be useful to the balance of the following criteria, which mean I will end up with less data that I could have had optimally.

Is there an algorithm that could balance the data using all criteria with their percentage target, and maximise the number of words remaining ?

I'm looking for a general algorithm, with a variable number of criteria.

EDIT : I use C++ and MongoDB (but I'll accept other languages/tools if it can help me, as well as algorithms).
You would need to balance the data according to the joint distribution of all 3 features.

One simple option is to treat each feature as categorical (binning any continuous features), then map each combination of features to a single new feature:

doc_len_tokens  | status   | gender | level
----------------|----------|--------|------
1               | active   | male   | 1
1               | active   | female | 2
1               | inactive | male   | 3
1               | inactive | female | 4
2               | active   | male   | 5
2               | active   | female | 6
2               | inactive | male   | 7
2               | inactive | female | 8
... etc ...


You would then stratify on level when sampling.

Here is an example in SQL:

SELECT
    data.unique_id,
    data.doc_num_tokens,
    data.status,
    data.gender
FROM (
    SELECT
        data.unique_id,
        data.doc_num_tokens,
        data.status,
        data.gender,
        row_number() OVER (
            PARTITION BY
                data.doc_num_tokens,
                data.status,
                data.gender
            ORDER BY
                newid()
        ) AS row_num
    FROM
        my_data AS data
) AS data
WHERE
    row_num &lt;= ${number of rows to sample}