User:Ping/Python Perceptron: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
No edit summary |
||
| Line 73: | Line 73: | ||
rate *= 0.99 | rate *= 0.99 | ||
</pre> | |||
The version below has two classes: Perceptron (which produces a floating-point output) and BooleanPerceptron (which produces a Boolean output). | |||
<pre>#!/usr/bin/env python | |||
__author__ = 'Ka-Ping Yee <ping@zesty.ca>' | |||
def dot_product(inputs, weights): | |||
return sum(input*weight for input, weight in zip(inputs, weights)) | |||
class Perceptron: | |||
def __init__(self, size): | |||
"""The 'size' parameter sets the number of inputs to this Perceptron.""" | |||
self.weights = [0.0]*size + [0.0] | |||
def __repr__(self): | |||
"""Display the internal weights of this Perceptron.""" | |||
weights = ', '.join('%.3g' % weight for weight in self.weights) | |||
return '<%s %s>' % (self.__class__.__name__, weights) | |||
def evaluate(self, inputs): | |||
"""Evaluate this Perceptron with the given inputs, giving 0 or 1. | |||
'inputs' should be a list of numbers, and the length of the list | |||
should equal the 'size' used to construct this Perceptron.""" | |||
return dot_product(self.weights, inputs + [1]) | |||
def adjust(self, inputs, rate): | |||
"""Adjust the weights of this Perceptron for the given inputs, using | |||
the given training rate.""" | |||
for i, input in enumerate(inputs + [1]): | |||
self.weights[i] += rate*input | |||
def train(self, inputs, expected_output, rate): | |||
"""Train this Perceptron for a single test case.""" | |||
output = self.evaluate(inputs) | |||
self.adjust(inputs, rate*(expected_output - output)) | |||
def train_all(self, training_set, rate): | |||
"""Train this Perceptron for all cases in the given training set.""" | |||
for inputs, expected_output in training_set: | |||
self.train(inputs, expected_output, rate) | |||
def check_all(self, training_set): | |||
"""Check whether this Perceptron produces all the correct outputs.""" | |||
print self | |||
failures = 0 | |||
for inputs, expected_output in training_set: | |||
output = self.evaluate(inputs) | |||
print ' %r -> %r (want %r)' % (inputs, output, expected_output) | |||
if output != expected_output: | |||
failures += 1 | |||
return not failures | |||
class BooleanPerceptron(Perceptron): | |||
def evaluate(self, inputs): | |||
"""Just like Perceptron.evaluate, but apply a threshold.""" | |||
return int(Perceptron.evaluate(self, inputs) > 0) | |||
training_set = [ | |||
([1, 0, 0], 1), | |||
([1, 0, 1], 1), | |||
([1, 1, 0], 1), | |||
([1, 1, 1], 0), | |||
([0, 1, 0], 1), | |||
([0, 0, 1], 1), | |||
([0, 1, 1], 1), | |||
([0, 0, 0], 1), | |||
] | |||
perceptron = BooleanPerceptron(3) | |||
rate = 0.1 | |||
while rate > 1e-9: | |||
if perceptron.check_all(training_set): | |||
print | |||
print 'Success:', perceptron | |||
break | |||
perceptron.train_all(training_set, rate) | |||
rate *= 0.9999 | |||
</pre> | </pre> | ||
Revision as of 20:36, 18 March 2009
This Perceptron builds in a bias input (by internally appending an extra 1 to the inputs).
#!/usr/bin/env python
__author__ = 'Ka-Ping Yee <ping@zesty.ca>'
def dot_product(inputs, weights):
return sum(input*weight for input, weight in zip(inputs, weights))
class Perceptron:
def __init__(self, size):
"""The 'size' parameter sets the number of inputs to this Perceptron."""
self.weights = [0.0]*size + [0.0]
self.threshold = 0.0
def __repr__(self):
"""Display the weights and threshold of this Perceptron."""
weights = '[%s]' % (', '.join('%.3g' % w for w in self.weights))
return '<weights=%s, threshold=%r>' % (weights, self.threshold)
def evaluate(self, inputs):
"""Evaluate this Perceptron with the given inputs, giving 0 or 1.
'inputs' should be a list of numbers, and the length of the list
should equal the 'size' used to construct this Perceptron."""
return int(dot_product(self.weights, inputs + [1]) > self.threshold)
def adjust(self, inputs, rate):
"""Adjust the weights of this Perceptron for the given inputs, using
the given training rate."""
for i, input in enumerate(inputs + [1]):
self.weights[i] += rate*input
def train(self, inputs, expected_output, rate):
"""Train this Perceptron for a single test case."""
output = self.evaluate(inputs)
self.adjust(inputs, rate*(expected_output - output))
def train_all(self, training_set, rate):
"""Train this Perceptron for all cases in the given training set."""
for inputs, expected_output in training_set:
self.train(inputs, expected_output, rate)
def check_all(self, training_set):
"""Check whether this Perceptron produces all the correct outputs."""
print self
failures = 0
for inputs, expected_output in training_set:
output = self.evaluate(inputs)
print ' %r -> %r (want %r)' % (inputs, output, expected_output)
if output != expected_output:
failures += 1
return not failures
training_set = [
([1, 0, 0], 1),
([1, 0, 1], 1),
([1, 1, 0], 1),
([1, 1, 1], 0),
([0, 1, 0], 1),
([0, 0, 1], 1),
([0, 1, 1], 1),
([0, 0, 0], 1),
]
perceptron = Perceptron(3)
rate = 0.1
while rate > 1e-9:
if perceptron.check_all(training_set):
print
print 'Success:', perceptron
break
perceptron.train_all(training_set, rate)
rate *= 0.99
The version below has two classes: Perceptron (which produces a floating-point output) and BooleanPerceptron (which produces a Boolean output).
#!/usr/bin/env python
__author__ = 'Ka-Ping Yee <ping@zesty.ca>'
def dot_product(inputs, weights):
return sum(input*weight for input, weight in zip(inputs, weights))
class Perceptron:
def __init__(self, size):
"""The 'size' parameter sets the number of inputs to this Perceptron."""
self.weights = [0.0]*size + [0.0]
def __repr__(self):
"""Display the internal weights of this Perceptron."""
weights = ', '.join('%.3g' % weight for weight in self.weights)
return '<%s %s>' % (self.__class__.__name__, weights)
def evaluate(self, inputs):
"""Evaluate this Perceptron with the given inputs, giving 0 or 1.
'inputs' should be a list of numbers, and the length of the list
should equal the 'size' used to construct this Perceptron."""
return dot_product(self.weights, inputs + [1])
def adjust(self, inputs, rate):
"""Adjust the weights of this Perceptron for the given inputs, using
the given training rate."""
for i, input in enumerate(inputs + [1]):
self.weights[i] += rate*input
def train(self, inputs, expected_output, rate):
"""Train this Perceptron for a single test case."""
output = self.evaluate(inputs)
self.adjust(inputs, rate*(expected_output - output))
def train_all(self, training_set, rate):
"""Train this Perceptron for all cases in the given training set."""
for inputs, expected_output in training_set:
self.train(inputs, expected_output, rate)
def check_all(self, training_set):
"""Check whether this Perceptron produces all the correct outputs."""
print self
failures = 0
for inputs, expected_output in training_set:
output = self.evaluate(inputs)
print ' %r -> %r (want %r)' % (inputs, output, expected_output)
if output != expected_output:
failures += 1
return not failures
class BooleanPerceptron(Perceptron):
def evaluate(self, inputs):
"""Just like Perceptron.evaluate, but apply a threshold."""
return int(Perceptron.evaluate(self, inputs) > 0)
training_set = [
([1, 0, 0], 1),
([1, 0, 1], 1),
([1, 1, 0], 1),
([1, 1, 1], 0),
([0, 1, 0], 1),
([0, 0, 1], 1),
([0, 1, 1], 1),
([0, 0, 0], 1),
]
perceptron = BooleanPerceptron(3)
rate = 0.1
while rate > 1e-9:
if perceptron.check_all(training_set):
print
print 'Success:', perceptron
break
perceptron.train_all(training_set, rate)
rate *= 0.9999