├── LICENSE ├── README.md ├── image_phase_vs_magnitude.ipynb ├── iris_dataset └── iris.csv ├── network_boolean.ipynb ├── network_mnist.ipynb ├── single_neuron-periodic-iris.ipynb ├── single_neuron-periodic-mnist.ipynb ├── single_neuron-periodic.ipynb ├── single_neuron.ipynb └── test_image └── test.jpg /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # complex_valued_neuralnetwork -------------------------------------------------------------------------------- /iris_dataset/iris.csv: -------------------------------------------------------------------------------- 1 | Type,PW,PL,SW,SL 2 | 0,2,14,33,50 3 | 1,24,56,31,67 4 | 1,23,51,31,69 5 | 0,2,10,36,46 6 | 1,20,52,30,65 7 | 1,19,51,27,58 8 | 2,13,45,28,57 9 | 2,16,47,33,63 10 | 1,17,45,25,49 11 | 2,14,47,32,70 12 | 0,2,16,31,48 13 | 1,19,50,25,63 14 | 0,1,14,36,49 15 | 0,2,13,32,44 16 | 2,12,40,26,58 17 | 1,18,49,27,63 18 | 2,10,33,23,50 19 | 0,2,16,38,51 20 | 0,2,16,30,50 21 | 1,21,56,28,64 22 | 0,4,19,38,51 23 | 0,2,14,30,49 24 | 2,10,41,27,58 25 | 2,15,45,29,60 26 | 0,2,14,36,50 27 | 1,19,51,27,58 28 | 0,4,15,34,54 29 | 1,18,55,31,64 30 | 2,10,33,24,49 31 | 0,2,14,42,55 32 | 1,15,50,22,60 33 | 2,14,39,27,52 34 | 0,2,14,29,44 35 | 2,12,39,27,58 36 | 1,23,57,32,69 37 | 2,15,42,30,59 38 | 1,20,49,28,56 39 | 1,18,58,25,67 40 | 2,13,44,23,63 41 | 2,15,49,25,63 42 | 2,11,30,25,51 43 | 1,21,54,31,69 44 | 1,25,61,36,72 45 | 2,13,36,29,56 46 | 1,21,55,30,68 47 | 0,1,14,30,48 48 | 0,3,17,38,57 49 | 2,14,44,30,66 50 | 0,4,15,37,51 51 | 2,17,50,30,67 52 | 1,22,56,28,64 53 | 1,15,51,28,63 54 | 2,15,45,22,62 55 | 2,14,46,30,61 56 | 2,11,39,25,56 57 | 1,23,59,32,68 58 | 1,23,54,34,62 59 | 1,25,57,33,67 60 | 0,2,13,35,55 61 | 2,15,45,32,64 62 | 1,18,51,30,59 63 | 1,23,53,32,64 64 | 2,15,45,30,54 65 | 1,21,57,33,67 66 | 0,2,13,30,44 67 | 0,2,16,32,47 68 | 1,18,60,32,72 69 | 1,18,49,30,61 70 | 0,2,12,32,50 71 | 0,1,11,30,43 72 | 2,14,44,31,67 73 | 0,2,14,35,51 74 | 0,4,16,34,50 75 | 2,10,35,26,57 76 | 1,23,61,30,77 77 | 2,13,42,26,57 78 | 0,1,15,41,52 79 | 1,18,48,30,60 80 | 2,13,42,27,56 81 | 0,2,15,31,49 82 | 0,4,17,39,54 83 | 2,16,45,34,60 84 | 2,10,35,20,50 85 | 0,2,13,32,47 86 | 2,13,54,29,62 87 | 0,2,15,34,51 88 | 2,10,50,22,60 89 | 0,1,15,31,49 90 | 0,2,15,37,54 91 | 2,12,47,28,61 92 | 2,13,41,28,57 93 | 0,4,13,39,54 94 | 1,20,51,32,65 95 | 2,15,49,31,69 96 | 2,13,40,25,55 97 | 0,3,13,23,45 98 | 0,3,15,38,51 99 | 2,14,48,28,68 100 | 0,2,15,35,52 101 | 1,25,60,33,63 102 | 2,15,46,28,65 103 | 0,3,14,34,46 104 | 2,18,48,32,59 105 | 2,16,51,27,60 106 | 1,18,55,30,65 107 | 0,5,17,33,51 108 | 1,22,67,38,77 109 | 1,21,66,30,76 110 | 1,13,52,30,67 111 | 2,13,40,28,61 112 | 2,11,38,24,55 113 | 0,2,14,34,52 114 | 1,20,64,38,79 115 | 0,6,16,35,50 116 | 1,20,67,28,77 117 | 2,12,44,26,55 118 | 0,3,14,30,48 119 | 0,2,19,34,48 120 | 1,14,56,26,61 121 | 0,2,12,40,58 122 | 1,18,48,28,62 123 | 2,15,45,30,56 124 | 0,2,14,32,46 125 | 0,4,15,44,57 126 | 1,24,56,34,63 127 | 1,16,58,30,72 128 | 1,21,59,30,71 129 | 1,18,56,29,63 130 | 2,12,42,30,57 131 | 1,23,69,26,77 132 | 2,13,56,29,66 133 | 0,2,15,34,52 134 | 2,10,37,24,55 135 | 0,2,15,31,46 136 | 1,19,61,28,74 137 | 0,3,13,35,50 138 | 1,18,63,29,73 139 | 2,15,47,31,67 140 | 2,13,41,30,56 141 | 2,13,43,29,64 142 | 1,22,58,30,65 143 | 0,3,14,35,51 144 | 2,14,47,29,61 145 | 1,19,53,27,64 146 | 0,2,16,34,48 147 | 1,20,50,25,57 148 | 2,13,40,23,55 149 | 0,2,17,34,54 150 | 1,24,51,28,58 151 | 0,2,15,37,53 152 | -------------------------------------------------------------------------------- /network_boolean.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 26, 6 | "metadata": { 7 | "collapsed": false 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "# neural network of many complex valued neurons in 3 layers\n", 12 | "import numpy" 13 | ] 14 | }, 15 | { 16 | "cell_type": "code", 17 | "execution_count": 27, 18 | "metadata": { 19 | "collapsed": false 20 | }, 21 | "outputs": [], 22 | "source": [ 23 | "class neuralNetwork:\n", 24 | " \n", 25 | " def __init__(self, inputnodes, hiddennodes, outputnodes, cats, periods):\n", 26 | " # set number of nodes in each input, hidden, output layer\n", 27 | " self.inodes = inputnodes + 1 # increament for bias node\n", 28 | " self.hnodes = hiddennodes\n", 29 | " self.onodes = outputnodes\n", 30 | " \n", 31 | " # link weight matrices, wih and who\n", 32 | " # weights inside the arrays are w_i_j, where link is from node i to node j in the next layer\n", 33 | " # w11 w21\n", 34 | " # w12 w22 etc \n", 35 | " self.wih = numpy.random.uniform(-1.0, 1.0, (self.hnodes, self.inodes))\n", 36 | " self.wih = numpy.array(self.wih, ndmin=2, dtype='complex128')\n", 37 | " self.wih += 1j * numpy.random.uniform(-1.0, 1.0, (self.hnodes, self.inodes))\n", 38 | " \n", 39 | " self.who = numpy.random.uniform(-1.0, 1.0, (self.onodes, self.hnodes))\n", 40 | " self.who = numpy.array(self.who, ndmin=2, dtype='complex128')\n", 41 | " self.who += 1j * numpy.random.random((self.onodes, self.hnodes))\n", 42 | " \n", 43 | " # number of output class categories\n", 44 | " self.categories = cats\n", 45 | " \n", 46 | " # todo periodicity\n", 47 | " self.periodicity = periods\n", 48 | " pass\n", 49 | " \n", 50 | " def z_to_class(self, z):\n", 51 | " # first work out the angle, but shift angle from [-pi/2, +pi.2] to [0,2pi]\n", 52 | " angle = numpy.mod(numpy.angle(z) + 2*numpy.pi, 2*numpy.pi)\n", 53 | " # from angle to category\n", 54 | " p = int(numpy.floor (self.categories * angle / (2*numpy.pi)))\n", 55 | " return p\n", 56 | "\n", 57 | " def class_to_angle(self, p):\n", 58 | " # class to angle, using bisector\n", 59 | " angle = ((p + 0.5) / self.categories) * 2 * numpy.pi\n", 60 | " return angle\n", 61 | " \n", 62 | " def status(self):\n", 63 | " print (\"self.wih = \", self.wih)\n", 64 | " print (\"self.who = \", self.who)\n", 65 | " pass\n", 66 | "\n", 67 | " def query(self, inputs_list):\n", 68 | " # add bias input\n", 69 | " inputs_list.append(1.0)\n", 70 | " \n", 71 | " # convert input to complex\n", 72 | " inputs = numpy.array(inputs_list, ndmin=2, dtype='complex128').T\n", 73 | " print(\"inputs = \\n\", inputs)\n", 74 | " \n", 75 | " # signal into hidden layer\n", 76 | " hidden_inputs = numpy.dot(self.wih, inputs)\n", 77 | " #print(\"hidden_inputs = \", hidden_inputs)\n", 78 | " #signal out of hidden layer\n", 79 | " hidden_outputs = numpy.exp(1j * numpy.angle(hidden_inputs))\n", 80 | " #print(\"hidden_outputs = \", hidden_outputs)\n", 81 | " \n", 82 | " # signal into final output layer\n", 83 | " final_inputs = numpy.dot(self.who, hidden_outputs)\n", 84 | " #print(\"final_input = \", final_inputs)\n", 85 | " #signal out of output layer\n", 86 | " final_outputs = numpy.exp(1j * numpy.angle(final_inputs))\n", 87 | " #print(\"final_outputs = \", final_outputs)\n", 88 | " \n", 89 | " # map to output classes\n", 90 | " output_classes = self.z_to_class(final_outputs)\n", 91 | " print(\"output_classes = \", output_classes)\n", 92 | " return output_classes\n", 93 | " \n", 94 | " def train(self, inputs_list, target_class_list):\n", 95 | " # add bias input\n", 96 | " inputs_list.append(1.0)\n", 97 | " \n", 98 | " # convert input to complex\n", 99 | " inputs = numpy.array(inputs_list, ndmin=2, dtype='complex128').T\n", 100 | " #print(\"inputs = \\n\", inputs)\n", 101 | " \n", 102 | " # map target classes to unit circle\n", 103 | " targets = numpy.exp(1j * self.class_to_angle(numpy.array(target_class_list, ndmin=2).T))\n", 104 | " #print(\"targets = \\n\", targets)\n", 105 | "\n", 106 | " # signal into hidden layer\n", 107 | " hidden_inputs = numpy.dot(self.wih, inputs)\n", 108 | " #print(\"hidden_inputs = \", hidden_inputs)\n", 109 | " #signal out of hidden layer\n", 110 | " hidden_outputs = numpy.exp(1j * numpy.angle(hidden_inputs))\n", 111 | " #print(\"hidden_outputs = \", hidden_outputs)\n", 112 | " \n", 113 | " # signal into final output layer\n", 114 | " final_inputs = numpy.dot(self.who, hidden_outputs)\n", 115 | " #print(\"final_inputs = \", final_inputs)\n", 116 | " #signal out of output layer\n", 117 | " final_outputs = numpy.exp(1j * numpy.angle(final_inputs))\n", 118 | " #print(\"final_outputs = \", final_outputs)\n", 119 | " \n", 120 | " # output layer error is the (target - actual)\n", 121 | " output_errors = targets - final_outputs\n", 122 | " #print(\"output_errors = \", output_errors)\n", 123 | " # hidden layer error is the output_errors split simply (not by weights)\n", 124 | " hidden_errors = numpy.dot(numpy.array(numpy.ones((self.hnodes)), ndmin=2).T / self.hnodes, output_errors)\n", 125 | " #print(\"hidden_errors = \", hidden_errors)\n", 126 | " \n", 127 | " # dw = e * x.T / (x.x.T)\n", 128 | " #dwho = (output_errors * numpy.conj(hidden_outputs.T)) / (self.hnodes)\n", 129 | " dwho = numpy.dot(output_errors, numpy.conj(hidden_outputs.T)) / (self.hnodes)\n", 130 | " #print(\"dwho = \", dwho)\n", 131 | " self.who += dwho\n", 132 | " \n", 133 | " #dwih = (hidden_errors * numpy.conj(inputs.T)) / (self.inodes)\n", 134 | " dwih = numpy.dot(hidden_errors, numpy.conj(inputs.T)) / (self.inodes)\n", 135 | " #print(\"dwih = \", dwih)\n", 136 | " self.wih += dwih \n", 137 | " pass" 138 | ] 139 | }, 140 | { 141 | "cell_type": "code", 142 | "execution_count": 28, 143 | "metadata": { 144 | "collapsed": false 145 | }, 146 | "outputs": [ 147 | { 148 | "name": "stdout", 149 | "output_type": "stream", 150 | "text": [ 151 | "self.wih = [[-0.97560880-0.44299654j 0.39673175+0.45313716j -0.36348055-0.42098974j]\n", 152 | " [-0.78914030+0.38495572j 0.06405584+0.12566801j 0.93014655+0.4663918j ]]\n", 153 | "self.who = [[-0.15796713+0.42202923j -0.66723068+0.01251784j]]\n" 154 | ] 155 | } 156 | ], 157 | "source": [ 158 | "# number of input, hidden and output nodes\n", 159 | "input_nodes = 2\n", 160 | "hidden_nodes = 2\n", 161 | "output_nodes = 1\n", 162 | "\n", 163 | "# categories, periodicity\n", 164 | "categories = 2\n", 165 | "periodicity = 1\n", 166 | "\n", 167 | "# create instance of neural network\n", 168 | "n = neuralNetwork(input_nodes,hidden_nodes,output_nodes, categories, periodicity)\n", 169 | "n.status()" 170 | ] 171 | }, 172 | { 173 | "cell_type": "code", 174 | "execution_count": 29, 175 | "metadata": { 176 | "collapsed": false 177 | }, 178 | "outputs": [], 179 | "source": [ 180 | "# train neural network - OR\n", 181 | "\n", 182 | "epochs = 5\n", 183 | "\n", 184 | "for e in range(epochs):\n", 185 | " n.train([-1.0, -1.0], [0])\n", 186 | " n.train([-1.0, 1.0], [1])\n", 187 | " n.train([1.0, -1.0], [1])\n", 188 | " n.train([1.0, 1.0], [1])\n", 189 | " pass" 190 | ] 191 | }, 192 | { 193 | "cell_type": "code", 194 | "execution_count": 30, 195 | "metadata": { 196 | "collapsed": false 197 | }, 198 | "outputs": [ 199 | { 200 | "name": "stdout", 201 | "output_type": "stream", 202 | "text": [ 203 | "self.wih = [[-0.95393264-1.0836447j 0.39135471-1.35898696j -0.32501294-2.01430814j]\n", 204 | " [-0.76746414-0.25569244j 0.05867880-1.68645611j 0.96861417-1.1269266j ]]\n", 205 | "self.who = [[ 1.17035804+0.61847302j -0.13069239-0.41321431j]]\n", 206 | "inputs = \n", 207 | " [[-1.+0.j]\n", 208 | " [-1.+0.j]\n", 209 | " [ 1.+0.j]]\n", 210 | "output_classes = 0\n", 211 | "inputs = \n", 212 | " [[-1.+0.j]\n", 213 | " [ 1.+0.j]\n", 214 | " [ 1.+0.j]]\n", 215 | "output_classes = 1\n", 216 | "inputs = \n", 217 | " [[ 1.+0.j]\n", 218 | " [-1.+0.j]\n", 219 | " [ 1.+0.j]]\n", 220 | "output_classes = 1\n", 221 | "inputs = \n", 222 | " [[ 1.+0.j]\n", 223 | " [ 1.+0.j]\n", 224 | " [ 1.+0.j]]\n", 225 | "output_classes = 1\n" 226 | ] 227 | }, 228 | { 229 | "data": { 230 | "text/plain": [ 231 | "1" 232 | ] 233 | }, 234 | "execution_count": 30, 235 | "metadata": {}, 236 | "output_type": "execute_result" 237 | } 238 | ], 239 | "source": [ 240 | "# query after training\n", 241 | "n.status()\n", 242 | "n.query( [-1.0, -1.0] )\n", 243 | "n.query( [-1.0, 1.0] )\n", 244 | "n.query( [1.0, -1.0] )\n", 245 | "n.query( [1.0, 1.0] )" 246 | ] 247 | }, 248 | { 249 | "cell_type": "code", 250 | "execution_count": null, 251 | "metadata": { 252 | "collapsed": false 253 | }, 254 | "outputs": [], 255 | "source": [] 256 | }, 257 | { 258 | "cell_type": "code", 259 | "execution_count": null, 260 | "metadata": { 261 | "collapsed": true 262 | }, 263 | "outputs": [], 264 | "source": [] 265 | } 266 | ], 267 | "metadata": { 268 | "kernelspec": { 269 | "display_name": "Python 3", 270 | "language": "python", 271 | "name": "python3" 272 | }, 273 | "language_info": { 274 | "codemirror_mode": { 275 | "name": "ipython", 276 | "version": 3 277 | }, 278 | "file_extension": ".py", 279 | "mimetype": "text/x-python", 280 | "name": "python", 281 | "nbconvert_exporter": "python", 282 | "pygments_lexer": "ipython3", 283 | "version": "3.5.1" 284 | } 285 | }, 286 | "nbformat": 4, 287 | "nbformat_minor": 0 288 | } 289 | -------------------------------------------------------------------------------- /network_mnist.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 110, 6 | "metadata": { 7 | "collapsed": false 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "# neural network of many complex valued neurons in 3 layers\n", 12 | "# applied to the MNIST dataset\n", 13 | "import numpy" 14 | ] 15 | }, 16 | { 17 | "cell_type": "code", 18 | "execution_count": 111, 19 | "metadata": { 20 | "collapsed": false 21 | }, 22 | "outputs": [], 23 | "source": [ 24 | "class neuralNetwork:\n", 25 | " \n", 26 | " def __init__(self, inputnodes, hiddennodes, outputnodes, cats, periods):\n", 27 | " # set number of nodes in each input, hidden, output layer\n", 28 | " self.inodes = inputnodes +1 # increament for bias node\n", 29 | " self.hnodes = hiddennodes\n", 30 | " self.onodes = outputnodes\n", 31 | " \n", 32 | " # link weight matrices, wih and who\n", 33 | " # weights inside the arrays are w_i_j, where link is from node i to node j in the next layer\n", 34 | " # w11 w21\n", 35 | " # w12 w22 etc \n", 36 | " self.wih = numpy.random.uniform(-1.0, 1.0, (self.hnodes, self.inodes))\n", 37 | " self.wih = numpy.array(self.wih, ndmin=2, dtype='complex128')\n", 38 | " self.wih += 1j * numpy.random.uniform(-1.0, 1.0, (self.hnodes, self.inodes))\n", 39 | " \n", 40 | " self.who = numpy.random.uniform(-1.0, 1.0, (self.onodes, self.hnodes))\n", 41 | " self.who = numpy.array(self.who, ndmin=2, dtype='complex128')\n", 42 | " self.who += 1j * numpy.random.random((self.onodes, self.hnodes))\n", 43 | " \n", 44 | " # number of output class categories\n", 45 | " self.categories = cats\n", 46 | " \n", 47 | " # todo periodicity\n", 48 | " self.periodicity = periods\n", 49 | " pass\n", 50 | " \n", 51 | " def z_to_class(self, z):\n", 52 | " # first work out the angle, but shift angle from [-pi/2, +pi.2] to [0,2pi]\n", 53 | " angle = numpy.mod(numpy.angle(z) + 2*numpy.pi, 2*numpy.pi)\n", 54 | " # from angle to category\n", 55 | " p = int(numpy.floor (self.categories * angle / (2*numpy.pi)))\n", 56 | " return p\n", 57 | "\n", 58 | " def class_to_angle(self, p):\n", 59 | " # class to angle, using bisector\n", 60 | " angle = ((p + 0.5) / self.categories) * 2 * numpy.pi\n", 61 | " return angle\n", 62 | " \n", 63 | " def status(self):\n", 64 | " print (\"self.wih = \", self.wih)\n", 65 | " print (\"self.who = \", self.who)\n", 66 | " pass\n", 67 | "\n", 68 | " def query(self, inputs_list):\n", 69 | " # add bias input\n", 70 | " inputs_list.append(1.0)\n", 71 | " \n", 72 | " # convert input to complex\n", 73 | " inputs = numpy.array(inputs_list, ndmin=2, dtype='complex128').T\n", 74 | " #print(\"inputs = \\n\", inputs)\n", 75 | " \n", 76 | " # signal into hidden layer\n", 77 | " hidden_inputs = numpy.dot(self.wih, inputs)\n", 78 | " #print(\"hidden_inputs = \", hidden_inputs)\n", 79 | " #signal out of hidden layer\n", 80 | " hidden_outputs = numpy.exp(1j * numpy.angle(hidden_inputs))\n", 81 | " #print(\"hidden_outputs = \", hidden_outputs)\n", 82 | " \n", 83 | " # signal into final output layer\n", 84 | " final_inputs = numpy.dot(self.who, hidden_outputs)\n", 85 | " #print(\"final_input = \", final_inputs)\n", 86 | " #signal out of output layer\n", 87 | " final_outputs = numpy.exp(1j * numpy.angle(final_inputs))\n", 88 | " #print(\"final_outputs = \", final_outputs)\n", 89 | " \n", 90 | " # map to output classes\n", 91 | " output_classes = self.z_to_class(final_outputs)\n", 92 | " #print(\"output_classes = \", output_classes)\n", 93 | " return output_classes\n", 94 | " \n", 95 | " def train(self, inputs_list, target_class_list):\n", 96 | " # add bias input\n", 97 | " inputs_list.append(1.0)\n", 98 | " \n", 99 | " # convert input to complex\n", 100 | " inputs = numpy.array(inputs_list, ndmin=2, dtype='complex128').T\n", 101 | " #print(\"inputs = \\n\", inputs)\n", 102 | " \n", 103 | " # map target classes to unit circle\n", 104 | " targets = numpy.exp(1j * self.class_to_angle(numpy.array(target_class_list, ndmin=2).T))\n", 105 | " #print(\"targets = \\n\", targets)\n", 106 | "\n", 107 | " # signal into hidden layer\n", 108 | " hidden_inputs = numpy.dot(self.wih, inputs)\n", 109 | " #print(\"hidden_inputs = \", hidden_inputs)\n", 110 | " #signal out of hidden layer\n", 111 | " hidden_outputs = numpy.exp(1j * numpy.angle(hidden_inputs))\n", 112 | " #print(\"hidden_outputs = \", hidden_outputs)\n", 113 | " \n", 114 | " # signal into final output layer\n", 115 | " final_inputs = numpy.dot(self.who, hidden_outputs)\n", 116 | " #print(\"final_inputs = \", final_inputs)\n", 117 | " #signal out of output layer\n", 118 | " final_outputs = numpy.exp(1j * numpy.angle(final_inputs))\n", 119 | " #print(\"final_outputs = \", final_outputs)\n", 120 | " \n", 121 | " # output layer error is the (target - actual)\n", 122 | " output_errors = targets - final_outputs\n", 123 | " #print(\"output_errors = \", output_errors)\n", 124 | " # hidden layer error is the output_errors split simply (not by weights)\n", 125 | " hidden_errors = numpy.dot(numpy.array(numpy.ones((self.hnodes)), ndmin=2).T / self.hnodes, output_errors)\n", 126 | " #print(\"hidden_errors = \", hidden_errors)\n", 127 | " \n", 128 | " # dw = e * x.T / (x.x.T)\n", 129 | " dwho = numpy.dot(output_errors, numpy.conj(hidden_outputs.T)) / (self.hnodes)\n", 130 | " #print(\"dwho = \", dwho)\n", 131 | " self.who += dwho\n", 132 | " \n", 133 | " dwih = numpy.dot(hidden_errors, numpy.conj(inputs.T)) / (self.inodes)\n", 134 | " #print(\"dwih = \", dwih)\n", 135 | " self.wih += dwih \n", 136 | " pass" 137 | ] 138 | }, 139 | { 140 | "cell_type": "code", 141 | "execution_count": 112, 142 | "metadata": { 143 | "collapsed": false 144 | }, 145 | "outputs": [], 146 | "source": [ 147 | "# number of input, hidden and output nodes\n", 148 | "input_nodes = 784\n", 149 | "hidden_nodes = 100\n", 150 | "output_nodes = 1\n", 151 | "\n", 152 | "# categories, periodicity\n", 153 | "categories = 10\n", 154 | "periodicity = 1\n", 155 | "\n", 156 | "# create instance of neural network\n", 157 | "n = neuralNetwork(input_nodes,hidden_nodes,output_nodes, categories, periodicity)" 158 | ] 159 | }, 160 | { 161 | "cell_type": "code", 162 | "execution_count": 113, 163 | "metadata": { 164 | "collapsed": true 165 | }, 166 | "outputs": [], 167 | "source": [ 168 | "# load the mnist training data CSV file into a list\n", 169 | "training_data_file = open(\"mnist_dataset/mnist_train.csv\", 'r')\n", 170 | "training_data_list = training_data_file.readlines()\n", 171 | "training_data_file.close()" 172 | ] 173 | }, 174 | { 175 | "cell_type": "code", 176 | "execution_count": 114, 177 | "metadata": { 178 | "collapsed": false 179 | }, 180 | "outputs": [], 181 | "source": [ 182 | "# train neural network - OR\n", 183 | "\n", 184 | "epochs = 1\n", 185 | "\n", 186 | "for e in range(epochs):\n", 187 | " # go through all records in the training data set\n", 188 | " for record in training_data_list:\n", 189 | " # split the record by the ',' commas\n", 190 | " all_values = record.split(',')\n", 191 | " # scale and shift the inputs\n", 192 | " inputs = numpy.exp(1j * (numpy.asfarray(all_values[1:]) / 255.0) * numpy.pi)\n", 193 | " inputs_list = inputs.tolist()\n", 194 | " # create the target class list\n", 195 | " targets = [int(all_values[0])]\n", 196 | " n.train(inputs_list, targets)\n", 197 | " pass\n", 198 | " pass" 199 | ] 200 | }, 201 | { 202 | "cell_type": "code", 203 | "execution_count": 115, 204 | "metadata": { 205 | "collapsed": true 206 | }, 207 | "outputs": [], 208 | "source": [ 209 | "# load the mnist test data CSV file into a list\n", 210 | "test_data_file = open(\"mnist_dataset/mnist_test.csv\", 'r')\n", 211 | "test_data_list = test_data_file.readlines()\n", 212 | "test_data_file.close()" 213 | ] 214 | }, 215 | { 216 | "cell_type": "code", 217 | "execution_count": 116, 218 | "metadata": { 219 | "collapsed": false 220 | }, 221 | "outputs": [], 222 | "source": [ 223 | "# test the neural network\n", 224 | "\n", 225 | "# scorecard for how well the network performs, initially empty\n", 226 | "scorecard = []\n", 227 | "\n", 228 | "# go through all the records in the test data set\n", 229 | "for record in test_data_list:\n", 230 | " # split the record by the ',' commas\n", 231 | " all_values = record.split(',')\n", 232 | " # correct answer is first value\n", 233 | " correct_label = int(all_values[0])\n", 234 | " # scale and shift the inputs\n", 235 | " inputs = numpy.exp(1j * (numpy.asfarray(all_values[1:]) / 255.0) * numpy.pi)\n", 236 | " inputs_list = inputs.tolist()\n", 237 | " # query the network\n", 238 | " output_label = n.query(inputs_list)\n", 239 | " # append correct or incorrect to list\n", 240 | " if (output_label == correct_label):\n", 241 | " # network's answer matches correct answer, add 1 to scorecard\n", 242 | " scorecard.append(1)\n", 243 | " else:\n", 244 | " # network's answer doesn't match correct answer, add 0 to scorecard\n", 245 | " scorecard.append(0)\n", 246 | " pass\n", 247 | " \n", 248 | " pass" 249 | ] 250 | }, 251 | { 252 | "cell_type": "code", 253 | "execution_count": 117, 254 | "metadata": { 255 | "collapsed": false 256 | }, 257 | "outputs": [ 258 | { 259 | "name": "stdout", 260 | "output_type": "stream", 261 | "text": [ 262 | "performance = 0.1719\n" 263 | ] 264 | } 265 | ], 266 | "source": [ 267 | "# calculate the performance score, the fraction of correct answers\n", 268 | "scorecard_array = numpy.asarray(scorecard)\n", 269 | "print (\"performance = \", scorecard_array.sum() / scorecard_array.size)" 270 | ] 271 | }, 272 | { 273 | "cell_type": "code", 274 | "execution_count": null, 275 | "metadata": { 276 | "collapsed": true 277 | }, 278 | "outputs": [], 279 | "source": [] 280 | } 281 | ], 282 | "metadata": { 283 | "kernelspec": { 284 | "display_name": "Python 3", 285 | "language": "python", 286 | "name": "python3" 287 | }, 288 | "language_info": { 289 | "codemirror_mode": { 290 | "name": "ipython", 291 | "version": 3 292 | }, 293 | "file_extension": ".py", 294 | "mimetype": "text/x-python", 295 | "name": "python", 296 | "nbconvert_exporter": "python", 297 | "pygments_lexer": "ipython3", 298 | "version": "3.5.1" 299 | } 300 | }, 301 | "nbformat": 4, 302 | "nbformat_minor": 0 303 | } 304 | -------------------------------------------------------------------------------- /single_neuron-periodic-iris.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 220, 6 | "metadata": { 7 | "collapsed": false 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "# simple neural network of one complex valued neuron\n", 12 | "# extended to use a periodic activation function\n", 13 | "import numpy\n", 14 | "# pandas for reading csv files\n", 15 | "import pandas\n", 16 | "# sklearn for splitting data into test/train sets\n", 17 | "import sklearn.cross_validation" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": 221, 23 | "metadata": { 24 | "collapsed": false 25 | }, 26 | "outputs": [], 27 | "source": [ 28 | "class neuralNetwork:\n", 29 | " \n", 30 | " def __init__(self, inputs, cats, periods):\n", 31 | " # number of inputs\n", 32 | " self.inputs = inputs\n", 33 | " \n", 34 | " # link weights matrix\n", 35 | " self.w = numpy.random.normal(0.0, pow(1.0, -0.5), (self.inputs + 1))\n", 36 | " self.w = numpy.array(self.w, ndmin=2, dtype='complex128')\n", 37 | " self.w += 1j * numpy.random.normal(0.0, pow(1.0, -0.5), (self.inputs + 1))\n", 38 | " \n", 39 | " # testing overrride\n", 40 | " #self.w = numpy.array([1.0 + 0.0j, 1.0 + 0.0j], ndmin=2, dtype='complex128')\n", 41 | " \n", 42 | " # number of output class categories\n", 43 | " self.categories = cats\n", 44 | " \n", 45 | " # todo periodicity\n", 46 | " self.periodicity = periods\n", 47 | " \n", 48 | " pass\n", 49 | " \n", 50 | " def z_to_class(self, z):\n", 51 | " # first work out the angle, but shift angle from [-pi/2, +pi.2] to [0,2pi]\n", 52 | " angle = numpy.mod(numpy.angle(z) + 2*numpy.pi, 2*numpy.pi)\n", 53 | " # from angle to category\n", 54 | " p = int(numpy.floor (self.categories * self.periodicity * angle / (2*numpy.pi)))\n", 55 | " p = numpy.mod(p, self.categories)\n", 56 | " return p\n", 57 | "\n", 58 | " def class_to_angles(self, c):\n", 59 | " # class to several angles due to periodicity, using bisector\n", 60 | " angles = (c + 0.5 + (self.categories * numpy.arange(self.periodicity))) / (self.categories * self.periodicity) * 2 * numpy.pi\n", 61 | " return angles\n", 62 | " \n", 63 | " def status(self):\n", 64 | " print (\"w = \", self.w)\n", 65 | " print (\"categories = \", self.categories)\n", 66 | " print (\"periodicity = \", self.periodicity)\n", 67 | " pass\n", 68 | "\n", 69 | " def query(self, inputs_list):\n", 70 | " # add bias input\n", 71 | " inputs_list.append(1.0)\n", 72 | " \n", 73 | " # convert input to complex\n", 74 | " inputs = numpy.array(inputs_list, ndmin=2, dtype='complex128').T\n", 75 | " #print(\"inputs = \\n\", inputs)\n", 76 | " \n", 77 | " # combine inputs, weighted\n", 78 | " z = numpy.dot(self.w, inputs)\n", 79 | " #print(\"z = \", z)\n", 80 | " \n", 81 | " # map to output classes\n", 82 | " o = self.z_to_class(z)\n", 83 | " #print(\"output = \", o)\n", 84 | " #print (\"\")\n", 85 | " return o\n", 86 | " \n", 87 | " def train(self, inputs_list, target):\n", 88 | " # add bias input\n", 89 | " inputs_list.append(1.0)\n", 90 | " \n", 91 | " # convert inputs and outputs list to 2d array\n", 92 | " inputs = numpy.array(inputs_list, ndmin=2, dtype='complex128').T\n", 93 | "\n", 94 | " # combine inputs, weighted\n", 95 | " z = numpy.dot(self.w, inputs)[0]\n", 96 | " \n", 97 | " # desired angle from trainging set\n", 98 | " # first get all possible angles\n", 99 | " desired_angles = self.class_to_angles(target)\n", 100 | " \n", 101 | " # potential errors errors\n", 102 | " errors = numpy.exp(1j*desired_angles) - z\n", 103 | " # select smallest error\n", 104 | " e = errors[numpy.argmin(numpy.abs(errors))]\n", 105 | " \n", 106 | " # dw = e * x.T / (x.x.T)\n", 107 | " dw = (e * numpy.conj(inputs.T)) / (self.inputs + 1)\n", 108 | " #print(\"dw = \", dw)\n", 109 | " self.w += dw\n", 110 | " #print(\"new self.w = \", self.w )\n", 111 | " #print(\"test new self.w with query = \", self.query(inputs.T))\n", 112 | " #print(\"--\")\n", 113 | " pass" 114 | ] 115 | }, 116 | { 117 | "cell_type": "code", 118 | "execution_count": 222, 119 | "metadata": { 120 | "collapsed": false 121 | }, 122 | "outputs": [ 123 | { 124 | "name": "stdout", 125 | "output_type": "stream", 126 | "text": [ 127 | "w = [[ 0.38574064+1.66513146j 1.22031900+2.16144084j 1.21310153+0.176633j\n", 128 | " -1.12485307-0.25812644j -1.27266833-0.13015915j]]\n", 129 | "categories = 3\n", 130 | "periodicity = 3\n" 131 | ] 132 | } 133 | ], 134 | "source": [ 135 | "# create instance of neural network\n", 136 | "number_of_inputs = 4\n", 137 | "categories = 3\n", 138 | "periods = 3\n", 139 | "\n", 140 | "n = neuralNetwork(number_of_inputs, categories, periods)\n", 141 | "n.status()" 142 | ] 143 | }, 144 | { 145 | "cell_type": "code", 146 | "execution_count": 223, 147 | "metadata": { 148 | "collapsed": false, 149 | "scrolled": true 150 | }, 151 | "outputs": [ 152 | { 153 | "data": { 154 | "text/html": [ 155 | "
\n", 156 | "\n", 157 | " \n", 158 | " \n", 159 | " \n", 160 | " \n", 161 | " \n", 162 | " \n", 163 | " \n", 164 | " \n", 165 | " \n", 166 | " \n", 167 | " \n", 168 | " \n", 169 | " \n", 170 | " \n", 171 | " \n", 172 | " \n", 173 | " \n", 174 | " \n", 175 | " \n", 176 | " \n", 177 | " \n", 178 | " \n", 179 | " \n", 180 | " \n", 181 | " \n", 182 | " \n", 183 | " \n", 184 | " \n", 185 | " \n", 186 | " \n", 187 | " \n", 188 | " \n", 189 | " \n", 190 | " \n", 191 | " \n", 192 | " \n", 193 | " \n", 194 | " \n", 195 | " \n", 196 | " \n", 197 | " \n", 198 | " \n", 199 | " \n", 200 | " \n", 201 | " \n", 202 | " \n", 203 | " \n", 204 | " \n", 205 | " \n", 206 | " \n", 207 | " \n", 208 | " \n", 209 | "
TypePWPLSWSL
7200.040.160.340.50
8800.020.150.370.54
9800.020.150.350.52
000.020.140.330.50
110.240.560.310.67
\n", 210 | "
" 211 | ], 212 | "text/plain": [ 213 | " Type PW PL SW SL\n", 214 | "72 0 0.04 0.16 0.34 0.50\n", 215 | "88 0 0.02 0.15 0.37 0.54\n", 216 | "98 0 0.02 0.15 0.35 0.52\n", 217 | "0 0 0.02 0.14 0.33 0.50\n", 218 | "1 1 0.24 0.56 0.31 0.67" 219 | ] 220 | }, 221 | "execution_count": 223, 222 | "metadata": {}, 223 | "output_type": "execute_result" 224 | } 225 | ], 226 | "source": [ 227 | "# load the iris training data CSV file into a list\n", 228 | "df = pandas.read_csv('iris_dataset/iris.csv')\n", 229 | "\n", 230 | "# scale the lengths\n", 231 | "df[['PW', 'PL', 'SW', 'SL']] = df[['PW', 'PL', 'SW', 'SL']].astype(numpy.float64) * 0.01\n", 232 | "\n", 233 | "# shuffle and split dataframe into train and test sets, split 3/4 and 1/4\n", 234 | "iris_train, iris_test = sklearn.cross_validation.train_test_split(df, train_size=0.75)\n", 235 | "iris_test.head()" 236 | ] 237 | }, 238 | { 239 | "cell_type": "code", 240 | "execution_count": 224, 241 | "metadata": { 242 | "collapsed": false 243 | }, 244 | "outputs": [], 245 | "source": [ 246 | "# train neural network\n", 247 | "\n", 248 | "epochs = 2\n", 249 | "\n", 250 | "for e in range(epochs):\n", 251 | " # go through all records in the training data set\n", 252 | " for idx, data in iris_train.iterrows():\n", 253 | " data_list = data.tolist()\n", 254 | " species = data_list[0]\n", 255 | " lengths = data_list[1:]\n", 256 | " n.train(lengths, species)\n", 257 | " pass\n", 258 | " pass" 259 | ] 260 | }, 261 | { 262 | "cell_type": "code", 263 | "execution_count": 225, 264 | "metadata": { 265 | "collapsed": false 266 | }, 267 | "outputs": [ 268 | { 269 | "name": "stdout", 270 | "output_type": "stream", 271 | "text": [ 272 | "w = [[ 0.94712904+1.0675523j 2.43183469+0.84406376j 1.07463099+0.46028561j\n", 273 | " -0.61066543-0.54791292j -1.05720782+0.55283372j]]\n", 274 | "categories = 3\n", 275 | "periodicity = 3\n" 276 | ] 277 | } 278 | ], 279 | "source": [ 280 | "n.status()" 281 | ] 282 | }, 283 | { 284 | "cell_type": "code", 285 | "execution_count": 226, 286 | "metadata": { 287 | "collapsed": false 288 | }, 289 | "outputs": [ 290 | { 291 | "name": "stdout", 292 | "output_type": "stream", 293 | "text": [ 294 | "0 0\n", 295 | "0 0\n", 296 | "0 0\n", 297 | "0 0\n", 298 | "1 1\n", 299 | "2 2\n", 300 | "2 2\n", 301 | "1 1\n", 302 | "0 0\n", 303 | "0 0\n", 304 | "2 1\n", 305 | "1 1\n", 306 | "2 2\n", 307 | "2 2\n", 308 | "1 1\n", 309 | "1 1\n", 310 | "2 2\n", 311 | "2 2\n", 312 | "0 0\n", 313 | "1 1\n", 314 | "0 0\n", 315 | "2 2\n", 316 | "2 2\n", 317 | "1 1\n", 318 | "2 1\n", 319 | "2 2\n", 320 | "2 2\n", 321 | "0 0\n", 322 | "1 1\n", 323 | "1 1\n", 324 | "2 2\n", 325 | "1 1\n", 326 | "0 0\n", 327 | "0 0\n", 328 | "1 1\n", 329 | "2 2\n", 330 | "1 1\n", 331 | "0 0\n" 332 | ] 333 | } 334 | ], 335 | "source": [ 336 | "# query after training\n", 337 | "\n", 338 | "scorecard = []\n", 339 | "\n", 340 | "for idx, data in iris_test.iterrows():\n", 341 | " data_list = data.tolist()\n", 342 | " correct_species = int(data_list[0])\n", 343 | " lengths = data_list[1:]\n", 344 | " answer = n.query(lengths)\n", 345 | " print(correct_species, answer)\n", 346 | " if (answer == correct_species):\n", 347 | " # network's answer matches correct answer, add 1 to scorecard\n", 348 | " scorecard.append(1)\n", 349 | " else:\n", 350 | " # network's answer doesn't match correct answer, add 0 to scorecard\n", 351 | " scorecard.append(0)\n", 352 | " pass\n", 353 | " pass" 354 | ] 355 | }, 356 | { 357 | "cell_type": "code", 358 | "execution_count": 227, 359 | "metadata": { 360 | "collapsed": false 361 | }, 362 | "outputs": [ 363 | { 364 | "name": "stdout", 365 | "output_type": "stream", 366 | "text": [ 367 | "performance = 0.947368421053\n" 368 | ] 369 | } 370 | ], 371 | "source": [ 372 | "# calculate the performance score, the fraction of correct answers\n", 373 | "scorecard_array = numpy.asarray(scorecard)\n", 374 | "print (\"performance = \", scorecard_array.sum() / scorecard_array.size)" 375 | ] 376 | }, 377 | { 378 | "cell_type": "code", 379 | "execution_count": null, 380 | "metadata": { 381 | "collapsed": true 382 | }, 383 | "outputs": [], 384 | "source": [] 385 | } 386 | ], 387 | "metadata": { 388 | "kernelspec": { 389 | "display_name": "Python 3", 390 | "language": "python", 391 | "name": "python3" 392 | }, 393 | "language_info": { 394 | "codemirror_mode": { 395 | "name": "ipython", 396 | "version": 3 397 | }, 398 | "file_extension": ".py", 399 | "mimetype": "text/x-python", 400 | "name": "python", 401 | "nbconvert_exporter": "python", 402 | "pygments_lexer": "ipython3", 403 | "version": "3.5.1" 404 | } 405 | }, 406 | "nbformat": 4, 407 | "nbformat_minor": 0 408 | } 409 | -------------------------------------------------------------------------------- /single_neuron-periodic-mnist.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 183, 6 | "metadata": { 7 | "collapsed": false 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "# simple neural network of one complex valued neuron\n", 12 | "# extended to use a periodic activation function\n", 13 | "import numpy" 14 | ] 15 | }, 16 | { 17 | "cell_type": "code", 18 | "execution_count": 184, 19 | "metadata": { 20 | "collapsed": false 21 | }, 22 | "outputs": [], 23 | "source": [ 24 | "class neuralNetwork:\n", 25 | " \n", 26 | " def __init__(self, inputs, cats, periods):\n", 27 | " # number of inputs\n", 28 | " self.inputs = inputs\n", 29 | " \n", 30 | " # link weights matrix\n", 31 | " self.w = numpy.random.normal(0.0, pow(1.0, -0.5), (inputs + 1))\n", 32 | " self.w = numpy.array(self.w, ndmin=2, dtype='complex128')\n", 33 | " self.w += 1j * numpy.random.normal(0.0, pow(1.0, -0.5), (inputs + 1))\n", 34 | " \n", 35 | " # testing overrride\n", 36 | " #self.w = numpy.array([1.0 + 0.0j, 1.0 + 0.0j], ndmin=2, dtype='complex128')\n", 37 | " \n", 38 | " # number of output class categories\n", 39 | " self.categories = cats\n", 40 | " \n", 41 | " # todo periodicity\n", 42 | " self.periodicity = periods\n", 43 | " \n", 44 | " pass\n", 45 | " \n", 46 | " def z_to_class(self, z):\n", 47 | " # first work out the angle, but shift angle from [-pi/2, +pi.2] to [0,2pi]\n", 48 | " angle = numpy.mod(numpy.angle(z) + 2*numpy.pi, 2*numpy.pi)\n", 49 | " # from angle to category\n", 50 | " p = int(numpy.floor (self.categories * self.periodicity * angle / (2*numpy.pi)))\n", 51 | " p = numpy.mod(p, self.categories)\n", 52 | " return p\n", 53 | "\n", 54 | " def class_to_angles(self, c):\n", 55 | " # class to several angles due to periodicity, using bisector\n", 56 | " angles = (c + 0.5 + (self.categories * numpy.arange(self.periodicity))) / (self.categories * self.periodicity) * 2 * numpy.pi\n", 57 | " return angles\n", 58 | " \n", 59 | " def status(self):\n", 60 | " print (\"w = \", self.w)\n", 61 | " print (\"categories = \", self.categories)\n", 62 | " print (\"periodicity = \", self.periodicity)\n", 63 | " pass\n", 64 | "\n", 65 | " def query(self, inputs_list):\n", 66 | " # add bias input\n", 67 | " inputs_list.append(1.0)\n", 68 | " \n", 69 | " # convert input to complex\n", 70 | " inputs = numpy.array(inputs_list, ndmin=2, dtype='complex128').T\n", 71 | " #print(\"inputs = \\n\", inputs)\n", 72 | " \n", 73 | " # combine inputs, weighted\n", 74 | " z = numpy.dot(self.w, inputs)\n", 75 | " #print(\"z = \", z)\n", 76 | " \n", 77 | " # map to output classes\n", 78 | " o = self.z_to_class(z)\n", 79 | " #print(\"output = \", o)\n", 80 | " #print (\"\")\n", 81 | " return o\n", 82 | " \n", 83 | " def train(self, inputs_list, target):\n", 84 | " # add bias input\n", 85 | " inputs_list.append(1.0)\n", 86 | " \n", 87 | " # convert inputs and outputs list to 2d array\n", 88 | " inputs = numpy.array(inputs_list, ndmin=2, dtype='complex128').T\n", 89 | "\n", 90 | " # combine inputs, weighted\n", 91 | " z = numpy.dot(self.w, inputs)[0]\n", 92 | " \n", 93 | " # desired angle from trainging set\n", 94 | " # first get all possible angles\n", 95 | " desired_angles = self.class_to_angles(target)\n", 96 | " \n", 97 | " # potential errors errors\n", 98 | " errors = numpy.exp(1j*desired_angles) - z\n", 99 | " # select smallest error\n", 100 | " e = errors[numpy.argmin(numpy.abs(errors))]\n", 101 | " \n", 102 | " # dw = e * x.T / (x.x.T)\n", 103 | " dw = (e * numpy.conj(inputs.T)) / (self.inputs + 1)\n", 104 | " #print(\"dw = \", dw)\n", 105 | " self.w += dw\n", 106 | " #print(\"new self.w = \", self.w )\n", 107 | " #print(\"test new self.w with query = \", self.query(inputs.T))\n", 108 | " #print(\"--\")\n", 109 | " pass" 110 | ] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "execution_count": 185, 115 | "metadata": { 116 | "collapsed": false 117 | }, 118 | "outputs": [], 119 | "source": [ 120 | "# create instance of neural network\n", 121 | "number_of_inputs = 784\n", 122 | "categories = 10\n", 123 | "periods = 3\n", 124 | "\n", 125 | "n = neuralNetwork(number_of_inputs, categories, periods)" 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "execution_count": 186, 131 | "metadata": { 132 | "collapsed": false, 133 | "scrolled": true 134 | }, 135 | "outputs": [], 136 | "source": [ 137 | "# load the mnist training data CSV file into a list\n", 138 | "training_data_file = open(\"mnist_dataset/mnist_train.csv\", 'r')\n", 139 | "training_data_list = training_data_file.readlines()\n", 140 | "training_data_file.close()" 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": 187, 146 | "metadata": { 147 | "collapsed": false 148 | }, 149 | "outputs": [], 150 | "source": [ 151 | "# train the neural network\n", 152 | "\n", 153 | "# epochs is the number of times the training data set is used for training\n", 154 | "epochs = 5\n", 155 | "\n", 156 | "for e in range(epochs):\n", 157 | " # go through all records in the training data set\n", 158 | " for record in training_data_list:\n", 159 | " # split the record by the ',' commas\n", 160 | " all_values = record.split(',')\n", 161 | " # scale and shift the inputs\n", 162 | " inputs = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01\n", 163 | " inputs = inputs.tolist()\n", 164 | " n.train(inputs, int(all_values[0]))\n", 165 | " pass\n", 166 | " pass" 167 | ] 168 | }, 169 | { 170 | "cell_type": "code", 171 | "execution_count": 188, 172 | "metadata": { 173 | "collapsed": true 174 | }, 175 | "outputs": [], 176 | "source": [ 177 | "# load the mnist test data CSV file into a list\n", 178 | "test_data_file = open(\"mnist_dataset/mnist_test.csv\", 'r')\n", 179 | "test_data_list = test_data_file.readlines()\n", 180 | "test_data_file.close()" 181 | ] 182 | }, 183 | { 184 | "cell_type": "code", 185 | "execution_count": 189, 186 | "metadata": { 187 | "collapsed": false 188 | }, 189 | "outputs": [], 190 | "source": [ 191 | "# test the neural network\n", 192 | "\n", 193 | "# scorecard for how well the network performs, initially empty\n", 194 | "scorecard = []\n", 195 | "\n", 196 | "# go through all the records in the test data set\n", 197 | "for record in test_data_list:\n", 198 | " # split the record by the ',' commas\n", 199 | " all_values = record.split(',')\n", 200 | " # correct answer is first value\n", 201 | " correct_label = int(all_values[0])\n", 202 | " # scale and shift the inputs\n", 203 | " inputs = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01\n", 204 | " inputs = inputs.tolist()\n", 205 | " # query the network\n", 206 | " label = n.query(inputs)\n", 207 | "\n", 208 | " # append correct or incorrect to list\n", 209 | " if (label == correct_label):\n", 210 | " # network's answer matches correct answer, add 1 to scorecard\n", 211 | " scorecard.append(1)\n", 212 | " else:\n", 213 | " # network's answer doesn't match correct answer, add 0 to scorecard\n", 214 | " scorecard.append(0)\n", 215 | " pass\n", 216 | " \n", 217 | " pass" 218 | ] 219 | }, 220 | { 221 | "cell_type": "code", 222 | "execution_count": 190, 223 | "metadata": { 224 | "collapsed": false 225 | }, 226 | "outputs": [ 227 | { 228 | "name": "stdout", 229 | "output_type": "stream", 230 | "text": [ 231 | "performance = 0.1172\n" 232 | ] 233 | } 234 | ], 235 | "source": [ 236 | "# calculate the performance score, the fraction of correct answers\n", 237 | "scorecard_array = numpy.asarray(scorecard)\n", 238 | "print (\"performance = \", scorecard_array.sum() / scorecard_array.size)" 239 | ] 240 | }, 241 | { 242 | "cell_type": "code", 243 | "execution_count": null, 244 | "metadata": { 245 | "collapsed": true 246 | }, 247 | "outputs": [], 248 | "source": [] 249 | } 250 | ], 251 | "metadata": { 252 | "kernelspec": { 253 | "display_name": "Python 3", 254 | "language": "python", 255 | "name": "python3" 256 | }, 257 | "language_info": { 258 | "codemirror_mode": { 259 | "name": "ipython", 260 | "version": 3 261 | }, 262 | "file_extension": ".py", 263 | "mimetype": "text/x-python", 264 | "name": "python", 265 | "nbconvert_exporter": "python", 266 | "pygments_lexer": "ipython3", 267 | "version": "3.5.1" 268 | } 269 | }, 270 | "nbformat": 4, 271 | "nbformat_minor": 0 272 | } 273 | -------------------------------------------------------------------------------- /single_neuron-periodic.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 146, 6 | "metadata": { 7 | "collapsed": false 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "# simple neural network of one complex valued neuron\n", 12 | "# extended to use a periodic activation function\n", 13 | "import numpy" 14 | ] 15 | }, 16 | { 17 | "cell_type": "code", 18 | "execution_count": 147, 19 | "metadata": { 20 | "collapsed": false 21 | }, 22 | "outputs": [], 23 | "source": [ 24 | "class neuralNetwork:\n", 25 | " \n", 26 | " def __init__(self, inputs, cats, periods):\n", 27 | " # link weights matrix\n", 28 | " self.w = numpy.random.normal(0.0, pow(1.0, -0.5), (inputs + 1))\n", 29 | " self.w = numpy.array(self.w, ndmin=2, dtype='complex128')\n", 30 | " self.w += 1j * numpy.random.normal(0.0, pow(1.0, -0.5), (inputs + 1))\n", 31 | " \n", 32 | " # testing overrride\n", 33 | " #self.w = numpy.array([1.0 + 0.0j, 1.0 + 0.0j], ndmin=2, dtype='complex128')\n", 34 | " \n", 35 | " # number of output class categories\n", 36 | " self.categories = cats\n", 37 | " \n", 38 | " # todo periodicity\n", 39 | " self.periodicity = periods\n", 40 | " \n", 41 | " pass\n", 42 | " \n", 43 | " def z_to_class(self, z):\n", 44 | " # first work out the angle, but shift angle from [-pi/2, +pi.2] to [0,2pi]\n", 45 | " angle = numpy.mod(numpy.angle(z) + 2*numpy.pi, 2*numpy.pi)\n", 46 | " # from angle to category\n", 47 | " p = int(numpy.floor (self.categories * self.periodicity * angle / (2*numpy.pi)))\n", 48 | " p = numpy.mod(p, self.categories)\n", 49 | " return p\n", 50 | "\n", 51 | " def class_to_angles(self, c):\n", 52 | " # class to several angles due to periodicity, using bisector\n", 53 | " angles = (c + 0.5 + (self.categories * numpy.arange(self.periodicity))) / (self.categories * self.periodicity) * 2 * numpy.pi\n", 54 | " return angles\n", 55 | " \n", 56 | " def status(self):\n", 57 | " print (\"w = \", self.w)\n", 58 | " print (\"categories = \", self.categories)\n", 59 | " print (\"periodicity = \", self.periodicity)\n", 60 | " pass\n", 61 | "\n", 62 | " def query(self, inputs_list):\n", 63 | " # add bias input\n", 64 | " inputs_list.append(1.0)\n", 65 | " \n", 66 | " # convert input to complex\n", 67 | " inputs = numpy.array(inputs_list, ndmin=2, dtype='complex128').T\n", 68 | " print(\"inputs = \\n\", inputs)\n", 69 | " \n", 70 | " # combine inputs, weighted\n", 71 | " z = numpy.dot(self.w, inputs)\n", 72 | " print(\"z = \", z)\n", 73 | " \n", 74 | " # map to output classes\n", 75 | " o = self.z_to_class(z)\n", 76 | " print(\"output = \", o)\n", 77 | " print (\"\")\n", 78 | " return o\n", 79 | " \n", 80 | " def train(self, inputs_list, target):\n", 81 | " # add bias input\n", 82 | " inputs_list.append(1.0)\n", 83 | " \n", 84 | " # convert inputs and outputs list to 2d array\n", 85 | " inputs = numpy.array(inputs_list, ndmin=2, dtype='complex128').T\n", 86 | "\n", 87 | " # combine inputs, weighted\n", 88 | " z = numpy.dot(self.w, inputs)[0]\n", 89 | " \n", 90 | " # desired angle from trainging set\n", 91 | " # first get all possible angles\n", 92 | " desired_angles = self.class_to_angles(target)\n", 93 | " \n", 94 | " # potential errors errors\n", 95 | " errors = numpy.exp(1j*desired_angles) - z\n", 96 | " # select smallest error\n", 97 | " e = errors[numpy.argmin(numpy.abs(errors))]\n", 98 | " \n", 99 | " # dw = e * x.T / (x.x.T)\n", 100 | " dw = (e * numpy.conj(inputs.T)) / (3)\n", 101 | " #print(\"dw = \", dw)\n", 102 | " self.w += dw\n", 103 | " #print(\"new self.w = \", self.w )\n", 104 | " #print(\"test new self.w with query = \", self.query(inputs.T))\n", 105 | " #print(\"--\")\n", 106 | " pass" 107 | ] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "execution_count": 148, 112 | "metadata": { 113 | "collapsed": false 114 | }, 115 | "outputs": [ 116 | { 117 | "name": "stdout", 118 | "output_type": "stream", 119 | "text": [ 120 | "w = [[-1.56572466+0.70528849j -2.71967065+0.00440014j 1.31235568-0.46018874j]]\n", 121 | "categories = 2\n", 122 | "periodicity = 2\n" 123 | ] 124 | } 125 | ], 126 | "source": [ 127 | "# create instance of neural network\n", 128 | "number_of_inputs = 2\n", 129 | "categories = 2\n", 130 | "periods = 2\n", 131 | "\n", 132 | "n = neuralNetwork(number_of_inputs, categories, periods)\n", 133 | "n.status()" 134 | ] 135 | }, 136 | { 137 | "cell_type": "code", 138 | "execution_count": 149, 139 | "metadata": { 140 | "collapsed": false 141 | }, 142 | "outputs": [], 143 | "source": [ 144 | "# train neural network - XOR\n", 145 | "for i in range(10):\n", 146 | " n.train([-1.0, -1.0], 0)\n", 147 | " n.train([-1.0, 1.0], 1)\n", 148 | " n.train([1.0, -1.0], 1)\n", 149 | " n.train([1.0, 1.0], 0)\n", 150 | " pass" 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": 150, 156 | "metadata": { 157 | "collapsed": false 158 | }, 159 | "outputs": [ 160 | { 161 | "name": "stdout", 162 | "output_type": "stream", 163 | "text": [ 164 | "inputs = \n", 165 | " [[-1.+0.j]\n", 166 | " [-1.+0.j]\n", 167 | " [ 1.+0.j]]\n", 168 | "z = [[ 0.70710678+0.70710678j]]\n", 169 | "output = 0\n", 170 | "\n", 171 | "inputs = \n", 172 | " [[-1.+0.j]\n", 173 | " [ 1.+0.j]\n", 174 | " [ 1.+0.j]]\n", 175 | "z = [[-0.70710678+0.70710678j]]\n", 176 | "output = 1\n", 177 | "\n", 178 | "inputs = \n", 179 | " [[ 1.+0.j]\n", 180 | " [-1.+0.j]\n", 181 | " [ 1.+0.j]]\n", 182 | "z = [[ 0.70710678-0.70710678j]]\n", 183 | "output = 1\n", 184 | "\n", 185 | "inputs = \n", 186 | " [[ 1.+0.j]\n", 187 | " [ 1.+0.j]\n", 188 | " [ 1.+0.j]]\n", 189 | "z = [[-0.70710678-0.70710678j]]\n", 190 | "output = 0\n", 191 | "\n" 192 | ] 193 | }, 194 | { 195 | "data": { 196 | "text/plain": [ 197 | "0" 198 | ] 199 | }, 200 | "execution_count": 150, 201 | "metadata": {}, 202 | "output_type": "execute_result" 203 | } 204 | ], 205 | "source": [ 206 | "# query after training\n", 207 | "n.query( [-1.0, -1.0] )\n", 208 | "n.query( [-1.0, 1.0] )\n", 209 | "n.query( [1.0, -1.0] )\n", 210 | "n.query( [1.0, 1.0] )" 211 | ] 212 | }, 213 | { 214 | "cell_type": "code", 215 | "execution_count": null, 216 | "metadata": { 217 | "collapsed": false 218 | }, 219 | "outputs": [], 220 | "source": [] 221 | }, 222 | { 223 | "cell_type": "code", 224 | "execution_count": null, 225 | "metadata": { 226 | "collapsed": true 227 | }, 228 | "outputs": [], 229 | "source": [] 230 | } 231 | ], 232 | "metadata": { 233 | "kernelspec": { 234 | "display_name": "Python 3", 235 | "language": "python", 236 | "name": "python3" 237 | }, 238 | "language_info": { 239 | "codemirror_mode": { 240 | "name": "ipython", 241 | "version": 3 242 | }, 243 | "file_extension": ".py", 244 | "mimetype": "text/x-python", 245 | "name": "python", 246 | "nbconvert_exporter": "python", 247 | "pygments_lexer": "ipython3", 248 | "version": "3.5.1" 249 | } 250 | }, 251 | "nbformat": 4, 252 | "nbformat_minor": 0 253 | } 254 | -------------------------------------------------------------------------------- /single_neuron.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 112, 6 | "metadata": { 7 | "collapsed": false 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "# simple neural network of one complex valued neuron\n", 12 | "import numpy" 13 | ] 14 | }, 15 | { 16 | "cell_type": "code", 17 | "execution_count": 113, 18 | "metadata": { 19 | "collapsed": false 20 | }, 21 | "outputs": [], 22 | "source": [ 23 | "class neuralNetwork:\n", 24 | " \n", 25 | " def __init__(self):\n", 26 | " # link weights matrix\n", 27 | " self.w = numpy.random.normal(0.0, pow(1.0, -0.5), (3))\n", 28 | " self.w = numpy.array(self.w, ndmin=2, dtype='complex128')\n", 29 | " self.w += 1j * numpy.random.normal(0.0, pow(1.0, -0.5), (3))\n", 30 | " \n", 31 | " # testing overrride\n", 32 | " #self.w = numpy.array([1.0 + 0.0j, 1.0 + 0.0j], ndmin=2, dtype='complex128')\n", 33 | " \n", 34 | " # number of output class categories\n", 35 | " self.categories = 2\n", 36 | " \n", 37 | " # todo periodicity self.periodicity = 2\n", 38 | " pass\n", 39 | " \n", 40 | " def z_to_class(self, z):\n", 41 | " # first work out the angle, but shift angle from [-pi/2, +pi.2] to [0,2pi]\n", 42 | " angle = numpy.mod(numpy.angle(z) + 2*numpy.pi, 2*numpy.pi)\n", 43 | " # from angle to category\n", 44 | " p = int(numpy.floor (self.categories * angle / (2*numpy.pi)))\n", 45 | " return p\n", 46 | "\n", 47 | " def class_to_angle(self, p):\n", 48 | " # class to angle, using bisector\n", 49 | " angle = ((p + 0.5) / self.categories) * 2 * numpy.pi\n", 50 | " return angle\n", 51 | " \n", 52 | " def status(self):\n", 53 | " print (\"w = \", self.w)\n", 54 | " pass\n", 55 | "\n", 56 | " def query(self, inputs_list):\n", 57 | " # add bias input\n", 58 | " inputs_list.append(1.0)\n", 59 | " \n", 60 | " # convert input to complex\n", 61 | " inputs = numpy.array(inputs_list, ndmin=2, dtype='complex128').T\n", 62 | " print(\"inputs = \\n\", inputs)\n", 63 | " \n", 64 | " # combine inputs, weighted\n", 65 | " z = numpy.dot(self.w, inputs)\n", 66 | " print(\"z = \", z)\n", 67 | " \n", 68 | " # map to output classes\n", 69 | " o = self.z_to_class(z)\n", 70 | " print(\"output = \", o)\n", 71 | " print (\"\")\n", 72 | " return o\n", 73 | " \n", 74 | " def train(self, inputs_list, targets_list):\n", 75 | " # add bias input\n", 76 | " inputs_list.append(1.0)\n", 77 | " \n", 78 | " # convert inputs and outputs list to 2d array\n", 79 | " inputs = numpy.array(inputs_list, ndmin=2, dtype='complex128').T\n", 80 | " targets = numpy.array(targets_list, ndmin=2).T\n", 81 | "\n", 82 | " # combine inputs, weighted\n", 83 | " z = numpy.dot(self.w, inputs)\n", 84 | " #print(\"z = \", z)\n", 85 | " \n", 86 | " # desired angle from trainging set\n", 87 | " desired_angle = self.class_to_angle(targets)\n", 88 | " #print(\"desired_angle = \", desired_angle)\n", 89 | " \n", 90 | " # error e\n", 91 | " e = numpy.exp(1j*desired_angle) - z\n", 92 | " #print(\"e = \", e)\n", 93 | " \n", 94 | " # dw = e * x.T / (x.x.T)\n", 95 | " dw = (e * numpy.conj(inputs.T)) / (3)\n", 96 | " #print(\"dw = \", dw)\n", 97 | " self.w += dw\n", 98 | " #print(\"new self.w = \", self.w )\n", 99 | " #print(\"test new self.w with query = \", self.query(inputs.T))\n", 100 | " #print(\"--\")\n", 101 | " pass" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": 114, 107 | "metadata": { 108 | "collapsed": false 109 | }, 110 | "outputs": [ 111 | { 112 | "name": "stdout", 113 | "output_type": "stream", 114 | "text": [ 115 | "w = [[-1.06236919+0.04312478j 0.50718034+1.69705651j -0.81702728-0.51196168j]]\n" 116 | ] 117 | } 118 | ], 119 | "source": [ 120 | "# create instance of neural network\n", 121 | "n = neuralNetwork()\n", 122 | "n.status()" 123 | ] 124 | }, 125 | { 126 | "cell_type": "code", 127 | "execution_count": 115, 128 | "metadata": { 129 | "collapsed": false 130 | }, 131 | "outputs": [], 132 | "source": [ 133 | "# train neural network - OR\n", 134 | "for i in range(5):\n", 135 | " n.train([-1.0, -1.0], [0])\n", 136 | " n.train([-1.0, 1.0], [1])\n", 137 | " n.train([1.0, -1.0], [1])\n", 138 | " n.train([1.0, 1.0], [1])\n", 139 | " pass" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": 116, 145 | "metadata": { 146 | "collapsed": false 147 | }, 148 | "outputs": [ 149 | { 150 | "name": "stdout", 151 | "output_type": "stream", 152 | "text": [ 153 | "w = [[ -6.35598582e-06-0.33336145j 3.17265351e-05-0.16667827j\n", 154 | " -2.53705493e-05-0.49996028j]]\n", 155 | "inputs = \n", 156 | " [[-1.+0.j]\n", 157 | " [-1.+0.j]\n", 158 | " [ 1.+0.j]]\n", 159 | "z = [[ -5.07410985e-05 +7.94330603e-05j]]\n", 160 | "output = 0\n", 161 | "\n", 162 | "inputs = \n", 163 | " [[-1.+0.j]\n", 164 | " [ 1.+0.j]\n", 165 | " [ 1.+0.j]]\n", 166 | "z = [[ 1.27119716e-05-0.3332771j]]\n", 167 | "output = 1\n", 168 | "\n", 169 | "inputs = \n", 170 | " [[ 1.+0.j]\n", 171 | " [-1.+0.j]\n", 172 | " [ 1.+0.j]]\n", 173 | "z = [[ -6.34530701e-05-0.66664346j]]\n", 174 | "output = 1\n", 175 | "\n", 176 | "inputs = \n", 177 | " [[ 1.+0.j]\n", 178 | " [ 1.+0.j]\n", 179 | " [ 1.+0.j]]\n", 180 | "z = [[ -1.83663848e-16-1.j]]\n", 181 | "output = 1\n", 182 | "\n" 183 | ] 184 | }, 185 | { 186 | "data": { 187 | "text/plain": [ 188 | "1" 189 | ] 190 | }, 191 | "execution_count": 116, 192 | "metadata": {}, 193 | "output_type": "execute_result" 194 | } 195 | ], 196 | "source": [ 197 | "# query after training\n", 198 | "n.status()\n", 199 | "n.query( [-1.0, -1.0] )\n", 200 | "n.query( [-1.0, 1.0] )\n", 201 | "n.query( [1.0, -1.0] )\n", 202 | "n.query( [1.0, 1.0] )" 203 | ] 204 | }, 205 | { 206 | "cell_type": "code", 207 | "execution_count": null, 208 | "metadata": { 209 | "collapsed": false 210 | }, 211 | "outputs": [], 212 | "source": [] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": null, 217 | "metadata": { 218 | "collapsed": true 219 | }, 220 | "outputs": [], 221 | "source": [] 222 | } 223 | ], 224 | "metadata": { 225 | "kernelspec": { 226 | "display_name": "Python 3", 227 | "language": "python", 228 | "name": "python3" 229 | }, 230 | "language_info": { 231 | "codemirror_mode": { 232 | "name": "ipython", 233 | "version": 3 234 | }, 235 | "file_extension": ".py", 236 | "mimetype": "text/x-python", 237 | "name": "python", 238 | "nbconvert_exporter": "python", 239 | "pygments_lexer": "ipython3", 240 | "version": "3.5.1" 241 | } 242 | }, 243 | "nbformat": 4, 244 | "nbformat_minor": 0 245 | } 246 | -------------------------------------------------------------------------------- /test_image/test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/makeyourownneuralnetwork/complex_valued_neuralnetwork/89d7b02ae5b8e6496db5fd0243e46ab66f55c8d2/test_image/test.jpg --------------------------------------------------------------------------------