, , , , , , , , , , , ,

In my previous post, PyBrain on Raspberry Pi, I tinkered with Arkwood’s virtual girlfriend. I conducted a brain transplant, providing her with a neural network in the shape of the PyBrain Python package. Next up, I want to store an actual word in her brain, so that she can use it in conversation with my Belgian buddy.

Without further to do, let’s take a gander at the first part of the code, which trains the network:

from speech import Speech
from networkhelper import NetworkHelper
from languagehelper import LanguageHelper

speech = Speech()
network_helper = NetworkHelper()
language_helper = LanguageHelper()


# utter the secret word
print "Utter the secret word"
secret_word = speech.speech_to_text('/home/pi/PiAUISuite/VoiceCommand/speech-recog.sh').lower()

# create dataset
dataset = network_helper.create_dataset()

# update dataset with secret letters
for letter in secret_word:
    binary = language_helper.get_letter_binary(letter)
    network_helper.update_dataset(dataset, binary, DATASET_OUTPUT_SECRETLETTER)

# update dataset with other letters
for letter in language_helper.get_other_letters(secret_word):
    binary = language_helper.get_letter_binary(letter)
    network_helper.update_dataset(dataset, binary, DATASET_OUTPUT_OTHERLETTER)

# train network
network = network_helper.create_network(dataset.indim, dataset.outdim)
network_helper.train_network(network, dataset)

After initializing some helper classes and a couple of constants, we use a microphone attached to the computer to speak the secret word – the word we want to store in our neural network. We use Google’s Speech To Text service to convert the spoken word into text.

Next, we create a dataset for our network. The dataset is updated with the binary representation of each letter in our secret word. For example, the letter ‘s’ has a binary value of 1110011 – so these seven digits will be the input to our dataset, along with an output value of 1. We also update the dataset with other letters that do not feature in our secret word, with an output value of 0.

Finally, we can create and train our network on the dataset. Arkwood’s girlfriend’s brain has now stored the secret word.

Now for the second part of the code, which will test the network:

# test network
while True:

    # speak to girlfriend
    print "Charm her with your razor-sharp wit"
    my_chat = speech.speech_to_text('/home/pi/PiAUISuite/VoiceCommand/speech-recog.sh').lower()

    if(not my_chat):

    # girlfriend's brain processes your chat 
    retrieved_secret_word = None

    for word in my_chat.split():
        other_letter_found = False       
        for letter in word:
            binary = language_helper.get_letter_binary(letter)
            output = round(network_helper.test_network(network, binary)[0], 1)
            if(output != DATASET_OUTPUT_SECRETLETTER):
                other_letter_found = True

        if(not other_letter_found):
            retrieved_secret_word = word

    # girlfriend speaks
        speech.text_to_speech("oh darling, {} is just the tonic".format(retrieved_secret_word))
        speech.text_to_speech("honey, why are you beating around the bush?")

Within a while loop, Arkwood talks to his girlfriend, making use of Google’s Speech To Text service once again.

Now comes the moment of truth – can Arkwood’s girlfriend spot the secret word in his chat? First she splits his chat into single words, and then feeds the letters of each word into her brain i.e. the neural network. If any of the letters do not have a value of 1, she moves on to the next word. But if all the letters do have a value of 1 then the secret word has been found. Hurray!

Finally, his girlfriend uses Google’s Text To Speech service to speak to Arkwood through a set of speakers attached to the computer. If the secret word was found, he gets a saucy response. Otherwise, she quizzes him on beating around her bush.

Okay, let’s take the program for a test drive. I used the rich debugging and IntelliSense experience of Python Tools for Visual Studio on my Windows 7 PC to get it all working. But for the actual test, I want to port the code to my tiny Raspberry Pi computer. Why, you might ask? Well, because I like the idea that the program will run successfully on low spec kit and open source software that anyone can get their hands on. Here goes…


Wow! Arkwood, the sick pervert, has chosen the secret word ‘sex’. The word has been inserted into his girlfriend’s brain. Now when he utters the word in a sentence, she recognises it and responds accordingly. If he does not utter it, she grows impatient.

‘I’ll never get tired of talking to her now,’ Arkwood said with verve.

I sighed. ‘You know, you can choose another secret word. It doesn’t have to be “sex” every time.’

Arkwood retorted, ‘It does for me!’ How we both laughed.


Here’s the code for the LanguageHelper class:

import binascii
import re

class LanguageHelper(object):
    # get letter binary
    def get_letter_binary(self, letter):
        binary = bin(ord(letter))[2:].zfill(7)
        return list(binary) 

    # get other letters
    def get_other_letters(self, secret_word):
        alphabet = 'abcdefghijklmnopqrstuvwxyz'
        other_letters = re.sub("[{}]".format(secret_word), "", alphabet)
        return other_letters[:len(secret_word)]

And the code for the NetworkHelper class:

from pybrain.datasets import SupervisedDataSet
from pybrain.tools.shortcuts import buildNetwork
from pybrain.supervised import BackpropTrainer
from pybrain.datasets import UnsupervisedDataSet

class NetworkHelper(object):
    # create dataset
    def create_dataset(self):
        return SupervisedDataSet(7, 1)

    # update dataset
    def update_dataset(self, dataset, input, output):

        dataset.addSample(input, output)

    # create network
    def create_network(self, indim, outdim):

        return buildNetwork(indim, 7, outdim, recurrent=True)

    # train network on supplied dataset
    def train_network(self, network, dataset):

        trainer = BackpropTrainer(network, dataset, learningrate = 0.01, momentum = 0.99, verbose = True)

    # test network on supplied input
    def test_network(self, network, input):

        dataset = UnsupervisedDataSet(7)
        return network.activateOnDataset(dataset)[0]

If you want to see how the Speech class works, take a peek at my post, Virtual girlfriend on Raspberry Pi.

There are a couple of caveats, granted. If the secret word contains other words – such as ‘today’ containing ‘to’ and ‘day’ – then all these words will be successful. Also, the code does not cater for the secret letters being in a different order, or multiple occurrences of a secret letter. That said, if Arkwood sticks to ‘sex’ then he shouldn’t go far wrong.