Files
perceptron_ffnn/MlpNetwork.py

72 lines
3.2 KiB
Python

from typing import Tuple, List, Callable, Generator
from import_data import get_test_data_generator, get_training_data_generator, IMAGE_SIZE, print_img_to_console
import numpy as np
class MulticlassPerceptron:
class Perceptron:
def __init__(self, input_size, learn_rate: float = 0.0001):
self.weights = np.random.rand(input_size + 1) * 2 - 1
self.learn_rate = learn_rate
def train(self, data_lbl_pairs: Callable[[], Generator], positive_label: int, iterations: int = 10):
for num_iter in range(iterations):
print(f"Iteration number: {num_iter + 1}")
for i, (x, y) in enumerate(data_lbl_pairs()):
prediction = self.output(x)
label = 1 if y == positive_label else -1
correct = prediction >= 0 and label >= 0 or prediction < 0 and label < 0
if not correct:
self.weights = self.weights + self.learn_rate * label * np.array([1.0] + x)
def output(self, datum):
return np.dot(self.weights, np.array([1.0] + datum))
def get_normalised_weight_array(self):
return [int(x) for x in (((self.weights / np.max(self.weights) + 1) / 2) * 255)]
def __init__(self, input_size: int, num_classes: int, learn_rate: float = 0.001):
self.classifiers = [self.Perceptron(input_size, learn_rate) for _ in range(num_classes)]
def train(self, data_lbl_pairs: Callable[[], Generator], iterations: int = 10):
for i, classifier in enumerate(self.classifiers):
print(f"Training classifier for class {i}...")
classifier.train(data_lbl_pairs, i, iterations)
print()
def output(self, datum: List[int]):
return list(map(lambda x: x.output(datum), self.classifiers))
def prediction(self, datum):
return max(list(range(10)), key=lambda x: self.output(datum)[x])
def view_for_classifier(self, classifier_index: int):
return self.classifiers[classifier_index].get_normalised_weight_array()
def train_and_test_multiclass_perceptron(iterations: int = 5, training_inputs: int = -1, test_inputs: int = -1):
print("Loading data")
training_data_gen = get_training_data_generator(training_inputs)
print("Begin training model!")
model = MulticlassPerceptron(IMAGE_SIZE, 10)
model.train(training_data_gen, iterations)
print("Model successfully trained.")
print("Testing model...")
test_data = list(get_test_data_generator(test_inputs)())
n_correct = sum(model.prediction(x) == y for x, y in test_data)
accuracy = n_correct / len(test_data)
print(f"Accuracy: {accuracy} ({n_correct} correctly classified out of {len(test_data)} total test inputs.)")
for i in range(10):
print_img_to_console(model.view_for_classifier(i))
def make_trained_digit_model(iterations: int = 5, training_inputs: int = 5000, test_inputs: int = 1000):
training_data_gen = get_training_data_generator(training_inputs)
model = MulticlassPerceptron(IMAGE_SIZE, 10)
model.train(training_data_gen, iterations)
return model
if __name__ == "__main__":
train_and_test_multiclass_perceptron()