aspuru-guzik-group / GA

Code for the paper: Augmenting genetic algorithms with deep neural networks for exploring the chemical space
98 stars 36 forks source link

What does beta do? #4

Closed mapengsen closed 11 months ago

mapengsen commented 1 year ago
    ## Impose the beta cuttoff! --------------------------
    if impose_time_adapted_pen: 
        if generation_index > 100:
            # Check if there is a stagnation for 5 generations! (检查了 max_fitness_collector 列表的最后五个元素是否都是相同的)
            if len(set(max_fitness_collector[-5:])) == 1:
                beta = 1000
                print('Beta cutoff imposed  index: ', generation_index)
                f = open('{}/beta_change_log.txt'.format(data_dir), 'a+')
                f.write(str(generation_index) + '\n')
                f.close()
    ## beta cuttoff imposed! --------------------------

fitness = (beta * discriminator_predictions) + fitness

when the len(set(max_fitness_collector[-5:])) == 1:, then the fitness is very big, and get the order, But the change doesn't seem to be working? It simply increases the overall fitness of the population in this generation

akshat998 commented 1 year ago

Hi @mapengsen,

When the fitness is stagnant for a while, i,e. len(set(max_fitness_collector[-5:])) == 1, then the incorporation of beta in the fitness value naturally assign bad scores to the long standing molecules, thereby killing them & allowing new molecules to take their place.

Does this answer your question? This is discussed within the manuscript :)

Regards

mapengsen commented 1 year ago

@akshat998 First of all, thank you for your earlier answers In your code :

data_x = (1000,51)
dataset_y = (1000,)
predictions = Net(data_x) 
loss = loss_func(predictions, data_y)

This loss is the loss between calculating the predictions of data_x's input discriminator D and predictions of whether the molecule belongs to the retrieval data set (belonging to 1, not 0). I can understand what this loss means: If the loss is smaller then that means that the mutated molecule is more like the molecule in the database, and the greater the loss then that means that the mutated molecule is less like the molecule in the database.

        fitness_here, order, fitness_ordered, smiles_ordered, selfies_ordered = gen_func.obtain_fitness(disc_enc_type,      smiles_here,   selfies_here, 
                                                                                                        properties_calc_ls, discriminator, generation_index,
                                                                                                        max_molecules_len,  device,        generation_size,  
                                                                                                        num_processors,     writer,        beta,            
                                                                                                        image_dir,          data_dir,      max_fitness_collector, impose_time_adapted_pen)

Only the above code uses the discriminator D, and the discriminator's role here is to give the fitness of the mutated molecule, and it has no other role, and it does not know the discriminator backpropagation, if len(set(max_fitness_collector[-5:]) == 1, Then it means that after the mutation, the molecules become the same, the beta becomes 1000, and the fitness of all the mutated molecules in this generation will become large,

discriminator_predictions = D.do_predictions(discriminator, dataset_x, device)
fitness = (beta * discriminator_predictions) + fitness

It doesn't do any unnecessary operations on any molecule. I don't understand what you mean by "assign bad scores" above. Who gives points for business trips and who "kills them & allowing new molecules to take their place"?

to_replace, to_keep = gen_func.apply_generation_cutoff(order, generation_size)

Looking forward to your reply!

akshat998 commented 11 months ago

Hi @mapengsen,

Thank you for your follow-up question and the detailed explanation of your understanding of the code. Let me clarify the role of the beta cutoff and its impact on the fitness calculation.

In the context of the algorithm, the beta value acts as a penalty factor. When the algorithm detects stagnation in the fitness of the top molecules over several generations (as indicated by len(set(max_fitness_collector[-5:])) == 1), it significantly increases the beta value. This adjustment is intended to penalize molecules that have been persistently appearing at the top of the fitness ranking without significant improvement.

The line fitness = (beta * discriminator_predictions) + fitness incorporates this penalty into the fitness calculation. Here’s how it works:

  1. Role of Discriminator: The discriminator's role is to evaluate how similar a molecule is to those in the database. A lower loss indicates greater similarity.

  2. Impact of Increased Beta: By multiplying the discriminator predictions with a high beta value (1000 in this case), molecules that have been consistently at the top (but are not improving) receive a much higher fitness score.

  3. Effect on Selection: In many evolutionary algorithms, lower fitness scores are preferred for selection into the next generation. Thus, by artificially inflating the fitness scores of stagnant molecules, the algorithm effectively "penalizes" them. They become less likely to be chosen for the next generation, making room for new molecules.

  4. "Killing" and Replacing Molecules: The term "killing them & allowing new molecules to take their place" refers to this process. Molecules with inflated fitness scores due to the high beta penalty are less likely to be selected ("killed" in a metaphorical sense), while others with lower fitness scores (new or improved molecules) have a higher chance of being selected ("taking their place").

In summary, the beta cutoff is a mechanism to prevent the algorithm from getting stuck in a loop of selecting the same molecules over and over. By penalizing stagnant molecules, it encourages the exploration of new and potentially better molecular structures.

I hope this clarifies your query. Please feel free to reach out if you have any more questions or need further explanation.

P.S. If you would like to work on a more modern version of the algorithm, check out JANUS: https://github.com/aspuru-guzik-group/JANUS :)

Best regards,