From b0ade67350d91450c793c5cea2f0ee3e5ca71ac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Csaba=20G=C3=B3r?= Date: Wed, 4 Mar 2020 13:33:27 +0100 Subject: [PATCH] Bugfixes and setup.py --- Readme.md | 10 ++-- brainforge/__init__.py | 2 +- brainforge/gradientcheck/gradientcheck.py | 4 +- brainforge/learner/__init__.py | 2 +- brainforge/learner/abstract_learner.py | 58 ++++++++++++++++------- brainforge/learner/backpropagation.py | 2 +- brainforge/learner/feedback_alignment.py | 4 +- brainforge/learner/local_correlation.py | 4 +- brainforge/util/persistance.py | 4 +- setup.py | 16 +++++++ xperiments/xp_conv.py | 4 +- xperiments/xp_decoupled.py | 6 +-- xperiments/xp_dense.py | 4 +- xperiments/xp_getout.py | 4 +- xperiments/xp_iris_etalon.py | 4 +- xperiments/xp_lstm.py | 4 +- xperiments/xp_mnist.py | 4 +- xperiments/xp_pggymin.py | 4 +- xperiments/xp_pong.py | 4 +- xperiments/xp_qcartpole.py | 6 +-- xperiments/xp_sin.py | 4 +- xperiments/xp_vae.py | 12 ++--- 22 files changed, 104 insertions(+), 62 deletions(-) create mode 100644 setup.py diff --git a/Readme.md b/Readme.md index 9e8abe9..a3873d6 100644 --- a/Readme.md +++ b/Readme.md @@ -277,7 +277,7 @@ implemented: ```python import numpy as np -from brainforge import LayerStack, BackpropNetwork +from brainforge import LayerStack, Backpropagation from brainforge.layers import DenseLayer def input_stream(batchsize=20): @@ -307,7 +307,7 @@ For more complicated tasks, the use of the dataframe library csxdata is suggeste ```python from csxdata import CData -from brainforge import BackpropNetwork +from brainforge import Backpropagation from brainforge.layers import ( DenseLayer, DropOut, Activation, PoolLayer, ConvLayer, Flatten @@ -340,7 +340,7 @@ model.fit(X, Y, batch_size=20, epochs=30, validation=valid, ```python from csxdata import Sequence -from brainforge import BackpropNetwork +from brainforge import Backpropagation from brainforge.layers import DenseLayer, LSTM datapath = "path/to/text/file.txt" @@ -383,7 +383,7 @@ import time import numpy as np from matplotlib import pyplot as plt -from brainforge import BackpropNetwork +from brainforge import Backpropagation from brainforge.layers import DenseLayer, DropOut from brainforge.evolution import Population, to_phenotype @@ -477,7 +477,7 @@ from collections import deque import gym -from brainforge import BackpropNetwork +from brainforge import Backpropagation from brainforge.layers import DenseLayer from brainforge.reinforcement import DQN, agentconfig from brainforge.optimization import RMSprop diff --git a/brainforge/__init__.py b/brainforge/__init__.py index 77b93bf..de6be26 100644 --- a/brainforge/__init__.py +++ b/brainforge/__init__.py @@ -1,6 +1,6 @@ from brainforge.config import set_globals from brainforge.model import LayerStack -from brainforge.learner import BackpropNetwork +from brainforge.learner import Backpropagation from brainforge.learner import NeuroEvolution from brainforge.learner import DirectFeedbackAlignment from brainforge.learner import ExtremeLearningMachine diff --git a/brainforge/gradientcheck/gradientcheck.py b/brainforge/gradientcheck/gradientcheck.py index 0b37dfd..4c3b276 100644 --- a/brainforge/gradientcheck/gradientcheck.py +++ b/brainforge/gradientcheck/gradientcheck.py @@ -2,10 +2,10 @@ from .raw_gradients import analytical_gradients, numerical_gradients from .analyze_difference import analyze_difference_matrices, get_results -from ..learner import BackpropNetwork +from ..learner import Backpropagation -def run(network: BackpropNetwork, X=None, Y=None, epsilon=1e-5, throw=False, display=True): +def run(network: Backpropagation, X=None, Y=None, epsilon=1e-5, throw=False, display=True): if X is None: X = np.random.normal(scale=0.1, size=network.input_shape) if Y is None: diff --git a/brainforge/learner/__init__.py b/brainforge/learner/__init__.py index 0e2ed76..e4b0183 100644 --- a/brainforge/learner/__init__.py +++ b/brainforge/learner/__init__.py @@ -1,4 +1,4 @@ -from .backpropagation import BackpropNetwork +from .backpropagation import Backpropagation from .neuroevolution import NeuroEvolution from .abstract_learner import Learner from .feedback_alignment import DirectFeedbackAlignment diff --git a/brainforge/learner/abstract_learner.py b/brainforge/learner/abstract_learner.py index bdb52ee..edeff8f 100644 --- a/brainforge/learner/abstract_learner.py +++ b/brainforge/learner/abstract_learner.py @@ -15,7 +15,15 @@ def __init__(self, layerstack, cost="mse", name="", **kw): self.age = 0 self.cost = _costs.get(cost) - def fit_generator(self, generator, lessons_per_epoch, epochs=30, metrics=(), validation=(), verbose=1, **kw): + def fit_generator(self, + generator, + lessons_per_epoch, + epochs=30, + metrics=(), + validation=(), + validation_steps=None, + verbose=1, **kw): + metrics = [_metrics.get(metric) for metric in metrics] history = logging.MetricLogs.from_metric_list(lessons_per_epoch, ("cost",), metrics) lstr = len(str(epochs)) @@ -23,20 +31,29 @@ def fit_generator(self, generator, lessons_per_epoch, epochs=30, metrics=(), val if verbose: print("Epoch {:>{w}}/{}".format(epoch, epochs, w=lstr)) epoch_history = self.epoch(generator, updates_per_epoch=lessons_per_epoch, metrics=metrics, - validation=validation, verbose=verbose, **kw) + validation=validation, validation_steps=validation_steps, verbose=verbose, **kw) history.update(epoch_history) return history - def fit(self, X, Y, batch_size=20, epochs=30, metrics=(), validation=(), verbose=1, shuffle=True, **kw): + def fit(self, X, Y, + batch_size=20, + epochs=30, + metrics=(), + validation=(), + validation_steps=None, + verbose=1, + shuffle=True, + **kw): + metrics = [_metrics.get(metric) for metric in metrics] datastream = batch_stream(X, Y, m=batch_size, shuffle=shuffle) - return self.fit_generator(datastream, len(X) // batch_size, epochs, metrics, validation, verbose, **kw) + return self.fit_generator(datastream, len(X) // batch_size, epochs, metrics, validation, validation_steps, + verbose, **kw) - def epoch(self, generator, updates_per_epoch, metrics=(), validation=None, verbose=1, **kw): + def epoch(self, generator, updates_per_epoch, metrics=(), validation=None, validation_steps=None, verbose=1, **kw): metrics = [_metrics.get(metric) for metric in metrics] history = logging.MetricLogs.from_metric_list(updates_per_epoch, ["cost"], metrics) - done = 0 self.layers.learning = True batch_size = 0 @@ -50,8 +67,13 @@ def epoch(self, generator, updates_per_epoch, metrics=(), validation=None, verbo self.layers.learning = False if verbose and validation: - history = self.evaluate(*validation, batch_size=batch_size, metrics=metrics) - history.log(prefix=" ", suffix="") + if type(validation) in (tuple, list): + eval_history = self.evaluate(*validation, batch_size=batch_size, metrics=metrics, verbose=False) + else: + if validation_steps is None: + raise RuntimeError("If validating on a stream, validation_steps must be set to a positive integer.") + eval_history = self.evaluate_stream(validation, validation_steps, metrics, verbose=False) + eval_history.log(prefix=" ", suffix="") if verbose: print() @@ -70,24 +92,28 @@ def evaluate_batch(self, x, y, metrics=()): eval_metrics[str(metric).lower()] = metric(preds, y) / m return eval_metrics - def evaluate(self, X, Y, batch_size=32, metrics=(), verbose=False): - metrics = [_metrics.get(metric) for metric in metrics] - N = X.shape[0] - batch_size = min(batch_size, N) - steps = int(round(N / batch_size)) + def evaluate_stream(self, stream, steps, metrics=(), verbose=False): history = logging.MetricLogs.from_metric_list(steps, ["cost"], metrics) - - for x, y in batch_stream(X, Y, m=batch_size, shuffle=False, infinite=False): + metrics = [_metrics.get(metric) for metric in metrics] + for x, y in stream: eval_metrics = self.evaluate_batch(x, y, metrics) history.record(eval_metrics) if verbose: history.log("\r", end="") - if verbose: print() history.reduce_mean() return history + def evaluate(self, X, Y, batch_size=32, metrics=(), verbose=False): + N = X.shape[0] + batch_size = min(batch_size, N) + steps = int(round(N / batch_size)) + + stream = batch_stream(X, Y, m=batch_size, shuffle=False, infinite=False) + + return self.evaluate_stream(stream, steps, metrics, verbose) + def learn_batch(self, X, Y, metrics=(), **kw) -> dict: raise NotImplementedError diff --git a/brainforge/learner/backpropagation.py b/brainforge/learner/backpropagation.py index a278aef..cb1864f 100644 --- a/brainforge/learner/backpropagation.py +++ b/brainforge/learner/backpropagation.py @@ -4,7 +4,7 @@ from ..optimizers import optimizers, GradientDescent -class BackpropNetwork(Learner): +class Backpropagation(Learner): def __init__(self, layerstack, cost="mse", optimizer="sgd", name="", **kw): super().__init__(layerstack, cost, name, **kw) diff --git a/brainforge/learner/feedback_alignment.py b/brainforge/learner/feedback_alignment.py index 70f8b96..83a5018 100644 --- a/brainforge/learner/feedback_alignment.py +++ b/brainforge/learner/feedback_alignment.py @@ -1,10 +1,10 @@ import numpy as np -from .backpropagation import BackpropNetwork +from .backpropagation import Backpropagation from ..util.typing import white -class DirectFeedbackAlignment(BackpropNetwork): +class DirectFeedbackAlignment(Backpropagation): def __init__(self, layerstack, cost, optimizer, name="", **kw): super().__init__(layerstack, cost, optimizer, name, **kw) diff --git a/brainforge/learner/local_correlation.py b/brainforge/learner/local_correlation.py index a52143f..6638999 100644 --- a/brainforge/learner/local_correlation.py +++ b/brainforge/learner/local_correlation.py @@ -1,10 +1,10 @@ import numpy as np -from .backpropagation import BackpropNetwork +from .backpropagation import Backpropagation from ..metrics import mse -class LocalCorrelationAligment(BackpropNetwork): +class LocalCorrelationAligment(Backpropagation): def backpropagate(self, error): m = len(error) diff --git a/brainforge/util/persistance.py b/brainforge/util/persistance.py index 8cabf34..018f301 100644 --- a/brainforge/util/persistance.py +++ b/brainforge/util/persistance.py @@ -50,7 +50,7 @@ def __getitem__(self, item): def load(capsule): - from ..learner import BackpropNetwork + from ..learner import Backpropagation from ..optimizers import optimizers from ..util.shame import translate_architecture as trsl @@ -58,7 +58,7 @@ def load(capsule): capsule = Capsule.read(capsule) c = capsule - net = BackpropNetwork(input_shape=c["vlayers"][0][0], name=c["vname"]) + net = Backpropagation(input_shape=c["vlayers"][0][0], name=c["vname"]) for layer_name, layer_capsule in zip(c["varchitecture"], c["vlayers"]): if layer_name[:5] == "Input": diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..e5f8f4e --- /dev/null +++ b/setup.py @@ -0,0 +1,16 @@ +from setuptools import setup, find_packages + +long_description = open("Readme.md").read() + +setup( + name='brainforge', + version='0.1.0', + packages=find_packages(), + url='https://github.com/csxeba/brainforge.git', + license='GPLv3', + author='csxeba', + author_email='csxeba@gmail.com', + description='Deep Learning with NumPy only!', + long_description=long_description, + long_description_content_type='text/markdown' +) diff --git a/xperiments/xp_conv.py b/xperiments/xp_conv.py index 4f4c8dd..960b2e1 100644 --- a/xperiments/xp_conv.py +++ b/xperiments/xp_conv.py @@ -1,13 +1,13 @@ from verres.data import MNIST -from brainforge.learner import BackpropNetwork +from brainforge.learner import Backpropagation from brainforge.layers import ConvLayer, PoolLayer, Flatten, Dense, Activation from brainforge import gradientcheck X, Y = MNIST().table("train") X = X[..., 0][:, None, ...] ins, ous = X.shape[1:], Y.shape[1:] -net = BackpropNetwork(input_shape=ins, layerstack=[ +net = Backpropagation(input_shape=ins, layerstack=[ ConvLayer(32, 3, 3, compiled=1), Activation("relu"), ConvLayer(64, 3, 3, compiled=1), diff --git a/xperiments/xp_decoupled.py b/xperiments/xp_decoupled.py index 3bc4a17..d1d7185 100644 --- a/xperiments/xp_decoupled.py +++ b/xperiments/xp_decoupled.py @@ -1,4 +1,4 @@ -from brainforge.learner import BackpropNetwork +from brainforge.learner import Backpropagation from brainforge.layers import Dense from brainforge.optimizers import Momentum from brainforge.util import etalon @@ -36,7 +36,7 @@ def udpate(self, true_delta): def build_net(inshape, outshape): - net = BackpropNetwork(input_shape=inshape, layerstack=[ + net = Backpropagation(input_shape=inshape, layerstack=[ Dense(30, activation="tanh"), Dense(outshape, activation="softmax") ], cost="cxent", optimizer=Momentum(0.01)) @@ -44,7 +44,7 @@ def build_net(inshape, outshape): def build_synth(inshape, outshape): - synth = BackpropNetwork(input_shape=inshape, layerstack=[ + synth = Backpropagation(input_shape=inshape, layerstack=[ Dense(outshape) ], cost="mse", optimizer=Momentum(0.01)) return synth diff --git a/xperiments/xp_dense.py b/xperiments/xp_dense.py index 4188b38..5335f5a 100644 --- a/xperiments/xp_dense.py +++ b/xperiments/xp_dense.py @@ -1,4 +1,4 @@ -from brainforge.learner import BackpropNetwork +from brainforge.learner import Backpropagation from brainforge.layers import Dense from brainforge.gradientcheck import GradientCheck from brainforge.util import etalon @@ -6,7 +6,7 @@ X, Y = etalon inshape, outshape = X.shape[1:], Y.shape[1:] -network = BackpropNetwork(input_shape=inshape, layerstack=[ +network = Backpropagation(input_shape=inshape, layerstack=[ Dense(32, activation="sigmoid", trainable=1), Dense(32, activation="sigmoid", trainable=1), Dense(outshape, activation="linear", trainable=1) diff --git a/xperiments/xp_getout.py b/xperiments/xp_getout.py index bdc16d1..4620b16 100644 --- a/xperiments/xp_getout.py +++ b/xperiments/xp_getout.py @@ -4,13 +4,13 @@ from grund import getout -from brainforge import BackpropNetwork +from brainforge import Backpropagation from brainforge.layers import Dense, Flatten from brainforge.reinforcement import DQN, AgentConfig env = getout.GetOut((10, 10)) agent = DQN( - BackpropNetwork(input_shape=env.neurons_required[0], layerstack=[ + Backpropagation(input_shape=env.neurons_required[0], layerstack=[ Flatten(), Dense(30, activation="tanh"), Dense(env.neurons_required[-1], activation="linear") diff --git a/xperiments/xp_iris_etalon.py b/xperiments/xp_iris_etalon.py index ca3d54e..89898e7 100644 --- a/xperiments/xp_iris_etalon.py +++ b/xperiments/xp_iris_etalon.py @@ -1,5 +1,5 @@ from brainforge.util import etalon -from brainforge import LayerStack, BackpropNetwork +from brainforge import LayerStack, Backpropagation from brainforge.layers import Dense, DropOut @@ -9,5 +9,5 @@ Dense(3, activation="softmax") ]) -net = BackpropNetwork(ls, cost="cxent", optimizer="momentum") +net = Backpropagation(ls, cost="cxent", optimizer="momentum") costs = net.fit(*etalon, epochs=300, validation=etalon, verbose=1) diff --git a/xperiments/xp_lstm.py b/xperiments/xp_lstm.py index c0dd4bf..bea382b 100644 --- a/xperiments/xp_lstm.py +++ b/xperiments/xp_lstm.py @@ -1,6 +1,6 @@ import numpy as np -from brainforge.learner import BackpropNetwork +from brainforge.learner import Backpropagation from brainforge.layers import LSTM, Dense from brainforge.gradientcheck import GradientCheck @@ -11,7 +11,7 @@ X = np.random.randn(*DSHAPE) Y = np.random.randn(*OUTSHP) -net = BackpropNetwork(input_shape=DSHAPE[1:], layerstack=[ +net = Backpropagation(input_shape=DSHAPE[1:], layerstack=[ LSTM(16, activation="tanh", compiled=1), Dense(OUTSHP[1:], activation="linear", trainable=0) ], cost="mse", optimizer="sgd") diff --git a/xperiments/xp_mnist.py b/xperiments/xp_mnist.py index 008bf9d..415b7ad 100644 --- a/xperiments/xp_mnist.py +++ b/xperiments/xp_mnist.py @@ -1,12 +1,12 @@ from verres.data import inmemory -from brainforge import BackpropNetwork +from brainforge import Backpropagation from brainforge.layers import Dense, Flatten mnist = inmemory.MNIST() (lX, lY), (tX, tY) = mnist.table("train", shuffle=True), mnist.table("val", shuffle=False) -ann = BackpropNetwork(input_shape=lX.shape[1:], layerstack=[ +ann = Backpropagation(input_shape=lX.shape[1:], layerstack=[ Flatten(), Dense(64, activation="tanh"), Dense(10, activation="softmax") diff --git a/xperiments/xp_pggymin.py b/xperiments/xp_pggymin.py index 594ef9c..d3d2701 100644 --- a/xperiments/xp_pggymin.py +++ b/xperiments/xp_pggymin.py @@ -5,7 +5,7 @@ from matplotlib import pyplot -from brainforge.learner import BackpropNetwork +from brainforge.learner import Backpropagation from brainforge.layers import Dense from brainforge.optimizers import Momentum from brainforge.reinforcement import PG, AgentConfig @@ -15,7 +15,7 @@ def get_agent(): - brain = BackpropNetwork(input_shape=env.observation_space.shape, layerstack=[ + brain = Backpropagation(input_shape=env.observation_space.shape, layerstack=[ Dense(nactions, activation="softmax") ], cost="cxent", optimizer=Momentum(eta=0.001)) return brain diff --git a/xperiments/xp_pong.py b/xperiments/xp_pong.py index 5f3bd5d..758333e 100644 --- a/xperiments/xp_pong.py +++ b/xperiments/xp_pong.py @@ -3,7 +3,7 @@ import gym import numpy as np -from brainforge import BackpropNetwork +from brainforge import Backpropagation from brainforge.layers import Dense from brainforge.reinforcement import PG, AgentConfig @@ -32,7 +32,7 @@ def ds(image): nactions = env.action_space.n stateshape = 6400 print("Pong stateshape =", stateshape) -brain = BackpropNetwork(input_shape=stateshape, layerstack=[ +brain = Backpropagation(input_shape=stateshape, layerstack=[ Dense(200, activation="tanh"), Dense(nactions, activation="softmax") ], cost="cxent", optimizer="adam") diff --git a/xperiments/xp_qcartpole.py b/xperiments/xp_qcartpole.py index ff07b33..17d3920 100644 --- a/xperiments/xp_qcartpole.py +++ b/xperiments/xp_qcartpole.py @@ -3,7 +3,7 @@ import numpy as np import gym -from brainforge.learner import BackpropNetwork +from brainforge.learner import Backpropagation from brainforge.layers import Dense, ClockworkLayer from brainforge.optimizers import RMSprop from brainforge.reinforcement import AgentConfig, DDQN as AgentType @@ -14,7 +14,7 @@ def QannRecurrent(): - brain = BackpropNetwork(env.observation_space.shape, layers=[ + brain = Backpropagation(env.observation_space.shape, layers=[ ClockworkLayer(120, activation="tanh"), Dense(60, activation="relu"), Dense(nactions, activation="linear") @@ -23,7 +23,7 @@ def QannRecurrent(): def QannDense(): - brain = BackpropNetwork(input_shape=env.observation_space.shape, layerstack=[ + brain = Backpropagation(input_shape=env.observation_space.shape, layerstack=[ Dense(24, activation="tanh"), Dense(nactions, activation="linear") ], cost="mse", optimizer=RMSprop(eta=0.0001)) diff --git a/xperiments/xp_sin.py b/xperiments/xp_sin.py index 44e63c6..8c384c3 100644 --- a/xperiments/xp_sin.py +++ b/xperiments/xp_sin.py @@ -2,7 +2,7 @@ from matplotlib import pyplot as plt -from brainforge.learner import BackpropNetwork +from brainforge.learner import Backpropagation from brainforge.layers import Dense np.random.seed(1234) @@ -21,7 +21,7 @@ tX += np.random.randn(*tX.shape) / np.sqrt(tX.size*0.25) -net = BackpropNetwork([Dense(120, activation="tanh"), +net = Backpropagation([Dense(120, activation="tanh"), Dense(120, activation="tanh"), Dense(1, activation="linear")], input_shape=1, optimizer="adam") diff --git a/xperiments/xp_vae.py b/xperiments/xp_vae.py index 497dee0..a104ab7 100644 --- a/xperiments/xp_vae.py +++ b/xperiments/xp_vae.py @@ -2,7 +2,7 @@ from matplotlib import pyplot as plt from verres.data import inmemory -from brainforge import LayerStack, BackpropNetwork +from brainforge import LayerStack, Backpropagation from brainforge.layers.abstract_layer import LayerBase, NoParamMixin from brainforge.layers import Dense from brainforge.optimizers import Adam @@ -54,13 +54,13 @@ def derivative(self, mean, log_variance): class VAE: def __init__(self, Z): - self.encoder = BackpropNetwork([Dense(60, activation="relu"), + self.encoder = Backpropagation([Dense(60, activation="relu"), Dense(30, activation="relu")], optimizer=Adam(1e-4)) - self.mean_z = BackpropNetwork(input_shape=30, layerstack=[Dense(Z)], optimizer=Adam(1e-4)) - self.stdev_z = BackpropNetwork(input_shape=30, layerstack=[Dense(Z)], optimizer=Adam(1e-4)) - self.sampler = BackpropNetwork(input_shape=Z, layerstack=[Sampler()]) - self.decoder = BackpropNetwork(input_shape=Z, layerstack=[Dense(30, activation="relu"), + self.mean_z = Backpropagation(input_shape=30, layerstack=[Dense(Z)], optimizer=Adam(1e-4)) + self.stdev_z = Backpropagation(input_shape=30, layerstack=[Dense(Z)], optimizer=Adam(1e-4)) + self.sampler = Backpropagation(input_shape=Z, layerstack=[Sampler()]) + self.decoder = Backpropagation(input_shape=Z, layerstack=[Dense(30, activation="relu"), Dense(60, activation="relu"), Dense(784, activation="linear")], optimizer=Adam(1e-4))