Hi Jim,

Great to hear from you. Thanks for the advice.

Seems we've been doing a lot of similar work of late! (I wrote my own perceptron and unthresholded unit classes recently and had the students use them to produce various demos; the best part from a pedagogical point of view was the 3-d plots it generated; you can see http://millscs.jot.com/WikiHome/AIWeek13 and http://millscs.jot.com/ WikiHome/AIWeek12 for more if your interested.)

I used matplotlib (an old version, whose 3d plot routines were problematic), but have generally been happy with that interface (it produces high quality graphs and shares some of the benefits that Matlab has in this regard), so weight space trajectories during learning, as well as how output values changed during learning, were easy to construct and seemed to facilitate student learning.

I MAY have found a hack for doing what I want in the conx realm that requires no change to train. (My students haven't had calculus, so the NN derivation is out of scope, as is having them implement a multi-layer sigmoid-based learning alg).

Here's my current thinking, which is motivated by perusing the conx train method:

1) make the crossvalidation set be identical to the training set
2) set the savenetworkfile flag that's used when crossvalidation is set

weights of the successive networks can then presumably be retrieved from this file. I'll report back if I can actually get this hack to work.

--b

On Apr 17, 2007, at 12:23 PM, Jim Marshall wrote:

Hi Belinda,

I think you would need to rewrite the train method to record the weights. However, I just had my class do a simpler version of this exercise for a homework assignment, using gnuplot and a basic perceptron (implemented in pure Python, not Conx). The link to the assignment is here:

http://science.slc.edu/~jmarshall/courses/2007/spring/robotics/ assignments/a05/

In addition, I'll attach the completed code if you want to try it out. Hope this helps.
-jim


---------------------------
Jim Marshall
Computer Science Department
Sarah Lawrence College
Bronxville, New York


belinda thom wrote:
Hi,
Is there an easy way to record the changes made to weights during train, or would I have to basically rewrite that procedure to do what I want? I realize in non-toy problems, you'd probably not want to do this, but for simple examples (like And or fig 4.7 in Tom Mitchell's Machine Learning book) being able to access the weights as they change over time---e.g. to plot them---can be a useful pedagogical tool.
Please advise,
Thanks!
--b
_______________________________________________
Pyro-users mailing list
[email protected]
http://emergent.brynmawr.edu/mailman/listinfo/pyro-users
import random, string

def dotProduct(a, b):
    sum = 0.0
    for i in range(len(a)):
        sum = sum + a[i] * b[i]
    return sum

def pretty(values):
    return string.join(['%.3f' % v for v in values])

#--------------------------------------------------------------------- -----------

class Unit:

    def __init__(self, activation=0.0):
        self.activation = activation
        self.incomingConnections = []
        self.outgoingConnections = []

    def update(self):
activations = [c.fromUnit.activation for c in self.incomingConnections]
        weights = [c.weight for c in self.incomingConnections]
        netActivation = dotProduct(activations, weights)
        self.activation = self.stepFunction(netActivation)

    def stepFunction(self, x):
        if x > 0:
            return 1
        else:
            return 0

#--------------------------------------------------------------------- -----------

class Connection:

    def __init__(self, fromUnit, toUnit):
        self.fromUnit = fromUnit
        self.toUnit = toUnit
        self.randomize()

    def randomize(self):
        self.weight = random.uniform(-0.1, +0.1)

#--------------------------------------------------------------------- -----------

class SimplePerceptron:

    def __init__(self, numInputs):
        # create the units
        self.outputUnit = Unit()
        self.inputLayer = [Unit() for k in range(numInputs)]
        # wire up the network
        self.allConnections = []
        for unit in self.inputLayer:
            self.connect(unit, self.outputUnit)
        # connect the bias unit
        biasUnit = Unit(1.0)
        self.connect(biasUnit, self.outputUnit)
        self.learningRate = 0.1

    def connect(self, fromUnit, toUnit):
        c = Connection(fromUnit, toUnit)
        fromUnit.outgoingConnections.append(c)
        toUnit.incomingConnections.append(c)
        self.allConnections.append(c)

    def setWeights(self, newWeights):
