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