Skip to content

AIDesigners/Gul

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

32 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Gul

The Python Neural Compiler 'Gul' ('flower' in Urdu) is a generalization of Recurrent Neural Nets, RNN, architecture. The key idea of the generalization is external memories stack which allows flexible assembling of individual neural nets into a polymorphic analyzer that is capable to adjust own shape to the available data on a fly. The structure of NN in Gul is thus defined dynamically as assemble of several rather simple/shallow neural nets. The assembly, in turn, can be of arbitrary size, but as a test example I’ll show how it works with simple assembly of only five nets.

Lets assume that our decision/classification problem is dependent on unstructured data. Let also assume that the given object is described by 3 sentences - Fact_C, Fact_B, Fact_A. Furthermore, the results of semantic analysis indicates that Fact_B and Fact_C uses close language/words and thus likely to describe the same feature (Fact_B is mention later so we assume it is more specific while Fact_C is, probably, more generic). But, as it also follows from the semantic distance analysis, Fact_A is likely to be a distinct characteristic. The scheme of classification process is then described on the left in fig below. To train machine on this irregular/unstructured data we dynamically compile a classification process tree (on the right of the fig).

<img src=https://github.com/AIDesigners/Gul/blob/master/doc/fig1.png /img>

The nets assembly consists of 3 different neural nets (called neural functions in Gul). Initially the fact analyzing routine is called three times to form memories stacks. The routine is a simple three-layered perceptron which is ‘written’ via training. Similarly to function it, however, has a strict signature - it inputs an array of memories, an array of fact representation and outputs an updated array of memories. In other words the fact analyzing perceptron takes existing memories stack (which is zeroes at leaves of the process tree) and a new input fact represented as numpy array. The new knowledge is then integrated into current memories stack via passing of the fact data through neural net so its output is the updated memories stack. This way Fact_C updates empty memories stack, then Fact_B updates memories stack, which was created by analyzing of Fact_C, and Fact_A creates independent branch of memories.

At the second stage the memories about Fact_A and (Fact_B+Fact_C) are merged with second perceptron network, called memories aggregator. It takes two (independent) memories stacks and synthetases a joined one. Although not in this simple example, but memory aggregators can also be nested, similarly to the case of nested fact analyzing calls.

Eventually a memories updates ends up with one memories stack which holds all data extracted from the bag of provided facts. The third neural function, classifier, is applied to resulting memories stack to make a conclusion about the described object.

To compute (or train) the net assembly which is described above, with Gul, one need to execute the simple Pythonic code bellow:


#Define neural functions
nfunct2 = nncp.nf_perceptron(name = "nfunct2", size_in = SIZE_MSTACK,               size_mid = SIZE_N2*2 + 1,           size_out = 1,           trainable = True, dtype = np.float32)
nfunct1 = nncp.nf_perceptron(name = "nfunct1", size_in = SIZE_MSTACK + SIZE_MSTACK, size_mid = SIZE_N1*2 + SIZE_MSTACK, size_out = SIZE_MSTACK, trainable = True, dtype = np.float32)
nfunct0 = nncp.nf_perceptron(name = "nfunct0", size_in = SIZE_MSTACK + SIZE_IN,     size_mid = SIZE_N0*2 + SIZE_MSTACK, size_out = SIZE_MSTACK, trainable = True, dtype = np.float32)

#Define process tree process_tree = nncp.pTree(nncp.NeuralNode, size_mstack = SIZE_MSTACK); process_tree.root = nncp.NeuralNode(SIZE_MSTACK, nfunct2, data = None, nfn_transform_data = None, trainable = True, isRoot = True) process_tree.root.node_add( process_tree.factoryNode(SIZE_MSTACK, nfunct1, data = None, nfn_transform_data = None, trainable = True) ) process_tree.root.nodes[0].node_add( process_tree.factoryNode(SIZE_MSTACK, nfunct0, data = np.asarray(INPUT_B, dtype=nfunct0.dtype), nfn_transform_data = None, trainable = True) ) process_tree.root.nodes[0].nodes[0].node_add( process_tree.factoryNode(SIZE_MSTACK, nfunct0, data = np.asarray(INPUT_C, dtype=nfunct0.dtype), nfn_transform_data = None, trainable = True) ) process_tree.root.nodes[0].node_add( process_tree.factoryNode(SIZE_MSTACK, nfunct0, data = np.asarray(INPUT_A, dtype=nfunct0.dtype), nfn_transform_data = None, trainable = True) )

#Compute net and derivatives (for training) process_tree.calc_v() process_tree.calc_dv(np.array([1./process_tree.root.v[-1]], dtype=process_tree.root.nfunct.dtype))

#Call your solver (PARAMS_NN0, PARAMS_NN1, PARAMS_NN2) = your_NN_solver((PARAMS_NN0, PARAMS_NN1, PARAMS_NN2), (nfunct0.grad, nfunct1.grad, nfunct2.grad))

#Update the net with new parameters nfunct2.set_net(np.asarray(PARAMS_NN2, dtype=np.float32)) nfunct1.set_net(np.asarray(PARAMS_NN1, dtype=np.float32)) nfunct0.set_net(np.asarray(PARAMS_NN0, dtype=np.float32))

Technically Gul is a python package which calls to Caffe C++ bindings to perform actual computations. Because nothing more than NumPy vectors summation is carried out in Python itself during NN surgeries, Gul adds only small overhead to overall computations. On the other hand, it provides all the power of general purpose language for dynamic NN assembling and rich collection of libraries, one to mention is NLTK.

What it can be useful for?

The Gul is designed to deal with unstructured data where one can apply ideas of describing knowledge as processes. Natural language is a perfect examples because it intensively uses trajectories frames speaking about all variety of things. Say, prices rises or market goes down, weather improves or mind blows up and so on… Another potential example is video surveillance or sport observations; in these domains one can use convolution nets to recognize objects or persons and the processes tree framework to classify of what they are doing.

Further plans

Soon I will:

  • add facts representation code with examples.
  • add support of Spark (meanwhile you can install it as we described previously) into Gul so it can natively run on scale.
  • try DIIS optimization method for Gul solver.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages