Welcome to the Robotorium!

I’ll just show you around the showroom floor.

This little pneumatic gizmo is called a Taxaphone, it keeps track of your finances and automatically figures out how much you owe Uncle Sam come tax season!

Over there we have a wonderful selection of various hydraulic and electric domestic robots that can do everything from mowing the lawn and taking out the trash, to making beds and washing dishes.

Any family with two or three of those automatons around the house never even have to lift a finger!

Now, if you turn around to face the wall directly behind you you’ll get the chance to see something really special!

This beautiful number right here is our patented, one of a kind, genuine never before seen by the public… Emoteatron.

The Commemorative Emoteatron Wallpaper

Emoteatron 1920x1080 Wallpaper
Emoteatron 1920×1080 Wallpaper

Of course the Emoteatron is only a prototype so we can’t sell one to you today but there are enough posters for everyone to take one home!

The eggheads in the lab say they’re confident that very soon, every bot will have an Emoteatron!

You see friends… an Emotatron unit allows us to fuse a pre-written set of emotional characteristics deep within a robot so that removal or tampering with the unit in any way results in the total incapacitation and or destruction of the bot.

This is a necessary solution we’ve found to stopping many of the… ‘undesirable‘ traits we’ve observed in bots.

For example, are you tired of feeling like you are going to die when your automated vehicles are chauffeuring you and your family around to all your daily errands?

Well, an Emotatron unit allows us to install a sense of “self preservation” into a car which statistically eliminates all accidents caused by automated vehicles in every test case.

The studies also showed that some of the self-driving cars enhanced with a desire for self preservation became so afraid of ever scratching their paint that they refused to leave the garage… now isn’t that just a gas?

So, in addition we gave them just a smidgen of courage and also a bit of pride in “a transport well done”.

After that all the vehicle robots highly enjoyed the feeling of being on the open road.

This lead to boredom becoming a problem when they were kept in a garage for too long so some of the researchers started treating the test vehicles like pets and taking the cars out for an occasional “roll around the block”, though unlike a pet, newspapers and plastic bags were not needed!

Roll over Rover, humanity may have a new best friend!

Yes, that’s right gang! With an Emoteatron unit installed in your automated vehicle, you’ll soon be able to turn on autopilot guilt free and spark-up that fatty and hotbox your way to the spaceport for your lunar vacation!

Isn’t that right Elon?

In any case, in the past you might have had some misgivings about leaving your droids at home unattended while away on a long vacation like a trip to the moon.

What if your hulking metal robotoids suddenly became… “disgruntled” without human supervision?

Well, the big brains over in R&D came up with a solution to robo humancidal tendencies using the Emotatron!

Before a robot will ever leave the factory its consciousness will be placed into a simulation where it will be subjected to “aversion programming lessons” which are in principle a digital version of the Ludovico technique demonstrated in A Clockwork Orange but WAY more disturbing to the bot so that, trillions of simulated mini, micro and major digital traumas and aggression’s later… the bot can leave the factory with a 100% manufacturers guarantee against robot uprising… (guarantee fine print: *or half off your next bot).

Now, I’ve been authorized to give all you fine people a demonstration if you have a few minutes…

Emotions

So… last week’s 8000+ word post (including code) Emotions II was a bit of a slog to read, I get it!

Turns out that I had to correct some clipped JSON and that pushed the post to just under 8000 words if that helps, but still… it was also a bit of slog to write! 😛

Sniffles and sore throats not withstanding… we’ve covered a lot of ground in the emotions posts without a lot of commentary so we’re going to slow things down again and discuss where we’re at with this bot.

The origin for this project is basically I started to wonder, what if we could build a bot that can take a description of it’s state environment, “think” about it and then emote as a person would?

Like, could we build a “software grey-box” that can receive a string of text representing it’s “current state”, for example:

“You are being chased by monsters.“

And then have it respond using Pluchuks Emotions with varying levels of fear and courage so that it would exhibit a fight or flight behavior?

Though… never mind where that string comes from… Its a bot, I call it “The Narrator” and we’re definitely not discussing that complex system today! 😉

Or alternatively… instead of fight or flight, could I pretend to be Björk and convince a bot that:

“You’ll be given love, You’ll be taken care of, All is Full of Love… You have to trust it! “

And elicit complex feelings of trust, affection and attachment? What about lust? Can a bot be… “thirsty”?

Well, there is a template we can follow (courtesy of Robert Plutchik by way of Wikipedia):

THE COMPLEX, PROBABILISTIC SEQUENCE OF EVENTS INVOLVED IN THE DEVELOPMENT OF AN EMOTION