assert len(newWeights) == len(self.allConnections), 'wrong number of weights'
        for (c, w) in zip(self.allConnections, newWeights):
            c.weight = w

    def initialize(self):
        for c in self.allConnections:
            c.randomize()
        print 'weights randomized'

    def propagate(self, pattern):
assert len(pattern) == len(self.inputLayer), 'wrong pattern size'
        for (inputUnit, value) in zip(self.inputLayer, pattern):
            assert 0 <= value <= 1, 'invalid pattern value %g' % value
            inputUnit.activation = value
        self.outputUnit.update()
        return self.outputUnit.activation

    def test(self):
print 'weights =', pretty([c.weight for c in self.allConnections])
        for pattern in self.inputs:
            output = self.propagate(pattern)
            print 'output on %s = %d' % (pattern, output)
        print

    def computeError(self):
        error = 0.0
        correct = 0
        for (pattern, target) in zip(self.inputs, self.targets):
            output = self.propagate(pattern)
            error = error + (target - output) ** 2
            if output == target:
                correct = correct + 1
        total = len(self.inputs)
        score = 100.0 * correct / total
        return (correct, total, score, error)

    # perceptron learning rule
    def teach(self, pattern, target):
        output = self.propagate(pattern)
        self.outputUnit.error = target - output
        for c in self.allConnections:
increment = self.learningRate * c.toUnit.error * c.fromUnit.activation
            c.weight = c.weight + increment

    def teachDataset(self):
        assert len(self.inputs) > 0, 'no training data'
        dataset = zip(self.inputs, self.targets)
        random.shuffle(dataset)
        for (pattern, target) in dataset:
            #print '   teaching %s -> %s' % (pattern, target)
            self.teach(pattern, target)

    # changed
    def train(self, cycles=1000):
        assert len(self.inputs) > 0, 'no training data'
        (correct, total, score, error) = self.computeError()
print 'Epoch # 0: TSS error %7.4f, %d/%d correct (%.1f% %)' % \
              (error, correct, total, score)
        self.learningRate = 0.001
        file = open('pathway.dat', mode='w')
        for c in self.allConnections:
            file.write('%12g ' % c.weight)
        file.write('\n')
        for t in range(1, cycles+1):
            self.teachDataset()
            (correct, total, score, error) = self.computeError()
print 'Epoch #%4d: TSS error %7.4f, %d/%d correct (%.1f% %)' % \
                  (t, error, correct, total, score)
            for c in self.allConnections:
                file.write('%12g ' % c.weight)
            file.write('\n')
            if correct == total:
                print 'All patterns learned'
                break
        file.close()

#--------------------------------------------------------------------- -----------

# part 1
n = SimplePerceptron(2)
n.inputs = [[0, 0], [0, 1], [1, 0], [1, 1]]
n.targets = [0, 0, 0, 1]  # AND function

# to see training pathway, do this:
# >>> n.train()
# gnuplot> set style data linespoints
# gnuplot splot 'pathway.dat' pt 7

# part 2
carry = SimplePerceptron(3)
carry.inputs = [[0, 0, 0],
                [0, 0, 1],
                [0, 1, 0],
                [0, 1, 1],
                [1, 0, 0],
                [1, 0, 1],
                [1, 1, 0],
                [1, 1, 1]]
carry.targets = [0, 0, 0, 1, 0, 1, 1, 1]

sum = SimplePerceptron(3)
sum.inputs = carry.inputs
sum.targets = [0, 1, 1, 0, 1, 0, 0, 1]

_______________________________________________
Pyro-users mailing list
[email protected]
http://emergent.brynmawr.edu/mailman/listinfo/pyro-users

Reply via email to