root/lang/perl/Algorithm-LSH/trunk/lib/Algorithm/LSH.pm @ 31397

Revision 31397, 4.8 kB (checked in by miki, 4 years ago)

PODさらに直し

Line 
1package Algorithm::LSH;
2use strict;
3use warnings;
4use base qw(Algorithm::LSH::Base);
5use Algorithm::LSH::Bucket;
6use UNIVERSAL::require;
7use Scalar::Util qw(blessed);
8use Carp;
9use Storable qw( retrieve store );
10
11our $VERSION = '0.00001_01';
12
13__PACKAGE__->mk_accessors($_) for qw( hash bucket storage );
14
15sub new {
16    my $class = shift;
17    my $self  = $class->SUPER::new(@_);
18    $self->_setup(@_);
19    return $self;
20}
21
22sub insert {
23    my $self = shift;
24    my ( $label, $vector ) = @_;
25    my $hashed_arrayref = $self->hash->do_hashing($vector);
26    $self->bucket->insert( $label, $vector, $hashed_arrayref );
27}
28
29sub nn {
30    my $self = shift;
31    my $nn   = $self->nearest_neighbours(@_);
32    return $nn;
33}
34
35sub nearest_neighbours {
36    my $self         = shift;
37    my $vector       = shift;
38    my $without_self = shift;
39    my $neighbours   = $self->neighbours( $vector, $without_self );
40    my $nn           = $self->nearest( $vector, $neighbours );
41    return $nn;
42}
43
44sub neighbours {
45    my $self            = shift;
46    my $vector          = shift;
47    my $without_self    = shift;
48    my $hashed_arrayref = $self->hash->do_hashing($vector);
49    my $neighbours =
50      $self->bucket->select( $vector, $hashed_arrayref, $without_self );
51    return $neighbours;
52}
53
54sub nearest {
55    my $self       = shift;
56    my $vector     = shift;
57    my $neighbours = shift;
58    my %nearest;
59    for (@$neighbours) {
60        my ( $n_label, $n_vector ) = each %$_;
61        my $dist = $self->distance( $vector, $n_vector );
62        if ( ! defined $nearest{distance} || $dist < $nearest{distance} ) {
63            $nearest{label}    = $n_label;
64            $nearest{vector}   = $n_vector;
65            $nearest{distance} = $dist;
66        }
67    }
68    return \%nearest;
69}
70
71sub distance {
72    my $self     = shift;
73    my $vector_1 = shift;
74    my $vector_2 = shift;
75    my $sum;
76    for my $i ( 0 .. @{$vector_1} - 1 ) {
77        my $d = ( $vector_1->[$i] - $vector_2->[$i] )**2;
78        $sum += $d;
79    }
80    my $distance = sqrt($sum);
81    return $distance;
82}
83
84sub save {
85    my $self = shift;
86    my $file_path = shift || './save.bin';
87    $self->storage->save($file_path);
88}
89
90sub load {
91    my $self      = shift;
92    my $file_path = shift || './save.bin';
93    my $data      = $self->storage->load($file_path);
94    my $class     = blessed $data->hash;
95    $class->use;
96    for ( keys %$data ) {
97        $self->$_( $data->$_ );
98    }
99}
100
101sub _setup {
102    my $self = shift;
103
104    # param check
105    $self->_check_parameters;
106
107    # dynamic load (hash class)
108    my $hash_class = delete $self->{hash_class};
109    $hash_class ||= 'Algorithm::LSH::Hash::Hamming';
110    $hash_class->require or croak $@;
111    $self->hash( $hash_class->new( context => $self, @_ ) );
112
113    # dynamic loading (storage class)
114    my $storage_class = delete $self->{storage_class};
115    $storage_class ||= 'Algorithm::LSH::Storage::Storable';
116    $storage_class->require or croak $@;
117    $self->storage( $storage_class->new( context => $self, @_ ) );
118
119    # bucket class
120    $self->bucket( Algorithm::LSH::Bucket->new( context => $self, @_ ) );
121}
122
1231;
124__END__
125
126=head1 NAME
127
128Algorithm::LSH - perl implementation of Locality Sensitive Hashing
129
130=head1 SYNOPSIS
131
132  use Algorithm::LSH;
133
134  my $lsh = Algorithm::LSH->new(
135      L => 5,   # number of hash functions
136      k => 10,  # number of reductions
137      d => 3,   # number of dimentions,
138  );
139
140 
141  while(my($label, $vector) = each %database){
142      $lsh->insert($label, $vector);
143  }
144
145  $lsh->save("data.bin");
146
147  my $query_vector = [ 123, 456, 789 ];
148
149  $lsh->load("data.bin");
150
151  my $neighbours = $lsh->neighbours($query_vector);
152  my $nearest    = $lsh->nearest($neighbours);
153
154  # or
155
156  my $nearest    = $lsh->nearest_neighbours($query_vector);
157
158  # or
159
160  my $nearest    = $lsh->nn($query_vector);
161
162=head1 DESCRIPTION
163
164Algorithm::LSH is a perl implementation of Locality Sensitive Hashing algorithm.
165
166B<THIS MODULE IS IN ITS VERY ALPHA QUALITY.>
167
168=head1 METHODS
169
170=head2 new
171
172constructor. it needs three parameters.
173
174      L :  a number of hash function.
175      k :  a number of reduction. it must be smaller than parameter 'd'.
176      d :  a number of dimention.
177
178=head2 insert
179
180insert a vector data to buckets.
181
182=head2 neighbours
183
184it extracts some datas as neighbours with query vector.
185
186=head2 nearest
187
188pickup 1 nearest data from neighbours.
189
190=head2 nearest_neighbours
191
192it does neighbours() and nearset() at onece.
193
194=head2 nn
195
196an alias of nearest_neighbours()
197
198=head2 distance
199
200=head2 save
201
202save the data to storage.
203
204=head2 load
205
206load th data from storage
207
208=head2 hash
209
210accessor method
211
212=head2 bucket
213
214accessor method
215
216=head2 storage
217
218accessor method
219
220=head1 AUTHOR
221
222Takeshi Miki E<lt>miki@cpan.orgE<gt>
223
224=head1 LICENSE
225
226This library is free software; you can redistribute it and/or modify
227it under the same terms as Perl itself.
228
229=head1 SEE ALSO
230
231=cut
Note: See TracBrowser for help on using the browser.