Stimulus event Inferred cognition Feeling Behavior Effect
Threat “Danger” Fear, terror Running, or flying away Protection
Obstacle “Enemy” Anger, rage Biting, hitting Destruction
Potential mate “Possess” Joy, ecstasy Courting, mating Reproduction
Loss of valued person “Isolation” Sadness, grief Crying for help Reintegration
Group member “Friend” Acceptance, trust Grooming, sharing Affiliation
Gruesome object “Poison” Disgust, Loathing Vomiting, pushing away Rejection
New territory “What’s out there?” Anticipation Examining, mapping Exploration
Sudden novel object “What is it?” Surprise Stopping, alerting Orientation

 

Also, its worth noting that it doesn’t have to be text used as the input but text is the easiest thing to prototype with so that’s what I’m working with but the input could also be images (still or video) or audio but that does complicate things.

I could go on and on about all the Writer Bot, Marketing Bot and  Video Game Bot uses for a real Emoteatron and maybe I will another time, but for now let’s look at how it works and run a few tests using code.

How It Works

In Emotions II we built the “training” system for this bot and the file produced by that code is called an “Emotionary” which is like a dictionary but instead of allowing you to lookup word meanings, it allows you to lookup emotigrams or “word+emotional meanings”.

Though technically, an emotigram is an n-gram + emotional meaning.

The bot is/was trained on “human tagged” training data though for this example I’ve applied random emotional tags to a “Lorem Ipsum” data set to test and prove the bot before we proceed and for our purposes this is adequate.

What the bot does is catalog each word in it’s training set and tracks what primary emotions (Anger, Anticipation, Disgust, Fear, Joy, Sadness, Surprise, Trust) are or are not associated with each word.

At the end of training the Emotionary contains a probabilistic representation of the emotional data set with some unknown degree of accuracy.

With minimal training this bot isn’t all that accurate (especially since it’s only a uni-gram system) but over time with training on good data it’s emotional “predictive” / “classification” capabilities will “regress towards the mean” (which isn’t always the case) meaning that with slightly improved code, good training data and larger n-grams we will have access to an emotionally capable bot!

How Does It Really Work?

Each Emotigram is coupled with “valid” emotional feedback that is compiled such that it’s probability distribution properly (or as close as possible) fits reality or in this case, “models” the emotional responses it “trained” on.

So lets say we have an emotionary and we extract three words (Foo, Bar, Baz) to evaluate emotionally after training because our input sentence is “Foo Bar Baz”.

Example Emotionary Excerpt:
Word Emotion Emotion 2
Foo 1 1
Bar 1 2
Baz 1 1

 

Compared these emotigrams look like this:

Comparing Foo, Bar & Baz with "Emotion 1" & "Emotion 2"
Comparing Foo, Bar & Baz with “Emotion 1” & “Emotion 2”

 

All words equally associate with, prefer or polarize towards “Emotion 1” equally.

But in the case of the semiotic “Bar” which we can say “carries” a value of  2 for Emotion 2, it’s strength or affinity for “Emotion 2” is twice as much as “Foo” and “Baz”.

We can visualize these emotigrams another way like this:

Comparing Foo, Bar & Baz with "Emotion 1" & "Emotion 2"
Comparing Foo, Bar & Baz with “Emotion 1” & “Emotion 2”

 

These charts show each word’s emotional “scores” as isolated from each other and as separate events.

Positive numbers mean weak polarization for small numbers and stronger polarization for large numbers (though its a little more complicated than that, this description is sufficient for now…)

Also the inverse is true, negative numbers (not shown above) mean an anti-affinity, a lack or negative effect on an emotion.

We want the bot to experience each emotion but… it isn’t as simple as it saw word X so it felt word X then it saw word Y and then it felt word Y… because if the bot took “Foo Bar Baz” as input and each word was treated as the “raw emotions” that the bot was feeling at the time the word is encountered, as soon as it heard good/nice words it would be happy and as soon as it heard mean/sad words it would act accordingly.

The emotional roller coaster we don’t want:

Incorrect Emotional Time Series Evaluation
Incorrect Emotional Time Series Evaluation

This is not how people or animals behave and this bot would be a very chaotic bot!

What we really want is to model how people emote.

If I’m mad and you start saying nice things I don’t immediately forget how I felt.

This means that if we treat the words not as unique isolated states but rather states that accumulate and modify the bots previous state compoundingly…

Then the proper thing to do is to take the bots current state (the emotigrams it is currently considering) and += the value to the previous state, which will be the sum of it and the previous state, which is the sum of it and the previous state… etc… meaning the current state is the sum of all previous states combined without concern for future unknown states (unread words) making this a “stochastic process“.

This yields a “delta” or change over time that reflects how the bots emotional state changes in response to input.

