File Coverage

blib/lib/AI/NeuralNet/Kohonen/Demo/RGB.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             package AI::NeuralNet::Kohonen::Demo::RGB;
2            
3 1     1   9563 use vars qw/$VERSION/;
  1         2  
  1         68  
4             $VERSION = 0.123; # 13 March 2003; using smoothing
5            
6             =head1 NAME
7            
8             AI::NeuralNet::Kohonen::Demo::RGB - Colour-based demo
9            
10             =head1 SYNOPSIS
11            
12             use AI::NeuralNet::Kohonen::Demo::RGB;
13             $_ = AI::NeuralNet::Kohonen::Demo::RGB->new(
14             display_scale => 20,
15             display => 'hex',
16             map_dim => 39,
17             epochs => 9,
18             table => "R G B"
19             ."1 0 0"
20             ."0 1 0"
21             ."0 0 1",
22             );
23             $_->train;
24             exit;
25            
26            
27             =head1 DESCRIPTION
28            
29             A sub-class of C
30             that impliments extra methods to make use of TK
31             in a very slow demonstration of how a SOM can collapse
32             a three dimensional space (RGB colour values) into a
33             two dimensional space (the display). See L.
34            
35             The only things added are two new fields to supply to the
36             constructor - set C to C for display as
37             a unified distance matrix, rather than plain grid; set
38             C for the size of the display.
39            
40             =cut
41            
42 1     1   6 use strict;
  1         1  
  1         36  
43 1     1   5 use warnings;
  1         5  
  1         44  
44 1     1   4 use Carp qw/cluck carp confess croak/;
  1         2  
  1         83  
45            
46 1     1   5 use base "AI::NeuralNet::Kohonen";
  1         2  
  1         1176  
47            
48 1     1   10472 use Tk;
  0            
  0            
49             use Tk::Canvas;
50             use Tk::Label;
51             use Tk qw/DoOneEvent DONT_WAIT/;
52            
53             #
54             # Used only by &tk_train
55             #
56             sub tk_show { my $self=shift;
57             for my $x (0..$self->{map_dim_x}){
58             for my $y (0..$self->{map_dim_y}){
59             my $colour = sprintf("#%02x%02x%02x",
60             (int (255 * $self->{map}->[$x]->[$y]->{weight}->[0])),
61             (int (255 * $self->{map}->[$x]->[$y]->{weight}->[1])),
62             (int (255 * $self->{map}->[$x]->[$y]->{weight}->[2])),
63             );
64             if ($self->{display} and $self->{display} eq 'hex'){
65             my $xo = ($y % 2) * ($self->{display_scale}/2);
66             my $yo = 0;
67            
68             $self->{c}->create(
69             polygon => [
70             $xo + ((1+$x)*$self->{display_scale} ),
71             $yo + ((1+$y)*$self->{display_scale} ),
72            
73             # polygon only:
74             $xo + ((1+$x)*($self->{display_scale})+($self->{display_scale}/2) ),
75             $yo + ((1+$y)*($self->{display_scale})-($self->{display_scale}/2) ),
76             #
77            
78             $xo + ((1+$x)*($self->{display_scale})+$self->{display_scale} ),
79             $yo + ((1+$y)*$self->{display_scale} ),
80            
81             $xo + ((1+$x)*($self->{display_scale})+$self->{display_scale} ),
82             $yo + ((1+$y)*($self->{display_scale})+($self->{display_scale}/2) ),
83            
84             # Polygon only:
85             $xo + ((1+$x)*($self->{display_scale})+($self->{display_scale}/2) ),
86             $yo + ((1+$y)*($self->{display_scale})+($self->{display_scale}) ),
87             #
88            
89             $xo + ((1+$x)*$self->{display_scale} ),
90             $yo + ((1+$y)*($self->{display_scale})+($self->{display_scale}/2) ),
91            
92             ],
93             -outline => "black",
94             -fill => $colour,
95             );
96             }
97             else {
98             $self->{c}->create(
99             rectangle => [
100             (1+$x)*$self->{display_scale} ,
101             (1+$y)*$self->{display_scale} ,
102             (1+$x)*($self->{display_scale})+$self->{display_scale} ,
103             (1+$y)*($self->{display_scale})+$self->{display_scale}
104             ],
105             -outline => "black",
106             -fill => $colour,
107             );
108             }
109             }
110             }
111             return 1;
112             }
113            
114            
115             =head1 METHOD train
116            
117             Over-rides the base class to provide TK displays of the map
118            
119             =cut
120            
121             sub train { my ($self,$epochs) = (shift,shift);
122             my $label_txt;
123            
124             $epochs = $self->{epochs} unless defined $epochs;
125             $self->{display_scale} = 10 if not defined $self->{display_scale};
126            
127             $self->{mw} = MainWindow->new(
128             -width => 200+($self->{map_dim_x} * $self->{display_scale}),
129             -height => 200+($self->{map_dim_y} * $self->{display_scale}),
130             );
131             my $quit_flag = 0;
132             my $quit_code = sub {$quit_flag = 1};
133             $self->{mw}->protocol('WM_DELETE_WINDOW' => $quit_code);
134            
135             $self->{c} = $self->{mw}->Canvas(
136             -width => 50+($self->{map_dim_x} * $self->{display_scale}),
137             -height => 50+($self->{map_dim_y} * $self->{display_scale}),
138             -relief => 'ridge',
139             -border => 5,
140             );
141             $self->{c}->pack(-side=>'top');
142            
143             my $l = $self->{mw}->Label(-text => ' ',-textvariable=>\$label_txt);
144             $l->pack(-side=>'left');
145            
146             # Replaces Tk's MainLoop
147             for (0..$self->{epochs}) {
148             if ($quit_flag) {
149             $self->{mw}->destroy;
150             return;
151             }
152             $self->{t}++; # Measure epoch
153             my $target = $self->_select_target;
154             my $bmu = $self->find_bmu($target);
155            
156             $self->_adjust_neighbours_of($bmu,$target);
157             $self->_decay_learning_rate;
158            
159             $self->tk_show;
160             $label_txt = sprintf("Epoch: %04d",$self->{t})." "
161             . "Learning: $self->{l} "
162             . sprintf("BMU: %02d,%02d",$bmu->[1],$bmu->[2])." "
163             . "Target: [".join(",",@$target)."] "
164             ;
165             $self->{c}->update;
166             $l->update;
167             DoOneEvent(DONT_WAIT); # be kind and process XEvents if they arise
168             }
169             $label_txt = "Did $self->{t} epochs: now smoothed by "
170             .($self->{smoothing}? $self->{smoothing} : "default amount");
171             $_->smooth;
172             # MainLoop;
173            
174             return 1;
175             }
176            
177            
178            
179             1;
180            
181             __END__