TastyPiano / src /cocktails /pipeline /cocktailrep2recipe.py
Cédric Colas
initial commit
e775f6d
raw
history blame
17 kB
import matplotlib.pyplot as plt
import pickle
from src.cocktails.utilities.cocktail_generation_utilities.population import *
from src.cocktails.utilities.glass_and_volume_utilities import glass_volume
from src.cocktails.config import RECIPE2FEATURES_PATH
def test_mutation_params(cocktail_reps):
indexes = np.arange(cocktail_reps.shape[0])
np.random.shuffle(indexes)
perfs = []
mutated_perfs = []
pop_params = dict(mutation_params=dict(p_add_ing=0.7,
p_remove_ing=0.7,
p_switch_ing=0.5,
p_change_q=0.7,
delta_change_q=0.3,
asexual_rep=True,
crossover=True,
ingredient_addition=(0.1, 0.05)),
nb_generations=100,
pop_size=100,
nb_elites=10,
dist='mse',
n_neighbors=5)
for i in indexes[:20]:
target = cocktail_reps[i]
for j in range(100):
parent = IndividualCocktail(pop_params=pop_params,
target_affective_cluster=None,
target=target.copy())
perfs.append(parent.perf)
child = parent.get_child()[0]
# child.compute_cocktail_rep()
# child.compute_perf()
if perfs[-1] != child.perf:
mutated_perfs.append(child.perf)
else:
perfs.pop(-1)
filtered_children = np.argwhere(np.array(mutated_perfs)==-100).flatten()
non_filtered_ids = np.argwhere(np.logical_and(np.array(perfs)!=-100, np.array(mutated_perfs)!=-100)).flatten()
print(f'Proportion of filtered: {filtered_children.size} / {len(mutated_perfs)} = {int(filtered_children.size / len(mutated_perfs)*100)}%')
plt.figure()
plt.scatter(np.array(perfs)[non_filtered_ids], np.array(mutated_perfs)[non_filtered_ids], s=100, alpha=0.5)
plt.xlabel('parent perf')
plt.ylabel('child perf')
print(np.corrcoef(np.array(perfs)[non_filtered_ids], np.array(mutated_perfs)[non_filtered_ids])[0, 1])
plt.show()
stop = 1
def test_crossover(cocktail_reps):
indexes = np.arange(cocktail_reps.shape[0])
np.random.shuffle(indexes)
perfs = []
mutated_perfs = []
pop_params = dict(mutation_params=dict(p_add_ing=0.7,
p_remove_ing=0.7,
p_switch_ing=0.5,
p_change_q=0.7,
delta_change_q=0.3,
asexual_rep=True,
crossover=True,
ingredient_addition=(0.1, 0.05)),
nb_generations=100,
pop_size=100,
nb_elites=10,
dist='mse',
n_neighbors=5)
for i in indexes[:20]:
for j in range(100):
target = cocktail_reps[i]
parent1 = IndividualCocktail(pop_params=pop_params,
target_affective_cluster=None,
target=target.copy())
parent2 = IndividualCocktail(pop_params=pop_params,
target_affective_cluster=None,
target=target.copy())
child = parent1.get_child_with(parent2)[0]
# child.compute_cocktail_rep()
# child.compute_perf()
perfs.append((parent1.perf + parent2.perf)/2)
if perfs[-1] != child.perf:
mutated_perfs.append(child.perf)
else:
perfs.pop(-1)
filtered_children = np.argwhere(np.array(mutated_perfs)==-100).flatten()
non_filtered_ids = np.argwhere(np.logical_and(np.array(perfs)>-45, np.array(mutated_perfs)!=-100)).flatten()
print(f'Proportion of filtered: {filtered_children.size} / {len(mutated_perfs)} = {int(filtered_children.size / len(mutated_perfs)*100)}%')
plt.figure()
plt.scatter(np.array(perfs)[non_filtered_ids], np.array(mutated_perfs)[non_filtered_ids], s=100, alpha=0.5)
plt.xlabel('parent perf')
plt.ylabel('child perf')
print(np.corrcoef(np.array(perfs)[non_filtered_ids], np.array(mutated_perfs)[non_filtered_ids])[0, 1])
plt.show()
stop = 1
def run_comparisons():
np.random.seed(0)
indexes = np.arange(cocktail_reps.shape[0])
np.random.shuffle(indexes)
for n_neighbors in [0, 5]:
id_str_neigh = '5neigh_' if n_neighbors == 5 else '0_neigh_'
for asexual_rep in [True, False]:
id_str_as = id_str_neigh + 'asexual_' if asexual_rep else id_str_neigh
for crossover in [True, False]:
id_str = id_str_as + 'crossover_' if crossover else id_str_as
if crossover or asexual_rep:
mutation_params = dict(p_add_ing = 0.5,
p_remove_ing = 0.5,
p_change_q = 0.5,
delta_change_q = 0.3,
asexual_rep=asexual_rep,
crossover=crossover,
ingredient_addition = (0.1, 0.05))
nb_generations = 100
pop_size=100
nb_elites=10
dist = 'mse'
results = dict()
print(id_str)
for i, ind in enumerate(indexes[:30]):
print(i+1)
target_ing_str = data['ingredients_str'][ind]
target = cocktail_reps[ind]
population = Population(nb_generations=nb_generations, pop_size=pop_size, nb_elite=nb_elites,
target=target, dist=dist, mutation_params=mutation_params,
n_neighbors=n_neighbors, target_ing_str=target_ing_str, true_prep_type=data['category'][ind])
population.run_evolution(verbose=False)
best_scores, best_ind = population.get_best_score()
recipes = [ind.get_recipe()[3] for ind in best_ind[:5]]
results[str(ind)] = dict(best_scores=best_scores[:5], recipes=recipes, target=population.target_individual.get_recipe()[3])
with open(f'/home/cedric/Desktop/ga_tests_{id_str}.pickle', 'wb') as f:
pickle.dump(results, f)
def get_cocktail_distribution(cocktail_reps):
return (np.mean(cocktail_reps, axis=0), np.cov(cocktail_reps, rowvar=0))
def sample_cocktails(cocktail_reps, n=10, target_affective_cluster=None, to_print=True):
distrib = get_cocktail_distribution(cocktail_reps)
sampled_cocktail_reps = np.random.multivariate_normal(distrib[0], distrib[1], size=n)
recipes = []
closest_recipes = []
for i_c, cr in enumerate(sampled_cocktail_reps):
population = setup_recipe_generation(cr.copy(), target_affective_cluster=target_affective_cluster)
closest_recipes.append(population.nn_recipes[0])
best_scores, best_individuals = population.run_evolution()
recipes.append(best_individuals[0].get_recipe()[3])
if to_print:
print(f'Sample #{len(recipes)}:')
print(recipes[-1])
print('Closest from dataset:')
print(closest_recipes[-1])
stop = 1
return recipes, closest_recipes
def setup_recipe_generation(target, known_target_dict=None, target_affective_cluster=None):
# pop_params = dict(mutation_params=dict(p_add_ing=0.7,
# p_remove_ing=0.7,
# p_switch_ing=0.5,
# p_change_q=0.7,
# delta_change_q=0.3,
# asexual_rep=True,
# crossover=True,
# ingredient_addition=(0.1, 0.05)),
# nb_generations=2, #100
# pop_size=5, #100
# nb_elites=2, #10
# dist='mse',
# n_neighbors=3) #5
pop_params = dict(mutation_params=dict(p_add_ing=0.4,
p_remove_ing=1,
p_switch_ing=0.5,
p_change_q=1,
delta_change_q=0.3,
asexual_rep=True,
crossover=True,
ingredient_addition=(0.1, 0.05)),
nb_generations=100, # 100
pop_size=100, # 100
nb_elites=10, # 10
dist='mse',
n_neighbors=5) # 5
population = Population(target=target, target_affective_cluster=target_affective_cluster, known_target_dict=known_target_dict, pop_params=pop_params)
return population
def cocktailrep2recipe(cocktail_rep, unit='mL', target_affective_cluster=None, known_target_dict=None, n_output=1, return_ind=False, verbose=True, full_verbose=False, level=0):
init_time = time.time()
if verbose: print(' ' * level + 'Generating cocktail..')
if cocktail_rep.ndim > 1:
assert cocktail_rep.shape[0] == 1
cocktail_rep = cocktail_rep.flatten()
# target_affective_cluster = target_affective_cluster[0]
population = setup_recipe_generation(cocktail_rep.copy(), known_target_dict=known_target_dict, target_affective_cluster=target_affective_cluster)
if full_verbose:
print(' ' * (level + 2) + '3 nearest neighbors:')
for i, recipe, score in zip(range(3), population.nn_recipes[:3], population.nn_scores[:3]):
print(' ' * (level + 4) + f'#{i+1}, score: {score:.2f}')
print(' ' * (level + 4) + recipe[1:].replace('None ()', '').replace('\t\t', ' ' * (level + 6)))
best_scores, best_individuals = population.run_evolution(verbose=full_verbose, level=level+2)
for i in range(n_output):
best_individuals[i].make_recipe_fit_the_glass()
instructions = [ind.get_instructions() for ind in best_individuals[:n_output]]
recipes = [ind.get_recipe(unit=unit)[3] for ind in best_individuals[:n_output]]
glasses = [ind.glass for ind in best_individuals[:n_output]]
prep_types = [ind.prep_type for ind in best_individuals[:n_output]]
for i, g, p, inst in zip(range(len(recipes)), glasses, prep_types, instructions):
recipes[i] = recipes[i].replace('Recipe', 'Ingredients') + f'Serve in:\n {g.capitalize()} glass.\n' + inst
if full_verbose:
print(f'\n--------------\n{n_output} best results:')
for i, recipe, score in zip(range(n_output), recipes, best_scores[:n_output]):
print(f'#{i+1}, score: {score:.2f}')
print(recipe)
if verbose: print(' ' * (level + 2) + f'Generated in {int(time.time() - init_time)} seconds.')
if return_ind:
return recipes, best_scores[:n_output], best_individuals[:n_output]
else:
return recipes, best_scores[:n_output]
def interpolate(cocktail_rep1, cocktail_rep2, alpha, verbose=False):
recipe, score = cocktailrep2recipe(alpha * cocktail_rep1 + (1 - alpha) * cocktail_rep2, verbose=verbose)
return recipe[0], score
def interpolation_study(n_steps, cocktail_reps):
alphas = np.arange(0, 1 + 1e-6, 1/(n_steps + 1))
indexes = np.random.choice(np.arange(cocktail_reps.shape[0]), size=2, replace=False)
target_ing_str1, target_ing_str2 = data['ingredients_str'][indexes[0]], data['ingredients_str'][indexes[1]]
cocktail_rep1, cocktail_rep2 = cocktail_reps[indexes[0]], cocktail_reps[indexes[1]]
recipes, scores = [], []
for alpha in alphas:
recipe, score = interpolate(cocktail_rep1, cocktail_rep2, alpha)
recipes.append(recipe)
scores.append(score[0])
print('Point A:')
print_recipe(ingredient_str=target_ing_str2)
for i, alpha in enumerate(alphas):
print(f'Alpha = {alpha}, score = {scores[i]}')
print(recipes[i])
print('Point B:')
print_recipe(ingredient_str=target_ing_str1)
stop = 1
def test_robustness_affective_cluster(cocktail_reps):
indexes = np.arange(cocktail_reps.shape[0])
np.random.shuffle(indexes)
matches = []
for i in indexes:
target_ing_str = data['ingredients_str'][i]
true_prep_type = data['category'][i]
target = cocktail_reps[i]
# get affective cluster
recipes, best_scores, best_inds = cocktailrep2recipe(cocktail_rep=target, target_ing_str=target_ing_str, true_prep_type=true_prep_type, n_output=1, verbose=False,
return_ind=True)
matches.append(best_inds[0].does_affective_cluster_match())
print(np.mean(matches))
def test(cocktail_reps):
indexes = np.arange(these_cocktail_reps.shape[0])
unnormalized_cr = np.array([data[k] for k in rep_keys]).transpose()
for i in indexes:
target_ing_str = data['ingredients_str'][i]
true_prep_type = data['category'][i]
target = these_cocktail_reps[i]
# print('preptype:', true_prep_type)
# print('cocktail unnormalized', np.sum(unnormalized_cr[i]), unnormalized_cr[i])
# print('cocktail hand normalized', np.sum(normalize_cocktail(unnormalized_cr[i])), normalize_cocktail(unnormalized_cr[i]))
# print('cocktail rep normalized', np.sum(these_cocktail_reps[i]), these_cocktail_reps[i])
# print('cocktail rep normalized', np.sum(all_reps[i]), all_reps[i])
population = setup_recipe_generation(target.copy(), target_ing_str=target_ing_str, target_affective_cluster=None, true_prep_type=true_prep_type)
target = population.target_individual
target.compute_perf()
if target.perf < -50:
print(i)
print_recipe(target_ing_str)
if not target.is_alcohol_present(): print('No alcohol')
if not target.is_total_volume_enough(): print('small volume')
if not target.does_fit_glass():
print(target.end_volume)
print(glass_volume[target.get_glass_type()] * 0.81)
print('too much volume')
if not target.is_alcohol_reasonable():
print(f'amount of alcohol too small or too large: {target.alcohol_precentage}')
stop = 1
if __name__ == '__main__':
these_cocktail_reps = COCKTAIL_REPS.copy()
# test_crossover(these_cocktail_reps)
# test_mutation_params(these_cocktail_reps)
# test(these_cocktail_reps)
# recipes, closest_recipes = sample_cocktails(these_cocktail_reps, n=10)
# interpolation_study(n_steps=4, cocktail_reps=these_cocktail_reps)
# test_robustness_affective_cluster(these_cocktail_reps)
indexes = np.arange(these_cocktail_reps.shape[0])
np.random.shuffle(indexes)
# test_crossover(mutation_params, dist)
# test_mutation_params(mutation_params, dist)
stop = 1
unnormalized_cr = np.array([data[k] for k in rep_keys]).transpose()
for i in indexes:
print(i)
target_ing_str = data['ingredients_str'][i]
target_prep_type = data['category'][i]
target_glass = data['glass'][i]
print('preptype:', target_prep_type)
print('cocktail unnormalized', np.sum(unnormalized_cr[i]), unnormalized_cr[i])
print('cocktail hand normalized', np.sum(normalize_cocktail(unnormalized_cr[i])), normalize_cocktail(unnormalized_cr[i]))
print('cocktail rep normalized', np.sum(these_cocktail_reps[i]), these_cocktail_reps[i])
print('cocktail rep normalized', np.sum(all_reps[i]), all_reps[i])
print(i)
print('___________Target')
nn_model = NearestNeighbors()
nn_model.fit(these_cocktail_reps)
dists, indexes = nn_model.kneighbors(these_cocktail_reps[i].reshape(1, -1))
print(indexes)
print_recipe(target_ing_str)
target = these_cocktail_reps[i]
known_target_dict = dict(prep_type=target_prep_type,
ing_str=target_ing_str,
glass=target_glass)
recipes, best_scores = cocktailrep2recipe(cocktail_rep=target, known_target_dict=known_target_dict, n_output=1, verbose=True, full_verbose=True)
stop = 1