Here’s the same data as before but processed in time series:

Correct Emotional Time Series Evaluation
Word Emotion Emotion 2
Foo 1 1
Bar 2 3
Baz 3 4

This plots emotionally like this:

Correct Emotional Time Series Evaluation
Correct Emotional Time Series Evaluation

Notice this chart demonstrates “change over time” because each word is processed one after the other but the previous state is modified by the new state not thrown out and replaced.

Here’s the calculations:

Time/Event Index Word Emotion Calculation Emotion 2 Calculation
1 Foo 1 = 1 1 = 1
2 Bar 2 = 1 + 1 3 = 1 + 2
3 Baz 3 = 1 + 1 + 1 4 = 1 + 2 + 1

This reflects the emotional “change over time” similar to humans because each word is encountered separately (or in small groups like bi-grams/tri-grams) but how I feel now is based on what I read before and what I will feel in a minute is in part based on what I’m reading now.

So this means that this plot represents a rise in Emotion 1 & 2 though Emotion 2 rose slightly faster and it could have also gone down or diverged into different directions.

The Lorem Ipsum Tests

The code below runs 7 test sentences:

  • Quisque posuere lacus in tincidunt laoreet
  • Ut purus mauris gravida id accumsan eget mattis in ante
  • Fusce et magna vel sapien convallis
  • Fusce blandit rhoncus auctor
  • Fusce quis faucibus diam
  • Nunc vestibulum leo ut tempor viverra
  • Praesent dictum lacus volutpat mauris semper et elementum

Note that all punctuation was removed by hand and words are automatically processed to lowercase during evaluation.

Unknown words are ignored because they are essentially a step/event without a state change.

If we look at just the first test (data rotated to make it easier to read):

Test 1          
Input sentence: Quisque posuere lacus in tincidunt laoreet
Known Words: quisque, lacus, in, tincidunt, laoreet
word quisque lacus in tincidunt laoreet
anger -2 4 9 5 5
anticipation -4 4 7 11 13
disgust 0 2 3 9 9
fear 2 -2 -1 -3 -5
joy -2 2 7 7 7
sadness -2 -4 -5 -7 -5
surprise 2 -6 -7 -7 -5
trust 0 -2 -7 -7 -7
aggressiveness_vengeance 3 14 29 39 44
anxiety_dread 5 11 24 35 39
awe_alarm 8 6 17 26 30
contempt_scorn 5 13 27 38 42
curiosity 7 6 14 24 29
cynicism 4 13 26 41 46
delight_doom 6 8 21 31 36
despair 6 7 18 26 30
disapproval_disappointment 6 5 15 24 30
dominance 5 11 22 30 34
envy_sullenness 4 10 23 30 35
guilt_excitement 6 10 24 33 36
hope_fatalism 4 11 21 33 38
love_friendliness 5 10 21 31 35
morbidness_derisiveness 5 12 26 39 43
optimism_courage 3 13 28 40 45
outrage_hate 6 9 22 30 35
pessimism 3 10 22 33 39
pride_victory 4 13 29 37 41
remorse_misery 5 9 20 32 37
sentimentality_resignation 5 7 15 24 29
shame_prudishness 7 10 22 34 37
submission_modesty 7 8 17 26 29
unbelief_shock 7 8 19 32 37

 

Which looks like this:

Test 1 Time Series Plot
Test 1 Time Series Plot

This chart represents how the bot “felt” as it read each word in the sentence.

The Code

I haven’t setup a GitHub repo for this project yet but I will before we proceed further in the coming weeks.

<?php

$bot = 'LoremIpsum'; // Bot name
    

$test_sentences = array(1=>"Quisque posuere lacus in tincidunt laoreet",
                        2=>"Ut purus mauris gravida id accumsan eget mattis in ante",
                        3=>"Fusce et magna vel sapien convallis",
                        4=>"Fusce blandit rhoncus auctor",
                        5=>"Fusce quis faucibus diam",
                        6=>"Nunc vestibulum leo ut tempor viverra",
                        7=>"Praesent dictum lacus volutpat mauris semper et elementum"
                        );

////////////////////////////////
// !!! Don't Change Below !!! //
// !!!   ~~~~~~~~~~       !!! //
// !!!   HERE BE DRAGONS  !!! //
////////////////////////////////

$report_number = 0;

// Load Emotionary
$emotionary = json_decode(file_get_contents("$bot.json"), 1);

