Loading...
Searching...
No Matches
Som.h
1/*
2
3MIT License
4
5Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26/*
27Part of Rack development has been done in the BALTRAD projects part-financed
28by the European Union (European Regional Development Fund and European
29Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30*/
31#ifndef SOM_H_
32#define SOM_H_
33
34
35
36
37/*
38 g++ drain/examples/Som-example.cpp drain/util/{Caster,Variable,Debug}.cpp drain/image/{Geometry,Coordinates,Image,FilePng}.cpp -lpng -o Som-example
39 */
40#include <iostream>
41#include <vector>
42#include <list>
43#include <limits>
44#include <sstream>
45
46#include <stdlib.h>
47
48#include "drain/Variable.h"
49
50
51
52namespace drain {
53
54// Consider
55typedef std::vector<double> SomVector; // for operator(std::ostream &)
56
64template <class T = std::vector<double> >
65class Som {
66
67public:
68
69 Som(int width=0, int height=0);
70
71
75 inline
76 void setGeometry(int width, int height) {
77 this->width = width;
78 this->height = height;
79 map.resize(height);
80 for (int j = 0; j < height; ++j) {
81 map[j].resize(width);
82 }
83 }
84
88 void fill(const T & sample){ // rename fill ?
89
90 for (int i=0; i<width; i++){
91 for (int j=0; j<height; j++){
92 map[j][i] = sample;
93 }
94 }
95 }
96
98
105 void initialise(void (* init)(T & x)) {
106
107 for (int i=0; i<width; i++){
108 for (int j=0; j<height; j++){
109 (*init)(map[j][i]);
110 }
111 }
112
113 }
114
115 inline
116 void setNeighbourhoodRadius(double r){
117 radius2 = r*r;
118 }
119
120 inline
121 void setLearningCoefficient(double c){
123 }
124
125
126
127 void setDistanceFunction(double (* d)(const T & x1, const T & x2)) {
129 }
130
131 void setMixingFunction(void (* mix)(const T & x1, const T & x2, double coeff, T & m)) {
132 mixingFunction = mix;
133 }
134
135
137 inline
138 int getHeight() const {
139 return height;
140 }
141
143 inline
144 int getWidth() const {
145 return width;
146 }
147
149
154 void findBestMatchingUnit(const T & sample, int & iBest, int & jBest){
155
156 double d;
157 double dBest = std::numeric_limits<double>::max();
158
159 for (int j=0; j<height; j++){
160 for (int i=0; i<width; i++){
161 d = (*distanceFunction)( sample, map[j][i]);
162 if (d < dBest){
163 dBest = d;
164 iBest = i;
165 jBest = j;
166 }
167 }
168 }
169 }
170
171
173
176 void train(const T & x){
177 int iBest;
178 int jBest;
180 train(x, iBest, jBest);
181 /*
182 double f;
183 for (int j=0; j<height; ++j){
184 for (int i=0; i<width; ++i){
185 f = defaultNeighborhoodFunction(i-iBest, j-jBest);
186 (*mixingFunction)(map[j][i], x, f, map[j][i]);
187 }
188 }
189 */
190 };
191
195 inline
196 void train(const T &x, int iBest, int jBest){
197 double f;
198 for (int j=0; j<height; ++j){
199 for (int i=0; i<width; ++i){
200 f = defaultNeighborhoodFunction(i-iBest, j-jBest);
201 (*mixingFunction)(map[j][i], x, f, map[j][i]);
202 }
203 }
204 };
205
206
207
208 void toStream(std::ostream &ostr) const{
209
210 std::string delimiter = "";
211
212 ostr << title << "\n";
213 for (int j=0; j<height; j++){
214 for (int i=0; i<width; i++){
215 ostr << j << ',' << i << ':';
216 ostr << '\t' << map[j][i] << '\n';
217 //delimiter = "";
218 //result += "\n";
219 };
220 ostr << '\n';
221 };
222
223 };
224
225
226 //static
227 double defaultNeighborhoodFunction(const int & i, const int & j) const {
228 return radius2 / (radius2 + i*i + j*j);
229 }
230
231 static
232 double defaultDistanceMetric(const T & x1, const T & x2);
233
234 static
235 void defaultMixingFunction(const T & x1, const T & x2, double coeff, T & m);
236
237
238
239
241 std::vector< std::vector<T> > map;
242
243protected:
244
246
249 double (* distanceFunction)(const T & x1, const T & x2);
250
252
255 void (* mixingFunction)(const T & x1, const T & x2, double alpha, T & result);
256
257
258 std::string title;
259
260 // signed, because comparisons will typically involve signed integers
261 int width;
262
263 // signed, because comparisons will typically involve signed integers
264 int height;
265
267 double radius2;
268
271
272};
273
274
275
276/*
277 For vectors and str objects having
278 */
279template <class T>
280double euclideanDistance2(const T & x1, const T & x2) {
281
282 double d, result = 0.0;
283
284 for (size_t i = 0; i < x1.size(); ++i) {// todo iterate
285 d = x1[i]-x2[i]; // todo dist();
286 result += d*d;
287 }
288
289 return result;
290
291}
292
293template <class T>
294void vectorMix(const T & x1, const T & x2, double coeff, T & m){ // todo iterate
295
296 for (size_t k = 0; k < x1.size(); ++k)
297 m[k] = (1.0-coeff)*x1[k] + coeff*x2[k];
298
299}
300
301template <>
302Som<>::Som(int width, int height){
303 setGeometry(width, height);
304 setDistanceFunction( euclideanDistance2 ); // consider Som<double>
305 setMixingFunction( vectorMix ); // consider Som<double>
306}
307
308
309
311template <class T>
312void uniformRandomVector256(std::vector<T> & x) {
313
314 for (size_t k = 0; k < x.size(); ++k)
315 x[k] = static_cast<T>(rand() & 0xff);
316 //x[k] = static_cast<T2>(rand() & 0xffff)/static_cast<T2>(0xf00);
317
318}
319
320
321
322
323
324// Utilities
325/*
326template <class T>
327static
328double Som<std::vector<T> >::defaultNeighborhoodFunction(const int & i, const int & j) const {
329 return radius2 / (radius2 + i*i + j*j);
330}
331 */
332
333
334
335/*
336template <class T>
337double Som<T>::defaultDistanceMetric(const T & x1, const T & x2) {
338
339 double d, result = 0.0;
340
341 for (int i = 0; i < x1.size(); ++i) {
342 d = x1[i]-x2[i];
343 result += d*d;
344 }
345
346 return result;
347
348}
349 */
350
351//class Som< std::vector<T> >;
352/*
353template <class T>
354double Som< std::vector<T> >::defaultDistanceMetric(const T & x1, const T & x2) {
355 return 123.456;
356}
357 */
358
359/*
360template <class T>
361void Som<T>::defaultMixingFunction(const T & x1, const T & x2, double coeff, T & m){
362
363 for (int k = 0; k < x1.size(); ++k)
364 m[k] = (1.0-coeff)*x1[k] + coeff*x2[k];
365
366}
367 */
368
369
370
372template <class T>
373//std::ostream & operator<<(std::ostream & ostr, const NeuralVector<T> & n){
374std::ostream & operator<<(std::ostream & ostr, const std::vector<T> & n){
375
376 for (typename std::vector<T>::const_iterator it = n.begin(); it !=
377 n.end(); ++it)
378 ostr << *it << ' ';
379 //ostr << '\n';
380 return ostr;
381};
382
383template <class T>
384//std::ostream & operator<<(std::ostream & ostr, const NeuralVector<T> & n){
385std::ostream & operator<<(std::ostream & ostr, const Som<T> & som){
386 som.toStream(ostr);
387 return ostr;
388};
389
390
391} // drain
392
393
394
395/* namespace drain */
396
397#endif /* SOM_H_ */
398
399// Drain
Definition Som.h:65
double(* distanceFunction)(const T &x1, const T &x2)
The similarity metric applied in finding the best-matching unit.
Definition Som.h:249
void(* mixingFunction)(const T &x1, const T &x2, double alpha, T &result)
Given objects x1 and x1 and a mixing coefficient coeff , outputs mixed object m.
Definition Som.h:255
void setGeometry(int width, int height)
Definition Som.h:76
void fill(const T &sample)
Definition Som.h:88
double learningCoefficient
The radius of the neighbourhood kernel applied in training;.
Definition Som.h:270
void train(const T &x)
Training with a single sample.
Definition Som.h:176
int getHeight() const
The number of rows in the map.
Definition Som.h:138
void train(const T &x, int iBest, int jBest)
Definition Som.h:196
double radius2
The radius of the neighbourhood kernel applied in training;.
Definition Som.h:267
std::vector< std::vector< T > > map
The actual neural network, two-dimensional map of units.
Definition Som.h:241
void findBestMatchingUnit(const T &sample, int &iBest, int &jBest)
Finds the unit with state closesest to that of sample.
Definition Som.h:154
void initialise(void(*init)(T &x))
Initialise the map with a user-defined function.
Definition Som.h:105
int getWidth() const
The number of columns in the map.
Definition Som.h:144
Definition DataSelector.cpp:1277
void uniformRandomVector256(std::vector< T > &x)
For initialising vector Soms.
Definition Som.h:312