Esempio n. 1
0
    def test_propogate_signal(self):
        """Check that signal propogation occurs properly for all edges.

        This is standard iterable return NOT YIELD, applied to each edge.
        """
        some_signal = np.array([1, 2, 3])
        graph = nx.MultiDiGraph()
        graph.add_node("x", node=IO())  # from this node
        graph.add_node("a", node=IO())
        graph.add_node("y", node=IO())
        graph.add_edge("x", "y")  # no signals yet
        graph.add_edge("x", "y")
        graph.add_edge("x", "y")
        graph.add_edge("a", "y")  # should never recieve a signal
        f = Firing()
        f._propogate_signal(graph=graph,
                            node_name="x",
                            signal_name="fwd",
                            signal=some_signal)
        # check signal has been applied to each individually
        for edge in graph.edges("x", data=True):
            np.testing.assert_array_almost_equal(edge[2]["fwd"],
                                                 some_signal,
                                                 decimal=1,
                                                 verbose=True)
        # check not applied to seperate node
        for edge in graph.edges("a", data=True):
            self.assertEqual(edge[2].get("fwd"), None)
Esempio n. 2
0
def cnn_regressor(data_shape, filter_length, stride=1):
    """Get simple 1 Layer 1D-CNN for time-series regression.

    :arg data_shape: The shape of the input data in the shape format of
     (timesteps, features)
    :type data_shape: tuple
    :arg filter_length: The length of the 1D CNN filter which to CC over data
    :type filter_length: int
    :arg stride: The steps between filters (default = 1)
    :type stride: int
    :return: neural network graph
    :rtype: networkx.MultiDigGraph
    """
    graph = nx.MultiDiGraph()
    data_shape = data_shape
    filter_shape = (filter_length, data_shape[1])
    stride = [stride, data_shape[1]]
    # creating window expression so we know how many nodes we need
    windows = CC().windex(data_shape, filter_shape, stride)

    # INPUTS
    graph.add_node("x", group=0, node=Rotate())
    graph.add_node("y", group=0, node=Rotate())

    # 1D CNN/ CC
    graph.add_node("1D-CC",
                   group=1,
                   node=CC(weights=filter_shape, stride=stride, bias=0))
    graph.add_edge("x", "1D-CC")
    graph.add_node("CC-dequeue", group=6, node=Dequeue())
    graph.add_edge("1D-CC", "CC-dequeue")
    graph.add_node("CC-enqueue", group=6, node=Enqueue(length=len(windows)))
    for i in range(len(windows)):
        graph.add_node("CC-sop-{}".format(i), group=1, node=Sum())
        graph.add_edge("CC-dequeue", "CC-sop-{}".format(i))
        graph.add_edge("CC-sop-{}".format(i), "CC-enqueue")
    graph.add_node("CNN-acti", group=1, node=RELU())
    graph.add_edge("CC-enqueue", "CNN-acti")

    # DENSE
    graph.add_node("Dense", group=2, node=ANN(weights=(len(windows), )))
    graph.add_edge("CNN-acti", "Dense", weight=ANN().cost)
    graph.add_node("Dense-acti", group=2, node=RELU())
    graph.add_edge("Dense", "Dense-acti")
    graph.add_node("Decrypt", group=5, node=Decrypt())
    graph.add_edge("Dense-acti", "Decrypt")
    graph.add_node("Selector", group=6, node=Selector(backward=[1, 0]))
    graph.add_edge("Decrypt", "Selector")

    # LOSS
    graph.add_node("MSE", group=3, node=MSE())
    graph.add_edge("Selector", "MSE", weight=MSE().cost)
    graph.add_edge("y", "MSE", weight=MSE().cost)

    # OUTPUT
    graph.add_node("y_hat", group=4, node=IO())
    graph.add_edge("Selector", "y_hat", weight=IO().cost)

    return graph
Esempio n. 3
0
 def test_forward(self):
     """Check IO maps input to output."""
     i = IO()
     data = self.data
     out = i.forward(data)
     np.testing.assert_array_almost_equal(out,
                                          data,
                                          decimal=2,
                                          verbose=True)
Esempio n. 4
0
 def test_backward(self):
     """Check IO maps gradients to input."""
     i = IO()
     data = self.data
     i.forward(data)
     out = i.backward(data)
     np.testing.assert_array_almost_equal(out,
                                          data,
                                          decimal=2,
                                          verbose=True)
Esempio n. 5
0
    def test_get_signal_one(self):
        """Check get single signal is working as expected.

        This includes single edges which should not be in a meta container.
        """
        some_signal = np.array([1, 2, 3])
        graph = nx.MultiDiGraph()
        graph.add_node("x", node=IO())
        graph.add_node("y", node=IO())  # from this node
        graph.add_edge("x", "y", fwd=some_signal)
        f = Firing()
        signal = f._get_signal(graph=graph, node_name="y", signal_name="fwd")
        # should return just the input without meta container
        np.testing.assert_array_almost_equal(signal,
                                             some_signal,
                                             decimal=1,
                                             verbose=True)
