Here is a small tutorial on extending Python in C: ExtendingPython. Feel free to add or edit. -Doug
Most of the changes I was planning on making have been made. Conx is still open to tweaking and bug fixes or new suggestions. Here's a change list that documents what changes have been made.
Your Bugs or Suggestions
Change List
-
Adopted Python idioms where appropriate. ex. for i in range(len(<list of objects>)) becomes for item in <list of objects>
-
Changes some attribute names. ex. Network.input -> Network.inputs, Network.output -> Network.targets, Network.connection -> Network.connections
-
Changes some method names. Where possible the old method names are still around for compatibility. ex. Network.setOutputs() -> Network.setTargets(), but Network.setOutputs() is still around.
-
Fixed and modified many file IO methods in the Network class. ex. Added Network.patternVector() so that inputs or targets read from a file can be converted back into patterns.
-
Added Network.addPattern() and Network.delPattern() which are safer than Network.setPattern() which might unknowingly delete a previous pattern.
-
Modified exceptions to be more detailed. Added exception extension classes, LayerError, NetworkError, and SRNError. These extend AttributeError (most errors are due to attribute problems). Additionally, exceptions return a tuple with the first item being a string describing the problem and the second being the values of the offending variable(s).
-
Organized methods according to function for easier browsing. Included comments describing each group of methods.
-
Added doc strings to all methods. Pydoc will generate documentation based on these doc strings.
-
Eliminated all counter attributes describing list attributes where len(<list>) is a viable substitute. I'm assuming len() for a listtype in python is implemented in constant time but I have no documentation for this. If not, this is easy to change back. Using len(<list>) is safer.
-
Moved some methods into SRN that were related to prediction and sequencing that weren't alread there.
-
SRN class now has addContext() method. This is similar to Network.add() but takes a Layer instance argument and an option hidden layer name. Call addContext() when adding a context layer associated with a hidden layer (default 'hidden').
-
addContext() adds the layer to the network and also to a dictionary of (hidden layer name, context layer reference) items.
-
Added SRN.copyHiddenToContext() which copies hidden layer activations to context layers automatically for all context layers added using addContext.
-
Added more testing code with emphasis on exceptions and file IO.
-
Added a method verifyArchitecture() to Network. verifyArchitecture() is called in train(). propagate() no longer checks to make sure there is a valid network. verifyArchitecture() must be called to check this.
-
Added testing code for verifyArchitecture() at the end of conx.
Previous Changes
-
Removed SRN specific code from Network class. (Sequencing and prediction)
-
Added activationSet and targetSet flags to Layer class.
-
Should targetSet flag have to be reset before copying or setting another target.
-
Added verifyInputs() to propagate() for error checking.
-
Added verifyTargets() to backprop() for error checking.
-
Added many exceptions.
Most Recent Changes
-
Inputs and targets can be passed to step() as dictionary arguments in the form: <layer name> = <input/target list>
-
The step() method when called from SRN copies context to hidden automatically or clears context depending on the argument initContext = {0, 1}.
-
Fixed plugin NN brains.
-
Activations between 0-1 produce warning
-
Targets between 0-1 throw exception
-
Checks arguments to setInputs and setOutputs [[num,num,..],[...],...]
-
step() does not increment epoch
-
addSRNLayer -> addThreeLayers
-
Reimplemented target check for multiple targets as warning
-
Bured copyHiddenToContext() in backprop()
-
New type "kind" for layers
-
Added prop_from() method
-
connect() inforces layer and connection order
-
Weight matrix problem (getWeights) fixed
-
remove symmetric support
Numeric Conx
Conx now employs Numeric functions wherever possible. The speed of Conx should be noticably faster. I would estimate that moving Conx completely into C may make the code faster yet by a factor of two or more, but using Numeric functions in Python preserves the ease of extensibility that Python offers while now running at a reasonable speed.
Road Map to C
After doing more research on Friday I have discovered two options for moving conx code to C(++). If preserving the OO structure of the program is important then Boost.Python is probably the way to go. This is sort of like SWIG for C++ and would hopefully allow easy implementation of Python classes in C++. The second option is to create a Network type in C exclusively. This would involve taking all the core functionality to C code (not just single methods as I was trying before). The benefit is that those methods would become C code operating on C data structures, eliminating the overhead and providing the best optimization. We could then wrap this new type in a class that would provide some of the functionality (error checking etc...) left out of the C code and subclass it to create SRN specific code. The Layer and Connection classes would no longer exist, being folded into the Network type implementation.
C++ and Boost Pros
-
Possibly using existing C++ code (early conx prototype)
-
Preserve OO coding paradigm
-
Possibly translate C++ classes directly to Python for easy extensibility
C++ and Boost Cons
-
I do not know how to program in C++
-
Boost may not provide an easy translation from C++ to Python and I have no way of evaluating this
-
Some extensibility issues may not be easily resolvable without modifying C++ code
-
Not the standard approach so less examples of use
-
Nonstandard installation
C Type Extension Pros
-
I can program in C
-
Python C API (usable in C++)
-
Doesn't depend on 3rd party library (only Python API)
-
This is the standard method of optimization so plenty of examples
C Type Extension Cons
-
Difficulty maintaining a flexible code base
-
Lisa mentioned the following example: Suppose we wanted to change the activation function or have different activation functions for different layers. A hard coded C type would not allow this (from Python at least).
-
For the above, we can provide function call backs to python in both C and C++ to make the code base more extensible in python.
-
Difficult to predict what future features may be excluded (not easily extensible)
