# Can I use Mathematica to generate candle scents?

I found this blog (which is highly entertaining). It has an interesting post where the author uses the GPT-2 neuro-network with candle scent training data to generate new candle scents. The AI comes up with some delightful names such as

• Frozen Styrofoam
• Asparagus & Pumpkin
• Marshmallow Chutney
• Friendly Wetsuit

along with much more "normal" candle scents such as

• Mango Vanilla
• Summer Sky
• Christmas Almond
• Wildflower Honey
• Vanilla Pumpkin Cake

I was wondering if it would be possible to do something similar in Mathematica. There exists this example, but based in python.

I've scraped a few websites for a list of 1.5k candle names: https://pastebin.com/T9VW709E. I note that GPT-2 is accessible from Mathematica relatively easily. Can I get Mathematica to predict new candle scents from my (relatively limited) training data?

You might be wanting something more skilled using GTP-2 and etc. However I found with fairly little work I could get some fun results.

First I simply took your list and used the GPT-2 net to create the 768 vector values for each candle name...

candlenames = data from link
model = NetModel["GPT-2 Transformer Trained on WebText Data"]
coor = Table[model[candlenames[[i]]], {i, 1, Length[candlenames]}];


I then took the coor data and took the median of each vector value and gave each name a point value.

preditiondata = Table[candlenames[[i]] -> First[Mean[coor[[i]]]], {i, 1, Length[candlenames]}];
p = Predict[preditiondata, Method -> "NeuralNetwork"]


After this I naively generated a list of 50, 000 adjective and noun combinations

names = {RandomWord["Adjective", 50000] RandomWord["Noun", 50000]};


Which is hilarious enough as it is....

RandomChoice[list, 10]


$$\{\text{lush} \text{ tractor},\text{erasable} \text{ toiler},\text{ frosted} \text{haulage},\text{contraceptive} \text{ temporal},\text{dowse} \text{ sociable},\text{adjunct} \text{ largo},\text{garbed} \text{ investiture},\text{deprecating} \text{ info},\text{advance} \text{ overhang},\text{oration} \text{ undiscovered}\}$$

Lush Tractor and Contraceptive Temporal probably being my favourite candle scents....

Anyways, I then used the predictor to give what i hoped to be good names based off of high values from the list of candle names given...which depending on the person was a wild success or huge statistical failure.

results = Table[{list[[i]], p[ToString[list[[i]]]]}, {i, 1, Length[list]}];
names = Position[results, n_ /; n > 1.8]
Sort[Table[results[[First[names[[i]]]]], {i, 1, Length[names]}], #1[[2]] > #2[[2]] &] // MatrixForm


I picked as an arbitrary value above 2 as it seemed to give me results that seemed plausible.

$$\left( \begin{array}{cc} \text{breeze} \text{ exclamatory} & 2.9989 \\ \text{breeze} \text{ smoldering} & 2.9989 \\ \text{avenged} \text{ breeze} & 2.63791 \\ \text{avocado} \text{ weathered} & 2.3345 \\ \text{enchanted} \text{ oxbow} & 2.2121 \\ \text{enchanted} \text{ propagator} & 2.2121 \\ \text{enchanted} \text{ proceeds} & 2.2121 \\ \text{enchanted} \text{ endocrine} & 2.2121 \\ \text{enchanted} \text{ submergence} & 2.2121 \\ \text{enchanted} \text{ torturer} & 2.2121 \\ \text{harvest} \text{ inconsiderable} & 2.20732 \\ \text{harvest} \text{ simplified} & 2.20732 \\ \text{autumn} \text{ unparalleled} & 2.18493 \\ \text{fruit} \text{ venomous} & 2.15026 \\ \end{array} \right)$$

In this random list it appears "autumn","enchanted" and "breeze" are popular candle scent titles...I expect because they show up often in the list. By using RandomWord[] more clever and using Predict in combination with the GPT-2 vector values, one could probably get a much better results...However names are quite subjective and I enjoyed the results I got. Maybe this will inspire someone more clever than I.

** Update **

To attempt to get some better names, took all the string names and split them into individual words gave them a weighting through word frequency and ran them through the predictor again with the full names

words = Table[StringSplit[candlenames[[i]]], {i, 1, Length[candlenames]}] // Flatten;


swords = DeleteDuplicates[words];
totalwords = StringJoin[Riffle[words, " "]];
weightedvalues = Table[swords[[i]] -> 1000 WordFrequency[totalwords, ToString[swords[[i]]]], {i, 1, Length[swords]}]

data = Join[Table[weightedvalues[[i]], {i, 1, Length[weightedvalues]}], Table[candlenames[[i]] -> First[Mean[coor[[i]]]], {i, 1, Length[candlenames]}]];

p = Predict[data, Method -> "NeuralNetwork"]


Now generate the words:

SeedRandom[113]
list = RandomWord["Adjective", limit] RandomWord["Noun", limit];
listnn = RandomWord["Noun", limit, IncludeInflections -> True] RandomWord[limit, IncludeInflections -> True];
l1 = RandomWord["Noun", limit];
l2 = RandomChoice[{2, 0.01} -> {" ", " & "}, limit];
l3 = RandomWord["Noun", limit];

stringlist1 = Table[ToString[list[[i]]], {i, 1, Length[list]}];
stringlist2 = Table[ToString[listnn[[i]]], {i, 1, Length[listnn]}];
namelist = Join[Table[StringJoin[l1[[i]], l2[[i]], l3[[i]]], {i, 1, Length[l1]}], stringlist1, stringlist2];


Pass the data through the predictor,

results = Table[{namelist[[i]], p[namelist[[i]]]}, {i, 1, Length[namelist]}];

names = Position[results, n_ /; n > 0.757];
Sort[Table[results[[First[names[[i]]]]], {i, 1, Length[names]}], #1[[2]] > #2[[2]] &] // MatrixForm


This has given me many different results, but the new weighting makes a heavy difference it seems. I have gotten some interesting results. The weighting would have to be adjusted some more

Some of my favourites:

Niobium spice, Absurd Grapefruit, Fruit Obtrusive, Telemarketing Lumberjack, Fated Mango, Valley & Rhapsody, Claptrap Brew

However, it's taken 60, 000 random generated results to get these and most seem to be better for IPA beers.

Regardless a bit of fun.

• coor = Table[model[candlenames[[i]]], {i, 1, Length[candlenames]}]; -- How about using Map? – Anton Antonov Mar 2 at 15:43
• @AntonAntonov oh yeah, map is a good function i never use for some reason...i’m sure my code is mostly poorly written :) – morbo Mar 2 at 15:46
• @morbo, I was wondering if you could post what 'model[]' is, you use it in coor - but don't post it. :) – Tomi Mar 2 at 17:42
• @Tomi whoops! Good eye, :) forgot to copy, it was just the GPT-2 NetModel – morbo Mar 2 at 20:45

Here is a poor mans version with no ML.

words = candlenames // Map[StringSplit /* TextWords] // Flatten // DeleteStopwords;

SeedRandom[111];
Table[RandomSample[words, 2], 10] // Map[StringRiffle[#, " "] &]

(*
{"Cinnamon Caramel", "Boston Cherry", "Oatmeal Cupcake", "Citrus Hot", "Black Vanilla",
"Honeysuckle Ocean", "Country Musk", "Cupcake Brown", "Sleep Rain", "Cherries Musk"}
*)

• If you downvote, please comment on why. Thanks. – Rohit Namjoshi Mar 3 at 2:34