Esempio n. 6
0
 def test_harvest(self):
     """Check that probes are harvesting signals."""
     some_signal = np.array([1, 2, 3])
     graph = nx.MultiDiGraph()
     graph.add_node("x", node=IO())
     graph.add_node("a", node=IO())
     graph.add_node("y", node=IO())  # from this node
     graph.add_edge("x", "y", forward=some_signal)
     graph.add_edge("x", "y", forward=some_signal)
     graph.add_edge("x", "y", forward=some_signal)
     graph.add_edge("a", "y", forward=some_signal)
     f = Firing(graph=graph)
     crop = f.harvest(["y", "y"])
     truth = np.broadcast_to(some_signal, shape=(4, 3))
     for (_, signal) in crop:
         np.testing.assert_array_almost_equal(signal,
                                              truth,
                                              decimal=1,
                                              verbose=True)
Esempio n. 7
0
    def test_get_signal_none(self):
        """Check get non-existant signal is working as expected.

        If the node does not have all of its inputs then it is not ready.
        So getsignal should return None as the signal is incomplete.
        """
        # create a graph with 3 parallel edges from one node and one other
        some_signal = np.array([1, 2, 3])
        graph = nx.MultiDiGraph()
        graph.add_node("x", node=IO())
        graph.add_node("a", node=IO())
        graph.add_node("y", node=IO())  # from this node
        graph.add_edge("x", "y", fwd=some_signal)
        graph.add_edge("x", "y")  # some missing signal
        graph.add_edge("x", "y", fwd=some_signal)
        graph.add_edge("a", "y", fwd=some_signal)
        f = Firing()
        signal = f._get_signal(graph=graph, node_name="y", signal_name="fwd")
        self.assertEqual(signal, None)
Esempio n. 8
0
    def test_propogate_signal_yield(self):
        """Check that propogate signal works properly with yield.

        If the signal is of type generator/ yield it should map each output
        in order with the graph edges. Thus the edges can be different to one
        another.
        """
        def yielder():
            i = 0  # np.array([0]) <- would return by reference
            while True:
                yield i
                i += 1

        some_signal = yielder()  # as generator
        graph = nx.MultiDiGraph()
        graph.add_node("x", node=IO())  # from this node
        graph.add_node("a", node=IO())
        graph.add_node("y", node=IO())
        graph.add_edge("x", "y")  # no signals yet
        graph.add_edge("x", "y")
        graph.add_edge("x", "y")
        graph.add_edge("x", "DrWho?")  # checking works with non yield too
        graph.add_edge("a", "y")  # should never recieve a signal
        f = Firing()
        f._propogate_signal(graph=graph,
                            node_name="x",
                            signal_name="fwd",
                            signal=some_signal)
        # check signal has been applied to each individually
        truth = yielder()
        for (_, _, edge) in graph.edges("x", data=True):
            np.testing.assert_array_almost_equal(edge["fwd"],
                                                 next(truth),
                                                 decimal=1,
                                                 verbose=True)

        # check not applied to seperate node
        for edge in graph.edges("a", data=True):
            self.assertEqual(edge[2].get("fwd"), None)
Esempio n. 9
0
    def test_get_signal_many(self):
        """Check get multi signal is working as expected.

        This includes considering parallel edges, and standard multi edges.
        """
        # create a graph with 3 parallel edges from one node and one other
        some_signal = np.array([1, 2, 3])
        graph = nx.MultiDiGraph()
        graph.add_node("x", node=IO())
        graph.add_node("a", node=IO())
        graph.add_node("y", node=IO())  # from this node
        graph.add_edge("x", "y", fwd=some_signal)
        graph.add_edge("x", "y", fwd=some_signal)
        graph.add_edge("x", "y", fwd=some_signal)
        graph.add_edge("a", "y", fwd=some_signal)
        f = Firing()
        signal = f._get_signal(graph=graph, node_name="y", signal_name="fwd")
        truth = np.broadcast_to(some_signal, shape=(4, 3))
        # should return all inputs in meta container of shape (4,3) here
        np.testing.assert_array_almost_equal(signal,
                                             truth,
                                             decimal=1,
                                             verbose=True)
Esempio n. 10
0
 def test_propogate_none(self):
     """Check that signal propogation does not occur when signal=None."""
     some_signal = None
     graph = nx.MultiDiGraph()
     graph.add_node("x", node=IO())  # from this node
     graph.add_node("a", node=IO())
     graph.add_node("y", node=IO())
     graph.add_edge("x", "y")  # no signals yet
     graph.add_edge("x", "y")
     graph.add_edge("x", "y")
     graph.add_edge("a", "y")  # should never recieve a signal
     f = Firing()
     f._propogate_signal(graph=graph,
                         node_name="x",
                         signal_name="fwd",
                         signal=some_signal)
     # check signal has not been applied to each edge
     for edge in graph.edges("x", data=True):
         with self.assertRaises(KeyError):
             edge[2]["fwd"]
     # check not applied to seperate node
     for edge in graph.edges("a", data=True):
         self.assertEqual(edge[2].get("fwd"), None)
