class Ai4r::Som::Som
Introduction¶ ↑
This is an implementation of a Kohonen Self-Organizing Maps
Features¶ ↑
-
Support for any network architecture (number of layers and neurons)
-
Configurable propagation function
-
Optional usage of bias
-
Configurable momentum
-
Configurable learning rate
-
Configurable initial weight function
-
100% ruby code, no external dependency
Parameters¶ ↑
-
dim => dimension of the input vector
-
number_of_nodes => is the number of nodes per row/column (square som).
-
layer => instante of a layer-algorithm class
About the project¶ ↑
- Author
-
Thomas Kern
- License
-
MPL 1.1
- Url
Public Class Methods
# File lib/ai4r/som/som.rb, line 61 def initialize(dim, number_of_nodes, layer) @layer = layer @dimension = dim @number_of_nodes = number_of_nodes @nodes = Array.new(number_of_nodes * number_of_nodes) @epoch = 0 @cache = {} end
Public Instance Methods
adjusts all nodes within a certain radius to the bmu
# File lib/ai4r/som/som.rb, line 87 def adjust_nodes(input, bmu, radius, learning_rate) @nodes.each do |node| dist = node.distance_to_node(bmu[0]) next unless dist < radius influence = @layer.influence_decay dist, radius node.weights.each_with_index do |weight, index| node.weights[index] += influence * learning_rate * (input[index] - weight) end end end
finds the best matching unit (bmu) of a certain input in all the @nodes returns an array of length 2 => [node, distance] (distance is of eucledian type, not a neighborhood distance)
# File lib/ai4r/som/som.rb, line 73 def find_bmu(input) bmu = @nodes.first dist = bmu.distance_to_input input @nodes[1..-1].each do |node| tmp_dist = node.distance_to_input(input) if tmp_dist <= dist dist = tmp_dist bmu = node end end [bmu, dist] end
returns the node at position (x,y) in the square map
# File lib/ai4r/som/som.rb, line 131 def get_node(x, y) raise(Exception.new) if check_param_for_som(x,y) @nodes[y + x * @number_of_nodes] end
calculates the global distance error for all data entries
# File lib/ai4r/som/som.rb, line 107 def global_error(data) data.inject(0) {|sum,entry| sum + find_bmu(entry)[1]**2 } end
intitiates the map by creating (@number_of_nodes * @number_of_nodes) nodes
# File lib/ai4r/som/som.rb, line 137 def initiate_map @nodes.each_with_index do |node, i| @nodes[i] = Node.create i, @number_of_nodes, @dimension end end
main method for the som. trains the map with the passed data vector calls #train_step as long as #train_step returns false
# File lib/ai4r/som/som.rb, line 101 def train(data) while !train_step(data) end end
trains the map with the data as long as the @epoch is smaller than the epoch-value of @layer returns true if @epoch is greater than the fixed epoch-value in @layer, otherwise false 1 is added to @epoch at each method call the radius and learning rate is decreased at each method call/epoch as well
# File lib/ai4r/som/som.rb, line 116 def train_step(data) return true if @epoch >= @layer.epochs radius = @layer.radius_decay @epoch learning_rate = @layer.learning_rate_decay @epoch data.each do |entry| adjust_nodes entry, find_bmu(entry), radius, learning_rate end @epoch += 1 false end
Private Instance Methods
checks whether or not there is a node in the map at the coordinates (x,y). x is the row, y the column indicator
# File lib/ai4r/som/som.rb, line 147 def check_param_for_som(x, y) y > @number_of_nodes - 1 || x > @number_of_nodes - 1 || x < 0 || y < 0 end