Using machine learning to generate recipes that actually work | by Mikael Davidsson | Towards Data Science

The field of generative models has in recent years had some great success in regards to facial generation, or creating interesting landscapes from drawings.
However, making a recipe for a dish that humans actually would like to eat seems to be outside of our current capabilities. The results are often hilariously bad, and it makes for some great entertainment to actually try them out, see for example:
https://www.youtube.com/watch?v=LXSjtiahNtY
https://www.popularmechanics.com/technology/apps/a19304/computer-generated-recipes-are-gut-bustlingly-bad/
I set out to try some different ways of recipe generation, cook them to find out what makes them bad, and perhaps improve upon them.
For the dataset, I will be using recipes from sites: https://www.koket.se/ and https://www.tasteline.com/. The reason for this being that:
I have used them for years and know that the recipes are of high quality and usually result in tasty food.
The recipes are sort of “international”. Even though the sites are Swedish, most of the recipes reflect the modern Swedish audience's craving for foods from other cultures. So, although you will find traditional foods such as meatballs, you will also find tom kai gai, empanadas, scaloppine al limone di vitello, and over 100 recipes of hummus. Some of the more “exotic” recipes have been somewhat tampered with, for example, galangal is sometimes substituted for ginger, but not always.
TextGenRNN is a text generation python lib that uses a Recurrent Neural Network (RNN). RNN is one solution to the problem of working with sequential data. Since text data is of variable length (different amount of words, or letters), we cannot use a vanilla type neural network where, for example, each letter goes into one perceptron in the input layer, so instead, we are going to input the letters one by one as a sequence. We would like our NN to remember everything that has been fed into it, not just the latest element of the sequence. To achieve that, we are going to feed a hidden state back into the perceptron for every letter. The hidden state works as an internal memory of the RNN.
One of the problems with vanilla RNNs are that for each step the influence of a step further back gets smaller and smaller since it has been feed through the neurons so many times. So, an RNN might have problems keeping the context of a long sentence and can sometimes forget if it was talking about a person, a pizza, or the weather mid-sentence. One way to mitigate this is to use a specialized type of perceptron called an LSTM or a GRU, the results are better, but not stellar.
Anyway, this is what I got:
mix together with olive oil, sambal oelek, and put on a plate
dice the cucumber and cut into wedges
boil the pasta according to the instructions on the package
add onion, garlic, oil and embalm the salmon filets on both sides, and put them into the oven for about 10 min or until golden
wash and cut the tomatoes in half
Verdict: This was an OK meal. Making a simple sauce out of sambal oelek and olive oil was a nice idea. I had to iterate through a lot of recipes before I could find something that I could actually cook though. Most recipes were incoherent and impossible to follow.
Some of the most famous generative models are Generative Adversarial Networks (GANs). They work by letting two Neural Networks compete. The Generator is trying to generate data similar to the training set and the Discriminator is trying to figure out which one is fake and which one is from the training set. Through this competition, they both get better.
While most GANs are specialized in image generation, TableGAN is a python lib that uses the GAN technology to generate tabular data. Here is an example where the input data is random numbers with expected value 200, and standard deviation 100. TableGAN generated the following, which I think looks pretty good.
This seems to be a nice fit for a list of ingredients. I converted the recipes into vectors using the CountVectorizer from scikit-learn. The result is:
[‘aubergines’, ‘baby spinach’, ‘bacon’, ‘leaf spinach’, ‘bulgur’, ‘mushrooms’, ‘chili flakes’, ‘chili sauce’, ‘lemon juice’, ‘cognac’, ‘dragon’, ‘solid potatoes’, ‘fish sauce’, ‘liquid margarine’, ‘fresh thyme’, ‘fresh herbs’, ‘Greek yoghurt’, ‘green peppers’, ‘cucumbers’, ‘Japanese soy’, ‘Japanese rice’, ‘capers’, ‘coconut milk’ , ‘concentrated veal stock’, ‘minced meat’, ‘lime’, ‘limes’, ‘light beer’, ‘beef steak’, ‘corn starch’, ‘oil’, ‘cheese’, ‘oyster slices’, ‘pepper (to taste)’ , ‘pine nuts’,’ leeks’, ‘rosemary’, ‘raw lingonberries’,’ red onions’, ‘red wine’, ‘salt’, ‘shallots’,’ shallots’, ‘sesame seeds’,’ pork loins’, ‘butter ( to fry in) ‘,’ soy ‘,’ standard milk ‘,’ black pepper ‘,’ sweet chili sauce ‘,’ sweet potatoes ‘,’ dried thyme ‘,’ cod back ‘,’ walnuts ‘,’ yoghurt ‘,’ zucchini ‘,’ eggs ‘,’ apple cider vinegar ‘]
Verdict: There are simply too many ingredients in this one, so I won't try it.
Generative Pre-trained Transformer 2 (GPT-2) is a so-called transformer. They learn from the training data how likely a word is to occur depending on the other words in the full text, but different words are given different weights, a process called attention. In this way, it can keep the context theoretically indefinitely. The way to use GPT-2 is to write a few words as a starter and let the transformer fill in what word is most likely to follow, then look at the new string and repeat the process. GPT-2 is trained on large parts of the internet and has seen many recipes.
I have used https://app.inferkit.com/demo, which is a site where one can try out GPT-2 for free.
The starter sentence is in bold.
Chop the onion. Grind the cumin and mace. Sauté the onion. Remove the onion, cumin, mace, salt, and pepper from the skillet and grind the onion in a separate container. Turn the heat back up. Add the chickpeas, garlic, ginger, lemongrass, chicken broth, lime juice, soy sauce, and wine. Bring the liquid to a simmer, then reduce the heat and cover the pot. Cook for about 30 minutes, stirring occasionally. Once the liquid comes to a full boil, stir in the heavy cream. Reduce the heat again, cover, and
Verdict: This seems like a nice chickpea stew. I did end up not cooking it.
Mix tomatoes, cilantro, tomato paste, sour cream, lime juice, salt, black pepper, cumin, chili powder, and cayenne pepper in a large bowl. Let marinate 30 minutes. Heat a 12 — inch nonstick skillet over medium-high heat. Add the bacon, onion, and pepper flakes. Cook and stir 3 minutes or until bacon is crispy. Stir in the sour cream mixture. Add the ground beef and cook, breaking up the meat with a wooden spoon, 3 to 4 minutes, or until no longer pink. Combine the chopped lettuce, onion, and tomatoes; toss
Verdict: This tasted really good. Just perhaps a bit too generic Tex-Mex.
Legolas chopped the onions and mixed them with the breadcrumbs, some olive oil, and chicken broth. While they were stirring, Aragorn rolled out the dough for the lasagna and cut it into eight equal squares. “I don’t know if this is the best lasagna ever made,” he said, “but it’s at least better than it was yesterday.” “You haven’t eaten it yet.” Aragorn got up and started to put everything together. “You’ll just have to trust me on that.” “It’s good.” “Not as good as mine. But then, mine is my specialty.” They finished cooking and
Verdict: One of the fun things about GPT-2 is that you can feed it with whatever you like and it will finish it in a coherent way. I especially like that GPT knows that Aragorn has commented on how good the food is before he has tasted it, and writes about how Legolas calls him out for it.
I did not cook this hardy meal.
The above recipes were good enough, but I had to iterate through quite a few to get to them. However, I think the biggest problem is that they are very low in serendipity. Serendipity is a metric that is commonly used in recommender systems, where a high score means that the user was pleasantly surprised. So, for example, if I recommend food items, I can get high accuracy by recommending milk or bananas, because this is something that people often buy. But such a recommendation is not very good since the customer was going to buy that anyway. Rather, we would like to recommend the customer something that they will like, but would not likely have thought about themselves. That is high serendipity. It could arguably be seen as the most important metric for AI-generated recipes. We already have humans making recipes, what we would like from an AI is a shockingly different but still tasty recipe, free from human preconceived notions of what tastes good together.
One thing to notice is that when a human constructs a recipe, that human draws on experience on what different ingredients taste, smell, and look like. All this information is unavailable to the algorithm, which can only see how different ingredients are being used together. This is a common problem in machine learning, btw, where the model inherits the bias of the training data. This excludes some viable ingredient combinations that are uncommon because of geographical accidents. For example, it is unusual to see ginger and cream together, since ginger grows in a part of the world with a large percentage of the population is lactose intolerant. Nevertheless, I see no reason why they could not work together, since ginger and coconut milk is common.
I decided to add features to the ingredients and investigate. The features I use are:
Starch_1
Starch_2
Protein_1
Protein_2
Fat_1
Fat_2
Sweet_1
Sweet_2
Sour_1
Sour_2
Umami_1
Umami_2
Bitter
Soft
Medium
Crunchy
Red
Yellow
Green
Brown
White
Spice
The 1 means “some” and 2 means “mostly”. So for example, milk will have sweet_1, whereas honey will have sweet_2. Soft, Medium, Crunchy denotes the texture.
Now, this is somewhat subjective, and also prone to error since certain ingredients have different features depending on how they are prepared. This can be slightly alleviated by for example having “potatoes” and “mashed potatoes” as different ingredients.
Counting frequency reveals something interesting.
The counting is done as such: Whenever a recipe has at least 1 of a feature we increase that feature. We do this for all recipes and divide by the total amount of recipes. The “unnamed” marks whenever a recipe contains an ingredient that I do not have in my list of ingredients with features. This means that the numbers should likely be higher had I had the time and energy to notate more ingredients.
This seems to indicate that:
Most dishes have at least some of all the tastes, except for bitter.
A lot of recipes consist of many different textures and colors.
Almost all dishes have a spice of some kind.
I’m still not sure what conclusions can be drawn about bitter. Is it there because we enjoy it, or merely because a bitter ingredient has some other desirable quality, for example, roman salad, which is bitter but also very crunchy. My best guess is that sometimes it is there accidentally and other times it is consciously added to make the dish a bit more interesting, much in the same way that spices are used. It seems to be different in function from the other four tastes, sweet, salt, umami, and sour.
I find it interesting to contrast these with what I got for desserts:
More sweet and less umami, just as expected. I suspect that the prevalence of Umami_1 is mostly due to eggs and nuts of various sorts. I will focus on the non-dessert recipes in this article.
Looking at the most common ingredient in the non-dessert recipes:
Onion (yellow, red, shallot, etc): 0.90
Cheese: 0.55
Tomato: 0.45
Garlic: 0.31
Lemon: 0.30
I don’t know why this is the case. It could be that onions were cultivated very early on and in many places (Egypt 5,500 years ago, India and China 5,000 years ago, Sumeria 4,500 years ago). Also, onions are sulfur-rich, and some of the chemical compounds that are created when fried have sort of a meaty quality. The prevalence of cheese is probably due to the recipes being taken from a western cooking site.
Now that we have recipes described by their features rather than their ingredients, perhaps we can use this as training data? But, we would like to generate a recipe that is described by ingredients and not features. To achieve this we will:
Train a One Class SVM to recognize what is a valid recipe in terms of its features.
Generate a random combination of ingredients, calculate the features and let the SVM determine if it’s a valid recipe, if not repeat. This means that we will have to run through a couple of hundred random combinations before we get to something we can use. Even though this method of generating things is a bit indirect it is fast enough.
no_of_tries = 1000generated_recipe = ''for x in range(no_of_tries):    sample = df_ingredients.sample(12)    sample_sum = sample.sum()[feature_names]    pred = clf.predict([sample_sum.values])    if pred[0] == 1:        print(sample_sum[feature_names].values)        generated_recipe = sample.sort_values(['Starch_2', 'Protein_2'], ascending=False)        break        generated_recipe['Nudles', 'Chickpeas', 'Shrimps', 'Melon', 'Asparagus',       'Thai Basil', 'Cabbage', 'Sesame seeds', 'Orange','Tamarind',       'Butter', 'Cinnamon']
Another method might be to look at the frequencies of the features above and draw the conclusion that we would like to have one of each. So instead of our SVM, we hard code this rule, like this:
no_of_tries = 10000generated_recipe = ''for x in range(no_of_tries):    sample = df_ingredients.sample(16)    sample_sum = sample.sum()[feature_names]        if sample_sum['Starch_2'] == 1 and sample_sum['Protein_2'] == 1 and all([x > 0 for x in sample_sum]):        generated_recipe = sample.sort_values(['Starch_2', 'Protein_2'], ascending=False)        break['Polenta', 'Chicken', 'Pear', 'Star Anise', 'Lime juice', 'Radish', 'Mayonnaise', 'Tomato', 'Mushrooms', 'Artichoke', 'Vanilla', 'Eggs', 'Orange Zest', 'Oyster sauce', 'Sugar', 'Fennel']
Putting it together: Since we only have ingredients, I had to decide by myself what to do with them. This is what I came up with:
Dry-brine chicken in salt.
Make polenta with fennel and oyster sauce.
Grill chicken and polenta.
Pan roast mushrooms and tomatoes.
Make a salad with pear, radish, artichoke, and lime juice.
Make a sauce with oyster sauce, sugar, lime juice, water, orange zest, vanilla, star anise, fennel, and mayonnaise.
Verdict: It tasted good and, more importantly, a bit unusual (high serendipity). The sugar, vanilla, star anise, and fennel made the sauce taste a bit like licorice candy, but the oyster sauce made it savory and thus avoided it tasting like a dessert.
It occurred to me that this generator would lend itself to filling in missing ingredients if it were given a few to start with. Since there exist hundreds of recipes of hummus I decided to see if the algorithm could generate a new one. So I started with bread and chickpeas and the recipe became:
['Bread', 'Chickpeas', 'Stock', 'Dried tomatoes', 'Sunflower oil', 'Coca cola', 'Almonds', 'Dill', 'Pickles', 'Smoked paprika', 'Lemon juice', 'Beer']
I decided to use chopped almonds as garnish and eat the pickles as a side. Then I had to make a decision about which of the Coca-Cola and the beer should go into the hummus and which I should drink. I decided to pour a few tablespoons of Coca-Cola into the hummus.
Verdict: It tasted good and a bit different from the usual hummus recipes.
At this point, I decided that I did not have enough background knowledge to continue, so I ordered a couple of books:
I also found a nice lecture series on YouTube:
After reading and listening, I am ready to make some educated guesses as to what this all means.
The following are my own ideas. I have tried them out, but the sample size is too small to draw any general conclusions. Still, I will present them here, but take them with a grain of salt.
Balance. Something that only tastes salt is not tasty. The same for sweet, or any of the other tastes. What is needed to make a good meal, is a balance between sweet, salt, umami, and sour.
Variation. A meal needs to be varied and stimulate many different senses, thus it’s best if it contains different colors, textures, fragrances, temperatures.
Novelty. Eating the same thing over and over can be boring. We like to experience new combinations of sensations. I think this is one of the key features of many modernist restaurants, which serve foods with unusual combinations of taste, texture, color, etc.
Familiarity. As kids, we learn what is edible and what is not from our culture. This is vital for our survival so that each new generation does not have to figure out which berries are poisonous by trying them out. This also leads to that when cooking, we cannot stray too far from the boundaries set by the generations before us. At least not all in one go, by taking baby steps it is possible to learn to appreciate new types of food that are very different from what you are used to.
I find it interesting that the eating habits of humans seem to have a specific human element to them. One of the main challenges of making a good meal is of course to make something that the brain registers as nutritious food, as opposed to, say, a random plant like grass, or dirt. But, this is not enough. It also needs to stimulate and surprise us. It seems to work eerily similar to the way lots of other human leisure activities work. For example, one could argue that the list above could also be used as a guide on how to make music.
Texture: Speaking of humans, I have a guess why we are so obsessed with texture. In many cookbooks there are entire chapters, sometimes several, dedicated to getting the right texture of meat (I prefer sous vide or reverse sear for tender cuts, and pressure cooker for the though cuts to turn the collagen into gelatin. Rub in salt or brine a few hours beforehand). At the same time, most animals gladly eat all meat no matter how tough. My guess is that this has to do with us having a very high larynx (because of speech) combined with small jaw muscles (to make room for our big brain). This makes humans uniquely susceptible to die from choking, so tender meat is not just a matter of taste, but also of survival. Softer meat might also be an indicator that the meat has been cooked, and since this makes it easier for us to absorb the nutrients it makes sense for us to prefer meat this way.
Tastes: That we like sweet should come as no surprise to anyone, since sugar is high in energy and thus something that would be priced by our ancestors. Umami is a bit trickier since it’s not proteins in general, but just one particular amino acid. My guess is that glutamates are usually found in conjunction with other proteins and that we use it as a proxy for high protein food. Sour is trickier still. It could be that it indicates vitamin-C content, it could also be that it made our ancestors prefer unripe fruit, thus making them eat it before the competition. Salt is essential for correctly functioning physiology.
Chili: Now, this is a bit of an enigma, since consuming chili triggers pain receptors. It seems to be no consensus regarding this one, but one nice theory is that it is simulating a dangerous situation that we can control, and know is not dangerous, similar to a roller coaster.
It seems to me that spices are mostly for making the food more interesting and that there is no such thing as a spice that goes better with a certain ingredient. Pairing seems to be mostly cultural.
You should start by building your recipe so that it contains the right amounts of sweet, sour, salt, and umami. That way your brain will identify it as food. After that you can add any smell you find pleasant.
If you like the smell of a spice you can use it with anything.
Like the smell of cinnamon? It is not only for desserts, use it in a chicken stew, that’s what they do in India.
Like the smell of pine? Put some ground-up juniper berries in your ice cream.
Do you find the tickling sensation of Szechuanese cuisine interesting? Put some Szechuan pepper in your creamy mushroom stew.
Also, spices are mostly about smell (except for a few like chili, black pepper, Szechuan pepper), and there might be a close connection between the part of the brain that processes smell and the hypothesis that processes memories. This would mean that spices could be used to evoke certain memories. This is marvelously described in a famous scene in In Search of Lost Time by Proust, where the protagonist eats a Madeleine cake and drinks some lime flower tea and the smells trigger a vivid involuntary memory.
It might seem preposterous to reduce all the complexity in food to a few features like sweet, sour or crunchy. What happened to the idea that certain ingredients go better together than others, and how certain foodstuff complements and augments each other?
I think that an analogy to sound engineering is apt. So, in the early days of sound engineering, capturing the correct sound seemed like an insurmountable task. Acoustics is a vastly complicated field, move a pillar or make a wall smaller, or change the material and the way the sound waves propagate and interfere with each other will change entirely.
However, it was soon understood that the problem could be simplified by appreciating the fact that in all this complexity, humans still only have two ears.
In the same way, humans only have 5 types of taste buds on the tongue, and about 400 smell receptors. We do not add lemon to the sauce to “brighten it up” as is often said. We do it because most humans prefer a certain pH and the smell of citral and limonene. It also adds a bit of sweetness. We are free to substitute it for anything that fulfills the sour, sweet, and smell criterion. Balsamic vinegar might be a good candidate, given that you like the smell of tartaric, succinic, and malic acids and grape esters. Wine is also a good substitute.
And speaking of grapes, they go well with blue cheese because they contain sweet and sour but are low in salt and umami which is abundant in blue cheese. Beef jerky also contains these parts, and as expected tastes good with grapes, provided you like the smoky smell.
Another interesting analogue from the world of music is that of categorizing sounds. In the olden days, one would usually categorize by the way the instrument was played, looked like, or the material used. With the advent of synthesizers, we can now manufacture any sound without reference to real-world materials such as wood or brass. This has to lead a lot of VSTs to instead classify instruments by their function. So, we have pads for creating the background, leads for the melody, and bass for the, well, bass. In the same way, I tend to think about ingredients, not whether they are leaves, roots, or fruits, but whether they are crunchy, salty, red, or contains linalool.
The old way is also used in the classification of sauces into the French mother sauces: béchamel, espagnole, tomato, velouté, and hollandaise. They are classified according to ingredients and techniques used when cooking them, rather than how they taste and what their function is in the meal.
I used to be surprised by the taste of certain ingredients, such as fish sauce, Worcestershire sauce, oyster sauce, and the likes. When I tasted them on a spoon, I did not like them, so why would I use them in my food? Even things like parmigiano reggiano were a bit of a mystery, it tastes good on a sandwich, but a Comté tastes better, so why not use that instead?
Now I have understood that a lot of these more “funky” tasting ingredients are actually part of an ancient hunt for umami. Already the antique Romans had their garum, which supposedly smelled so bad that Seneca wrote of it:
Do you not realize that garum sociorum, that expensive bloody mass of decayed fish, consumes the stomach with its salted putrefaction?
But, umami is in short supply in nature, we crave it and are prepared to get it wherever we can. Nowadays I usually have a flask of fish sauce next to me whenever I cook, the fishy taste and smell is not really noticeable in the finished dish, and a lot of food gets better with some fish sauce. Not only Asian foods, mind you, putting some in the Ragu Bolognese will make it better.
Also, there are apparently two types of chemicals that trigger the umami receptors, glutamates and disodium inosinate and both together seem to yield a strong response, so it can be beneficial to use different types of umami_2 type ingredients in tandem.
One thing that surprised me when I started doing these kinds of experiments, is how the brain does not really see the different features as separate, but rather put together a unified picture based on a number of different sensations. So, for example, to some, it may sound distasteful to add sweetness to a savory dish, like adding sugar to a brown sauce. And, yes, if you add too much, you will taste the sweetness which might not be what you want. But, if the sauce is totally lacking in sweetness it will taste as if something is missing. Adding some sugar to the dish will not make it sweet, but rather, the brain will register it as “tasting good” (if you do not want to add sugar directly you can use carrots or even onions when making the sauce). The same goes for texture, where I sometimes do not really register the texture at all but rather just think of it as tasty.
The exact proportions are not given by the algorithm, so I usually do it by using my built-in chemical analyzers. That is, I taste it and add ingredients as necessary, usually something with a high concentration of the missing feature. So if sourness is missing, I reach for a lime, and if umami is missing, I use fish sauce, etc.
I guess it is possible to take a more scientific approach, I did try it with sourness by measuring the pH on a sauce I made.
The sauce seems to be about 6, compared to the other end with water which is 7.
Although there are many, many different types of dishes and cooking methods, it seems to me that some of them are extremely common all over the world.
Soup: Put all ingredients in water and heat until boiling. Let simmer until right texture and taste. Ex: Potato leek soup, Tom Kha Gai, Sopa Azteca, Bouillabaisse, Clam Chowder, Ramen soup, Pho, Hot and sour soup, Mulligatawny soup.
Stew: As a soup but remove the starchy ingredient and cook it by itself.Ex: Chili con carne, Dal, Massaman curry, Gumbo, Sega wat, Domoda, Mapo doufu.
By themselves: Prepare the starch, proteins, and vegetables by themselves and serve with a sauce.Ex: Meat and potatoes, Bangers and mash, Tapas, Peking duck, Steak Diane.
By themselves and mix: Prepare the starch, proteins, vegetables, and sauce by themselves and mix right before serving.Ex: Ragu Bolognese, Bo tai chanh, Pasta salad, Tabbouleh, Poke Bowl.
Sandwich: Prepare proteins and vegetables and serve on bread.Ex: Hamburger, Hot dog, Langos, Stuffed baguette, Döner Kebab, Burrito, Steak sandwich, Toast Skagen, Smørrebrød.
Pie: Bake proteins and vegetables on or inside a dough.Ex: Meat pie, Pierogi, Pizza, Dumplings, Börek, Kiymali pide, Empanadas, Bobotie.
Cooking is not only about finding the right ingredients and combining them, it’s also about chemistry. For example:
The Maillard reaction. There is a resilient myth from the 1800s that we sear meat to seal the juices in. This has been proven wrong, but there is still reason to sear. That reason is the Maillard reaction, a chemical reaction between amino acids and reducing sugars that produce a brown color, a crispy texture, and a nice fragrance.
Blanching. When we cut into vegetables we sever the cell walls and make different chemicals that were until then separated mix. This sometimes leads to an undesirable chemical reaction. For example, when cutting basil for pesto, a chemical reaction starts that makes the bright green color go brown. A way to stop this reaction from happening is to destroy the chemicals that cause it, by heating them up. This can be done by blanching the basil beforehand. Another example is onions which do not smell much until they are cut, and the subsequent mixing of chemicals produces some very potent sulfur-rich chemicals that become sulfuric acid when in contact with water and make our eyes burn. These reactions can be stopped by heating the onion in a frying pan.
Charring. Who would have thought that partially burning some plants would make them taste better? But it’s true, especially for the vegetables that are part of the immensely useful brassica oleracea species. It is one of those species that has been cultivated for a long time and has been selected to take many different useful forms. For example: Selection for terminal buds: CabbageSelection for lateral buds: Brussels sproutsSelection for stem: KohlrabiSelection for leaves: KaleSelection for stems and flowers: BroccoliSelection for flower clusters: CauliflowerBtw, the genus it belongs to also contains mustard and rapeseed.
I like this dish because it is very obvious how all the ingredients fit together. The dressing is:
Lime (Sour)
Palm sugar (Sweet)
Fish sauce (Umami, Salt)
Garlic, Chili, Ginger(Spice)
Sesame oil (Fat, Spice)
Now that all of the tastes are taken care of, the actual salad is mostly a matter of adding texture, color, and nutrition.
Rice Noodles (Starch, White, Soft)
Carrot (Starch, Orange, Crispy)
Cucumber (Starch, Green, Crispy)
Lettuce (Bitter, Green, Crispy)
Beef (Proteins, Medium texture)
Of course, some of these ingredients have some other features, for example, carrot is sweet and can function a bit like a spice (indeed, this was the reason the Persians domesticated it, to use the seeds and leaves as a spice), and meat has umami. But the dressing has more of it.
To make the dish even more interesting, add fresh herbs:
Mint
Cilantro
Thai basil
This is a dish that I have been cooking all my life, and I’ve never thought about improving it, until now. Armed with my new knowledge, I noticed that sour and sweet were missing, so one day I added a small amount of balsamic vinegar, and it did improve the dish. Now, I am sure that traditionally one would eat a sour side dish to balance it out, but I still think that my addition is an improvement.
There are many spices and it’s hard to know which one to use. To gain an overview I decided to group them. I Googled common substitutions and modeled it by drawing a graph where spice is connected to its substitutions. This was done in graph tool Gephi:
There seems to be a few clusters:
Christmas cluster (cloves, nutmeg, allspice, cinnamon, cardamom, powdered ginger, turmeric). To me, these are the tastes of gingerbread and Christmas. I guess Americans associate it with Thanksgiving and pumpkin pie. Also, the taste is common in Indian and Indonesian cuisine and Jamaican jerk. One characteristic chemical of this cluster is Eugenol.
Licorice cluster (anise, star anise, fennel, tarragon). To me, this is the taste of licorice, bread, salsiccia, and the Mediterranean. The characteristic taste of this cluster is due to Anethol or its isomer Estragole.
Spicy cluster (chili, black pepper, Szechuan pepper, paprika). These are different from other spices in that they are mostly about sensations (pungent, fiery, tickling) in the mouth rather than fragrance.
Fresh cluster (lemongrass, lemon zest, sumac). These are smells such as citral, linalool, and limonene, and are often associated with freshness, which is why they are common in soaps and detergents.
Fruity cluster (tamarind, lime). These are the flowery, fruity smells of various aldehydes.
Kick in the sinus cluster (horseradish, mustard, fenugreek). These are similar to the Spicy cluster, but the pain is in the nose instead of the mouth. Fenugreek does not have this quality.
Mediterranean herb cluster (oregano, basil, bay, thyme, sage): Smells like pizza and a Mediterranean meadow.
Musky cluster (cumin, coriander, caraway, dill): Smells like middle eastern cuisine.
Pine tree cluster (juniper berries, rosemary): This is the smell of conifer forest, mostly due to α-pinene.
Toothpaste cluster (mint, parsley, cilantro). To me, this is the fresh taste of toothpaste and mouthwash.
Nocluster (liquid smoke, vanilla, chocolate, saffron): These are spices that don’t really fit into any of the other categories.
Btw, the nice smell that makes herbs and spices so desirable to us is in many cases chemical warfare. See, herbs can’t run away from their enemies (such as fungus and insects), so instead, they produce toxic chemicals that kill off any invaders. These chemicals are what make spices smell the way they do. Apparently, herbs that have been attacked by pests during their lifetime taste more than those sprayed with pesticides. As to why humans like these chemicals, there are a few theories. One is that toxic chemicals help our immune system.
This is not the whole story though, tamarind and other fruits smell nice because they want to be eaten so that the seeds within them will be spread, and chilies are spicy to discourage mammals from eating them so that their seeds are instead spread by birds which cannot taste the heat.
Another thing to note about spices is that it is a good idea to store them whole and ground them just before use. The reason for this is the square-cube law. By decreasing the size of spice particles the volume decrease as size3, whereas area just decreases as size2, so that small particles have a much larger area-to-volume ratio and the smell molecules will dissipate faster. Much in the same way, small animals usually have a hard time keeping warm, whereas large animals struggle to not overheat.