source: proiecte/ParallelANN/BCMToolbox/BCM.cs @ 171

Last change on this file since 171 was 171, checked in by (none), 14 years ago
File size: 10.4 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Collections;
4using System.Linq;
5using System.Text;
6
7namespace BCMToolbox
8{
9
10    #region Network
11    public class SynchronousBCMNetwork : FixedTraceableNetwork
12    {
13       
14        protected Func<double, double> __activation = null;
15        protected Func<double, double> __activationDerivative = null;
16        protected int __neuronCount = 0;
17        protected double __slidingThreshold = 0.0;
18
19        double __inertia = 0.8;
20        double[] __intermediaryPotentials = null;
21        double[,] __potentialsQueues = null;
22        double[] __memoryRegression = null;
23
24 
25        internal SynchronousBCMNetwork(int neuronCount, Func<double, double> newThreshold, Func<double, double> newThresholdDerivative, int newID)
26            : base(neuronCount, newID)
27        {
28            __activation = newThreshold;
29            __activationDerivative = newThresholdDerivative;
30            __neuronCount = neuronCount;
31            __intermediaryPotentials = new double[neuronCount];
32
33
34
35            // setup the memory trace function memoizer
36            __memoryRegression = new double[] { 1, 0.90483741803596, 0.818730753077982, 0.740818220681718, 0.670320046035639, 0.606530659712633, 0.548811636094027, 0.49658530379141, 0.449328964117222, 0.406569659740599, 0.367879441171442, 0.33287108369808, 0.301194211912202, 0.272531793034013, 0.246596963941606, 0.22313016014843, 0.201896517994655, 0.182683524052735, 0.165298888221587, 0.149568619222635 };
37            __slidingThreshold = 9.08618386468457;
38            //__slidingThreshold = 9;
39
40            /*
41            int memoryRegressionDepth = 0;
42            for (memoryRegressionDepth = 0; memoryRegressionDepth > -100; memoryRegressionDepth--)
43                if (memoryFunction(memoryRegressionDepth) < MEMORY_REGRESSION_THRESHOLD)
44                    break;
45
46            __memoryRegression = new double[-memoryRegressionDepth];
47            for (int i = 0; i > memoryRegressionDepth; i--)
48                __memoryRegression[-i] = memoryFunction(i); */
49
50            // setup the queues
51            __potentialsQueues = new double[__neuronCount, __memoryRegression.Length];
52        }
53
54        public override string Identification
55        {
56            get
57            {
58                return String.Format("Vanilla BCM #{0}", this.UID);
59            }
60        }
61
62       
63
64       
65
66        public double Inertia
67        {
68            get
69            {
70                return __inertia;
71            }
72
73            set
74            {
75                __inertia = value;
76            }
77        }
78
79
80       
81
82        #region Applying inputs and propagation
83       
84
85        public override void ApplyInputs(double[] newInputs)
86        {
87            lock (SyncRoot)
88            {
89                if (newInputs == null)
90                    throw new ArgumentNullException();
91
92                if (newInputs.Length != __neuronCount)
93                    throw new ArgumentException("Invalid input size. Expected: ", __neuronCount.ToString());
94
95                for (int i = 0; i < __neuronCount; i++)
96                    __potentials[i] += newInputs[i];
97            }
98
99            base.ApplyInputs(newInputs);
100        }
101
102
103       
104        public override void Propagate()
105        {
106            // calculate intermediary potentials
107            for (int i = 0; i < __neuronCount; i++)
108            {
109                __intermediaryPotentials[i] = 0.0;
110                for (int j = 0; j < __neuronCount; j++)
111                    if ((i != j) && !double.IsNaN(__weights[j, i]))
112                       __intermediaryPotentials[i] += __weights[j, i] * __potentials[j];
113                   
114
115               
116                __intermediaryPotentials[i] = __activation(__intermediaryPotentials[i]);
117                System.Diagnostics.Debug.Assert(!double.IsNaN(__intermediaryPotentials[i]));
118                System.Diagnostics.Debug.Assert(!double.IsInfinity(__intermediaryPotentials[i]));
119            }
120
121            lock (SyncRoot)
122            {
123                // update weights
124                int queueIdx = Ticks % __memoryRegression.Length;
125                for (int i = 0; i < __neuronCount; i++)
126                {
127                    // determine output threshold
128                    double outputThreshold = 0.0;
129                    double last = __intermediaryPotentials[i];
130                    for (int j = 0; j < __memoryRegression.Length; j++)
131                    {
132                        int idx = queueIdx - 1 - j + __memoryRegression.Length;
133                        idx %= __memoryRegression.Length;
134
135                        if (j >= Ticks) // not progressed this far yet
136                            outputThreshold += last * last * __memoryRegression[j];
137                        else
138                        {
139                            outputThreshold += __potentialsQueues[i, idx] * __potentialsQueues[i, idx] * __memoryRegression[j];
140                            last = __potentialsQueues[i, idx];
141                        }
142                    }
143                    outputThreshold *= 1 / __slidingThreshold;
144
145                    /*
146                    if (i == 50)
147                        System.Diagnostics.Debug.WriteLine(String.Format("{0} - {1}", __intermediaryPotentials[i], outputThreshold)); */
148
149                    // update weights
150                    for (int j = 0; j < __neuronCount; j++)
151                    {
152                        if ((i == j) || double.IsNaN(__weights[j, i])) continue;
153                     
154                        double delta = __intermediaryPotentials[i] * (__intermediaryPotentials[i] - outputThreshold);
155
156                        delta *= __potentials[j];                       
157                        delta *= __activationDerivative(__intermediaryPotentials[i]); // Intrator and Cooper
158                        /*
159                        if(0 != outputThreshold)
160                            delta /= outputThreshold; // Law and Cooper */
161                        delta *= __inertia; 
162                        System.Diagnostics.Debug.Assert(!double.IsNaN(delta));
163                        System.Diagnostics.Debug.Assert(!double.IsInfinity(delta));
164                        __weights[j, i] += delta;
165
166                        /*
167                        // additional constraint: connections preserve their exc/inh status
168                         * NOT A GOOD IDEA - network wide inhibition needs to be implemented as a process which does not influece calculus
169                        if (__weights[j, i] < 0)
170                        {
171                            __weights[j, i] -= delta;
172                            if (__weights[j, i] > 0)
173                                __weights[j, i] = -double.Epsilon;
174                        }
175                        else
176                        {
177                            __weights[j, i] += delta;
178                            if (__weights[j, i] < 0)
179                                __weights[j, i] = double.Epsilon;
180                        } */
181                    }
182                }
183
184
185                // update potentials and queues
186                for (int i = 0; i < __neuronCount; i++)
187                {
188                    __potentials[i] = __intermediaryPotentials[i];
189                    __potentialsQueues[i, queueIdx] = __potentials[i];
190                }
191
192
193                NormalizeWeights(2.0);
194            }
195
196            base.Propagate();
197        }
198     
199        #endregion
200
201       
202    }
203    #endregion
204
205    #region Factories
206    public class BCMFactory
207    {
208        static int __uid = 0;
209        public static TraceableNetwork BuildSyncSigmoidActivationNetwork(int nodesCount)
210        {
211            return new SynchronousBCMNetwork(
212                nodesCount,
213                x => 1.0 / (1 + Math.Exp(-x)), // threshold function
214                x => { double e = Math.Exp(-x); return e / ((1.0 + e) * (1.0 + e)); }, // derivative of the threshold
215                __uid++); // memory regression parameter
216        }
217
218        public static TraceableNetwork BuildSyncSigmoidActivationNetworkSparse(int nodesCount, Func<int, int, bool> weightExistenceFunction)
219        {
220            SynchronousBCMNetwork toRet = new SynchronousBCMNetwork(
221                nodesCount,
222                x => 1.0 / (1 + Math.Exp(-x)), // threshold function
223                x => { double e = Math.Exp(-x); return e / ((1.0 + e) * (1.0 + e)); }, // derivative of the threshold
224                __uid++);
225           
226            for (int i = 0; i < nodesCount; i++)
227                for (int j = 0; j < nodesCount; j++)
228                    if (!weightExistenceFunction(i, j))
229                        toRet[i, j] = double.NaN;
230
231            return toRet;
232        }
233
234        public static TraceableNetwork Reduce(TraceableNetwork toReduce, Func<int, int, bool> weightExistenceFunction)
235        {
236            for (int i = 0; i < toReduce.Count; i++)
237                for (int j = 0; j < toReduce.Count; j++)
238                    if (!weightExistenceFunction(i, j))
239                        toReduce[i, j] = double.NaN;
240            return toReduce;
241        }
242
243       
244        public static TraceableNetwork BuildSyncSigmoidActivationNetwork2(int nodesCount)
245        {
246            return new SynchronousBCMNetwork(
247                nodesCount,
248                x => 2.0 / (1 - Math.Exp(-2*x)) - 1.0, // threshold function
249                x => { double e = Math.Exp(-2*x); return 4.0* e / ((1 + e) * (1 + e)); }, // derivative of the threshold
250                __uid++
251               ); // memory regression parameter
252        }
253
254        public static TraceableNetwork BuildOja(int nodesCount)
255        {
256            return new SynchronousOjaNetwork(nodesCount,
257                __uid++);
258        }
259
260        public static TraceableNetwork BuildModel01(int nodesCount)
261        {
262            return new Model01(nodesCount,
263                __uid++);
264        }
265
266        /*
267        public static TraceableNetwork BuildSyncLinearActivationNetwork(int nodesCount, double slidingThreshold)
268        {
269            return new SynchronousBCMNetwork(
270                nodesCount,
271                x => x,
272                x => 1.0,
273                __uid++,
274                x => Math.Exp(x / slidingThreshold),
275                slidingThreshold);
276        } */
277    }
278    #endregion
279}
Note: See TracBrowser for help on using the repository browser.