Esempio n. 11
0
def cnn_classifier(k):
    """Get simple 1 Layer CNN, with K number of densenets -> softmax -> CCE."""
    graph = nx.MultiDiGraph()
    classes = np.arange(k)

    # add nodes to graph with names (for easy human referencing),
    # and objects for what those nodes are
    graph.add_node("x", group=0, node=Rotate())

    data_shape = (28, 28)
    cnn_weights_shape = (6, 6)
    stride = [4, 4]
    windows = CC().windex(data_shape, cnn_weights_shape, stride)

    # CONSTRUCT CNN
    # with intermediary decrypted sum to save on some complexity later
    graph.add_node("CC-products",
                   group=1,
                   node=CC(weights=cnn_weights_shape, stride=stride, bias=0))
    graph.add_edge("x", "CC-products")
    graph.add_node("CC-dequeue", group=6, node=Dequeue(length=len(windows)))
    graph.add_edge("CC-products", "CC-dequeue")
    graph.add_node("CC-enqueue", group=6, node=Enqueue(length=len(windows)))
    for i in range(len(windows)):
        graph.add_node("Rotate-{}".format(i),
                       group=5,
                       node=Rotate(axis=1, flatten=True))
        graph.add_edge("CC-dequeue", "Rotate-{}".format(i))
        graph.add_node("CC-sop-{}".format(i), group=1, node=Sum())
        graph.add_edge("Rotate-{}".format(i),
                       "CC-sop-{}".format(i),
                       weight=Sum().cost)
        graph.add_edge("CC-sop-{}".format(i), "CC-enqueue")
    graph.add_node("CNN-RELU", group=1, node=RELU(q=10))
    graph.add_edge("CC-enqueue", "CNN-RELU")
    graph.add_node("CNN-distribute", group=6, node=Distributor())
    graph.add_edge("CNN-RELU", "CNN-distribute")
    # graph.add_edge("CNN-enqueue", "CNN-activation", weight=RELU().cost)

    # CONSTRUCT DENSE FOR EACH CLASS
    # we want to get the network to regress some prediction one for each class
    graph.add_node("Dense-enqueue", group=6, node=Enqueue(length=k))
    for i in classes:
        graph.add_node("Dense-{}".format(i),
                       group=2,
                       node=ANN(weights=(len(windows), )))
        graph.add_edge("CNN-distribute", "Dense-{}".format(i))
        graph.add_node("Dense-RELU-{}".format(i), group=2, node=RELU(q=10))
        graph.add_edge("Dense-{}".format(i), "Dense-RELU-{}".format(i))
        graph.add_edge("Dense-RELU-{}".format(i), "Dense-enqueue")
    graph.add_node("Decrypt", group=5, node=Decrypt())
    graph.add_edge("Dense-enqueue", "Decrypt")

    # CONSTRUCT SELECTOR TO SELECT COMPUTATIONAL CIRCUITS
    # we need to be able to select different computational circuits depending
    # on the receptor so we can say infer, or train, and so we can also
    # selectiveley backpropagate through only one circuit and ignore the other
    graph.add_node("Selector", group=6, node=Selector(backward=[1, 0]))
    graph.add_edge("Decrypt", "Selector")

    # CONSTRUCT CLASSIFIER
    # we want to turn the dense outputs into classification probabilities
    # using softmax and how wrong / right we are using Categorical
    # Cross-Entropy(CCE) as our loss function
    graph.add_node("Softmax", group=3, node=Softmax())
    graph.add_edge("Selector", "Softmax")
    # graph.add_edge("Dense-enqueue", "Softmax", weight=Softmax().cost)
    graph.add_node("Loss-CCE", group=3, node=CCE())
    graph.add_edge("Softmax", "Loss-CCE", weight=3)
    graph.add_node("One-hot-encoder",
                   group=0,
                   node=OneHotEncode(length=len(classes)))
    graph.add_edge("One-hot-encoder", "Loss-CCE", weight=0)
    graph.add_node("y", group=0, node=IO())
    graph.add_edge("y", "One-hot-encoder", weight=OneHotEncode().cost)

    graph.add_node("Argmax", group=4, node=Argmax())
    graph.add_edge("Selector", "Argmax")
    # graph.add_edge("Dense-enqueue", "Argmax", weight=Argmax().cost)
    graph.add_node("One-hot-decoder", group=4, node=OneHotDecode())
    graph.add_edge("Argmax", "One-hot-decoder", weight=OneHotDecode().cost)
    graph.add_node("y_hat", group=4, node=IO())
    graph.add_edge("One-hot-decoder", "y_hat", weight=0)
    return graph
Esempio n. 12
0
 def test_init(self):
     """Check IO initialises properly."""
     i = IO()
     self.assertIsInstance(i, IO)