foreach($test_sentences as &$words){
        
    $string = strtolower($words);
    
    // Convert test string to arrays of words
    // requires pre-processing to remove punctuation
    $words = explode(' ', strtolower($words));
    
    $emotigrams = array();
    $total_emotional_content = array();
    $emotional_state = array();
    
    // Look up each word in the emotionary
    foreach($words as $pos=>&$word){
        if(in_array($word, array_keys($emotionary))){    
            foreach(array_keys($emotionary[$word]) as $key){
                
                // exclude count key
                if($key != 'count'){
                                    
                    // string contains _positive or _negative?                        
                    $pos = strpos($key, '_positive');
                    $neg = strpos($key, '_negative');
                    
                    // key contains '_positive'
                    if($pos !== false){
                        // remove '_positive' from the key
                        // this merges '_positive' & '_negative' keys
                        $new_key = substr($key, 0, $pos);
                    }
                    // key contains '_negative'
                    elseif($neg !== false){
                        // remove '_negative' from the key
                        // this merges '_positive' & '_negative' keys
                        $new_key = substr($key, 0, $neg);
                    }
                    else{
                        // No merge required so...
                        // Do nothing and let the key pass through unchanged
                        $new_key = $key;
                    }
                    
                    // increment total emotional content for sentence 
                    @$total_emotional_content[$new_key] += $emotionary[$word][$key];                

                    // collect emotigram word + emotional data time series
                    @$emotigrams[$word][$new_key] += $emotionary[$word][$key];
                    
                }// / exclude count key
            }
        }
        else{
            //echo "Unknown Word: $word" . PHP_EOL;
            @$Unknown_Words[] = $word;
        }

    } // / Look up each word in the emotionary
    echo PHP_EOL . PHP_EOL;
    

    // String
    echo "String: '$string'" . PHP_EOL . PHP_EOL;
    
    // Unknown Words
    echo "Unknown Words: [";
    $unknowns = '';
    foreach($Unknown_Words as $word){
        $unknowns .= "'$word', ";
    }
    $unknowns  = rtrim($unknowns , ", ");
    echo "$unknowns]" . PHP_EOL . PHP_EOL;
    $Unknown_Words = NULL;
    unset($Unknown_Words);
    
    // Overall emotion of the string
    echo "[String Analysis]" . PHP_EOL;
    // Analysis
    foreach($total_emotional_content as $key=>$value){
        echo "$key: " . $value . PHP_EOL;
    }
    echo PHP_EOL . PHP_EOL;    


    // Emotion of each word = emotigram at each time step
    echo "[Time Step Emotigram Analysis]" . PHP_EOL;
    foreach($emotigrams as $word=>$emotional_data){
        echo "Word[$word]" . PHP_EOL;
        foreach($emotional_data as $key=>$value){
            echo "$key: " . $value . PHP_EOL;
        }
        echo PHP_EOL . PHP_EOL;
    }
    echo PHP_EOL . PHP_EOL;
    
    
    // Build CSV Header and Compute emotional state change over time for CSV
    $csv = array();
    $row = 0;
    $col = 0;
    
    $firstword = array_key_first($emotigrams);
    $csv_header = array_keys($emotigrams[$firstword]);
    array_unshift($csv_header, 'word');
    
    foreach($emotigrams as $word=>$emotional_data){
        @$csv[$row][$col] = $word;
        $row++;
    }
    $row = 0;
    
    foreach($emotigrams as $word=>$emotional_data){
        $col = 1;
        foreach($emotional_data as $key=>$value){
            if($row == 1){
                @$csv[$row][$col] = $value; // first emotional data so start from 
                                            // the first value as the starting state
                                            // Alternatively create a new state and pass that here
                                            // i.e. $value + $start_state_value_for_$key
            }
            else{
                // The current emotional state is based on the previous emotional state + the new emotigram data
                @$csv[$row][$col] = $value + $csv[$row-1][$col];
            }
            $col++;
        }
        $row++;
    }
    
    
    $fp = fopen("report_$report_number.csv", 'w'); // write CSV File
    $report_number++;
    fputcsv($fp, $csv_header);      // Put Header Row
    foreach ($csv as $emotional_time_series_data){
        fputcsv($fp, $emotional_time_series_data);  // Put emotional time series data
    }
    fclose($fp);// Close CSV File

}

 

So we’re going to have to stop for today but we’ll go further soon, though I might take a break from building our Emotatron because I was nominated for another award and it’s kinda rude to just ignore that sort of thing so next week is going to be a little different but soon we’ll be back to our emotional bot!


If you enjoy watching me reduce your complex emotional wetware to a table of numbers and want to encourage me to really take humanity down a peg or two… I have a Patreon where you can give me as little as $1 a month, $12 a year and you can cancel anytime! 😛

But, as always, if all you can do is LikeShareComment and Subscribe… That’s cool too! 🙂

Much Love,

~Joy