1 module des.isys.neiro.layer.structure; 2 3 import std.traits; 4 import std.conv; 5 6 import des.isys.neiro.func; 7 import des.isys.neiro.neiron; 8 import des.isys.neiro.layer.neiron; 9 10 class BPLayer(T) if( isFloatingPoint!T ) 11 { 12 package: 13 BPNeiron!T[] neirons; 14 public: 15 this( BPNeiron!T[] nn ) { neirons = nn; } 16 17 void process() { foreach( n; neirons ) n.process(); } 18 19 void correct( T nu, T alpha ) 20 { 21 foreach( neiron; neirons ) 22 neiron.correct( nu, alpha ); 23 } 24 } 25 26 interface NetStructure(T) 27 if( isFloatingPoint!T ) 28 { 29 @property 30 { 31 ValueNeiron!T[] input(); 32 BPLayer!T[] layers(); 33 } 34 } 35 36 interface NetWeight(T) 37 if( isFloatingPoint!T ) 38 { T opIndex( size_t layer, size_t left, size_t right ); } 39 40 class RandomWeight(T) : NetWeight!T 41 { 42 import des.isys.neiro.layer.rand; 43 T lim, gap; 44 45 this( T lim=0.2, T gap=0.1 ) 46 { 47 this.lim = lim; 48 this.gap = gap; 49 } 50 51 T opIndex( size_t layer, size_t input, size_t neiron ) 52 { return gap_symmetry_uniform(lim,gap); } 53 } 54 55 /++ 56 ConsistentlyAssociatedLayereNetStructure 57 58 input neiron set(ins) + unitary neiron(un) -> first layer (L1) 59 ins + un + L1 -> L2 60 ins + un + L1 + L2 -> L3 61 ins + un + L1 + L2 + L3 -> output 62 63 +/ 64 65 class ConsistentlyAssociatedLayereNetStructure(T) : NetStructure!T 66 if( isFloatingPoint!T ) 67 { 68 protected: 69 70 ValueNeiron!T[] in_neirons; 71 BPNeiron!T[] neirons; 72 BPLayer!T[] net_layers; 73 DerivativeFunction!T func; 74 75 public: 76 77 this( DerivativeFunction!T func, size_t[] sizes, NetWeight!T weight=null ) 78 in 79 { 80 assert( func !is null ); 81 assert( sizes.length > 1 ); 82 } 83 body 84 { 85 this.func = func; 86 87 addUnitaryNeiron(); 88 addInputNeirons( sizes[0] ); 89 if( weight is null ) weight = new RandomWeight!T; 90 addLayers( sizes[1..$], weight ); 91 } 92 93 @property 94 { 95 ValueNeiron!T[] input() { return in_neirons; } 96 BPLayer!T[] layers() { return net_layers; } 97 } 98 99 protected: 100 101 void addUnitaryNeiron() { neirons ~= new ReferenceBPNeiron!T( new ValueNeiron!T(1) ); } 102 103 void addInputNeirons( size_t count ) 104 { 105 foreach( i; 0 .. count ) 106 { 107 auto buf = new ValueNeiron!T(0); 108 in_neirons ~= buf; 109 neirons ~= new ReferenceBPNeiron!T(buf); 110 } 111 } 112 113 void addLayers( size_t[] net_struct, NetWeight!T weight ) 114 { 115 foreach( i; 0 .. net_struct.length ) 116 addLayer( net_struct[i], (size_t j, size_t k){ return weight[i,j,k]; } ); 117 } 118 119 void addLayer( size_t size, T delegate(size_t, size_t) weight ) 120 { 121 auto ln = createNeirons( size ); 122 123 linkNeirons( ln, neirons, weight ); 124 125 auto nln = to!(BPNeiron!T[])(ln); 126 127 neirons ~= nln; 128 net_layers ~= new BPLayer!T( nln ); 129 } 130 131 auto createNeirons( size_t count ) 132 { 133 auto ret = new BaseBPNeiron!T[](count); 134 ret[] = new BaseBPNeiron!T(func); 135 return to!(BPNeiron!T[])(ret); 136 } 137 138 /+ function weight(a,b) must return weight of link from input neiron lnk[a] to neiron ns[b] +/ 139 void linkNeirons( BPNeiron!T[] ns, BPNeiron!T[] lnk, T delegate(size_t,size_t) weight ) 140 in { assert( weight !is null ); } body 141 { foreach( i, n; ns ) n.setLinks( createLinks( lnk, (size_t j){ return weight(j,i); } ) ); } 142 143 BPLink!T[] createLinks( BPNeiron!T[] inn, T delegate(size_t) weight ) 144 in { assert( weight !is null ); } body 145 { 146 auto links = new BaseBPLink!T[](inn.length); 147 foreach( j; 0 .. inn.length ) 148 links[j] = new BaseBPLink!T( inn[j], weight(j) ); 149 return to!(BPLink!T[])( links ); 150 } 151 } 152 153 unittest 154 { 155 auto nw = new class NetWeight!float 156 { float opIndex(size_t,size_t,size_t) { return 1; } }; 157 158 auto calns = new ConsistentlyAssociatedLayereNetStructure!float( 159 new LinearDependence!float(2), [1,1], nw ); 160 161 calns.input[0].value = 1; 162 calns.layers[0].process(); 163 164 assert( calns.layers[0].neirons[0].output == 2 ); 165 }