Tags

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

Earlier this year I built a virtual girlfriend for Arkwood, to ease his lonely heart. But today he said to me, ‘The sex is great, but the conversation is limited.’ I was shocked. My Belgian buddy had never struck me as an Oscar Wilde or a Winston Churchill. ‘Okay,’ I conceded, ‘I will give your girlfriend some artificial intelligence.’

Scouting around for a suitable Python neural network, PyBrain caught my eye. Great! I will install it on my tiny Raspberry Pi computer and provide his sweetheart with a sophisticated brain.

But first, I would really like to get PyBrain working on my Windows 7 PC, so I can construct the neural network using the rich debugging and Intellisense experience of Python Tools for Visual Studio. Problem is, installing PyBrain’s dependencies on Windows – namely Scipy and Matplotlib – turns out to be a bit of a ball ache (incl. a cryptic error about vcvarsall.bat).

Anaconda provided the answer – it’s a Python distribution containing various scientific packages, including the dependencies I’m after. I downloaded and installed it (Windows 64-Bit, Python 2.7). Indeed, Python Tools for Visual Studio recommends it. And Anaconda provides instruction to check its integration with Python Tools for Visual Studio. You may need to set up an environment in Visual Studio for Anaconda:
anaconda_environment

Now we have our Anaconda environment in Visual Studio, we can simply right-click it and install the PyBrain Python package using pip:
anaconda_install_package

Pip has given me PyBrain 0.3 – trying to force it to yield PyBrain 0.3.1 proves troublesome, so I grab it from GitHub instead.

Okay, we’re now ready to create a neural network on our Windows 7 PC. Let’s start by creating a Python class to handle the classic XOR network.

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):
        
        dataset = SupervisedDataSet(2,1)

        dataset.addSample([1,1],[0])
        dataset.addSample([1,0],[1])
        dataset.addSample([0,1],[1])
        dataset.addSample([0,0],[0])

        return dataset

    # create network
    def create_network(self, dataset):

        return buildNetwork(dataset.indim, 3, dataset.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)
        for epoch in range(0, 1000):
            trainer.train()
        
        return network

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

        dataset = UnsupervisedDataSet(2)
        dataset.addSample(data)  
        
        return network.activateOnDataset(dataset)[0]

My NetworkHelper class is based on a code sample from Kristina Striegnitz, linked into an informative Stack Overflow article. It allows us to create a dataset, a network, and methods to train and test the network. Debugging the code with Python Tools for Visual Studio, we can take a peek at some of our network and dataset values:

pybrain_debug

Next we need to give Arkwood’s virtual girlfriend a lobotomy, swapping out a config file for our neural network:

from networkhelper import NetworkHelper
from speech import Speech

network_helper = NetworkHelper()
speech = Speech()

# define conversation
conversation = {
    'cook food': [0,0],
    'wash plates': [1,1],
    'kiss me': [0,1],
    'hug me': [1,0]
    }

# define love
true_love = 1.0
true_disgust = 0.0

# train a neural network
dataset = network_helper.create_dataset()
network = network_helper.create_network(dataset)
network = network_helper.train_network(network, dataset)

# loop forever
while True:

    # speak to girlfriend
    my_chat = speech.speech_to_text('/home/pi/PiAUISuite/VoiceCommand/speech-recog.sh')

    # weed out pointless conversation
    if my_chat not in conversation: 
        speech.text_to_speech("what you say baby")
        continue

    # get output from neural network
    data = conversation[my_chat]
    output = network_helper.test_network(network, data)[0]
    her_chat = round(output, 1)

    # now girlfriend speaks to Arkwood
    if(her_chat == true_love):
        speech.text_to_speech("oh darling")
    elif(her_chat == true_disgust):
        speech.text_to_speech("die in a ditch you worthless piece of shit")
    else:
        speech.text_to_speech("my feelings are so confused")

After setting up a couple of variables, we plough on with training our network. Once done, we drop into a while loop, where the conversation between Arkwood and his girlfriend happens. As per my previous post, Google’s Speech To Text service is used to convert Arkwood’s microphone commands into text. Next up, we pass Arkwood’s words to our network and get a reply, representing his girlfriend’s true love or disgust. For example, if Arkwood has asked his flame to wash the dishes then she spits back at him ‘die in a ditch you worthless piece of shit’. Fair enough. If the network fails to provide an appropriate reply, his girlfriend merely informs that she is confused. Her words are passed back to Arkwood through a set of speakers using Google’s Text To Speech service.

Brilliant. All that is left to do is install PyBrain on my Raspberry Pi and let Arkwood woo his girlfriend:

pi_pybrain_output

Hurray! Arkwood and his paramour are in conversation.

‘But she’s just as dumb as before,’ he moaned. I told him that this was just the beginning, and that the neural network could be developed to permit all manner of social intercourse. ‘I will soon have her discussing the merits of seventeenth-century philosophy.’

Arkwood unbuckled his trousers and asked me to leave the room. Clearly philosophy was not on his agenda tonight, anyhow.

Advertisements