giovinazzo-kevin / Adjustable-Markov-Chains

Adjustable Markov Chains is a Python implementation of a text generator based on the concept of Markov Chains, that can be adjusted further via fitness functions.
MIT License
25 stars 4 forks source link

Quick question #2

Open mfuery opened 5 years ago

mfuery commented 5 years ago

Thanks a lot for your article on Medium and your code. I'm having trouble understanding what this line is doing: https://github.com/G3Kappa/Adjustable-Markov-Chains/blob/462a98448566b68817a45ff4cec9d241584008db/markovchain.py#L171

in the fitness calculation. Would you explain step by step/or in a more verbose imperative language, what that is doing? I am trying to build my own Markov generators.

Thanks!

giovinazzo-kevin commented 5 years ago

Hi Michael,

Let's see here. It has been a while 😁

The train function is asking for a string. But we're iterating a list of pairs right now. So if we want to train the chain on the string "wordA wordB" by a factor of X, we're going to have to concatenate the pair ["WordA", "WordB"] first.

Honestly, now that I'm looking at it, I'm not sure why I chose to use reduce. You'd want to use reduce if you already had a list of pairs and wanted to build a fully concatenated string (i.e. if you didn't explicitly iterate it as I'm doing), but I'm only concatenating the individual words from each pair so there's no need for that. In other words, I could have written: self.train('{0} {1}'.format(p[0], p[1]), x).

But anyway, to explain reduce in an imperative context you have to look no further than a for loop that sums an array of ints.

int arr = new int[8];
...
int sum = arr[0];
for(int i = 1; i < arr.Length; ++i)
{
    sum += arr[i];
}
// Same as sum = reduce(lambda a, b: a + b, arr);

Hope that was clear enough, and thank you for enjoying my article and reaching out!

mfuery commented 5 years ago

It was the reduce that was confusing me. But taking it out I think I get it. It will train() onto the existing Markov chain by factor x for string a. Since x has been calculated to be between -1 and +1, this call to train() will either add or subtract from the weight of the connection of string a to b.

x was determined by https://github.com/G3Kappa/Adjustable-Markov-Chains/blob/462a98448566b68817a45ff4cec9d241584008db/markovchain.py#L166

Thanks again!

mfuery commented 5 years ago

Also, I was working 1) dad jokes, and 2) platitudes generators. Do you have suggestions for what some fitness functions I could create to make them more believable? So far, adding more data to the training set seems to help a bit, but by no means correct.

I'm wondering if I'm near the maximum extent I can improve my generators, without moving to NLP or something like that. It's even trickier because jokes and platitudes can employ colloquialisms, cultural references, which I have non experience building for.

giovinazzo-kevin commented 5 years ago

Well, Markov Chains are cool but there's a roof past where, I think, you really cannot push them (not without them turning into something different). I think there are still a few areas worth exploring though, such as coming up with better data structures that allow finer training, for example. Right now you can fine-tune adjacent word pairs but you could borrow some NLP techniques and make fitness functions that only work only when the pairs or the sentence they're included in match some semantic rules. But you'd need something a bit more complex than a tree for that.

The problem with most jokes, even dad jokes, is that they rely on human abstractions that cannot be learned trivially by analyzing some text. If you throw more data at the bot it will probably produce sentences that sound better, but it will always reuse jokes and at most mix them up slightly, admitted that it can even produce valid jokes. And you can't just write a fitness function to measure the objective quality of a joke in the same way as you measure the objective number of vowels and consonants in a pair of words.

As for platitudes, I think you might be in better luck. They don't need to be particularly meaningful: in fact, they're meaningless by definition. They just need to sound meaningful, and you can choose fitness functions that favor longer and more complex words, or maybe words that sound philosophical and existential (left as an exercise, but I'd start by looking at suffixes).

mfuery commented 5 years ago

Thanks, that's very helpful! :)