]> git.sesse.net Git - wloh/blob - train.pl
084f84b91c14f60029fe98f0b3e9dfcdb845f92f
[wloh] / train.pl
1 #! /usr/bin/perl
2 use DBI;
3 use strict;
4 use warnings;
5 no warnings qw(once);
6 use POSIX;
7 require './config.pm';
8
9 # Find last completely done season 
10 sub find_last_season {
11         my $dbh = shift;
12         my $ref = $dbh->selectrow_hashref('SELECT sesong FROM fotballserier GROUP BY sesong HAVING COUNT(*)=COUNT(avgjort=1 OR NULL) ORDER BY sesong DESC LIMIT 1');
13         return $ref->{'sesong'};
14 }
15
16 sub fetch_games {
17         my ($dbh, $last_season, $games, $ids) = @_;
18         my $q = $dbh->prepare('
19 SELECT
20   deltager1.id as p1, deltager2.id as p2, maalfor, maalmot, least(pow(2.0, (sesong - ? + 3) / 3.0), 1.0) AS vekt
21 FROM
22   Fotballresultater resultater
23   JOIN Fotballdeltagere deltager1 ON resultater.Lagrecno=deltager1.Nr AND resultater.Serie=deltager1.Serie
24   JOIN Fotballdeltagere deltager2 ON resultater.Motstander=deltager2.Nr AND resultater.Serie=deltager2.Serie
25   JOIN Fotballserier serier on resultater.Serie=serier.Nr
26 WHERE deltager1.Nr > deltager2.nr
27         ');
28         $q->execute($last_season);
29
30         while (my $ref = $q->fetchrow_hashref) {
31                 next if ($ref->{'maalfor'} == 150 && $ref->{'maalmot'} == 0);
32                 next if ($ref->{'maalfor'} == 0 && $ref->{'maalmot'} == 150);
33                 next if ($ref->{'maalfor'} == 150 && $ref->{'maalmot'} == 150);
34                 next if ($ref->{'maalfor'} == 0 && $ref->{'maalmot'} == 0);
35                 push @$games, { %$ref };
36                 $ids->{$ref->{'p1'}} = 1;
37                 $ids->{$ref->{'p2'}} = 1;
38         }
39 }
40
41 sub output_to_file {
42         my ($games, $ids) = @_;
43
44         my $tmpnam = POSIX::tmpnam();
45         open DATA, ">", $tmpnam
46                 or die "$tmpnam: $!";
47
48         printf DATA "%d\n", scalar keys %$ids;
49         for my $id (keys %$ids) {
50                 printf DATA "%d\n", $id;
51         }
52         for my $ref (@$games) {
53                 printf DATA "%d %d %d %d %f\n", $ref->{'p1'}, $ref->{'p2'}, $ref->{'maalfor'}, $ref->{'maalmot'}, $ref->{'vekt'};
54         }
55         close DATA;
56
57         return $tmpnam;
58 }
59
60 sub train_model {
61         my ($filename, $ratings, $covariances, $aux_params) = @_;
62
63         open RATINGS, "$config::base_dir/bayeswf < $filename |"
64                 or die "bayeswf: $!";
65         while (<RATINGS>) {
66                 chomp;
67                 my @x = split;
68                 if ($x[0] eq 'covariance') {
69                         push @$covariances, (join("\t", @x[1..3]));
70                 } elsif ($x[0] eq 'aux_param') {
71                         push @$aux_params, ("nb-NO" .  "\t" . $x[1] . "\t" . $x[2]);
72                 } else {
73                         push @$ratings, ($x[2] . "\t" . $x[0] . "\t" . $x[1]);
74                 }
75         }
76
77         close RATINGS;
78 }
79
80 my $dbh = DBI->connect($config::local_connstr, $config::local_username, $config::local_password)
81         or die "connect: " . $DBI::errstr;
82 $dbh->{AutoCommit} = 0;
83 $dbh->{RaiseError} = 1;
84
85 $dbh->do('SET client_min_messages TO WARNING');
86
87 my $last_season = find_last_season($dbh);
88 my @games = ();
89 my %ids = ();
90 fetch_games($dbh, $last_season, \@games, \%ids);
91 my $tmpnam = output_to_file(\@games, \%ids);
92
93 my @ratings = ();
94 my @covariances = ();
95 my @aux_params = ();
96 train_model($tmpnam, \@ratings, \@covariances, \@aux_params);
97 unlink($tmpnam);
98
99 $dbh->do('CREATE TABLE new_covariance ( player1 smallint NOT NULL, player2 smallint NOT NULL, cov float NOT NULL )');
100 $dbh->do('COPY new_covariance ( player1, player2, cov ) FROM STDIN');
101 $dbh->pg_putcopydata(join("\n", @covariances));
102 $dbh->pg_putcopyend();
103 $dbh->do('ALTER TABLE new_covariance ADD PRIMARY KEY ( player1, player2 );');
104 $dbh->do('DROP TABLE IF EXISTS covariance');
105 $dbh->do('ALTER TABLE new_covariance RENAME TO covariance');
106
107 $dbh->do('TRUNCATE aux_params');
108 $dbh->do('COPY aux_params ( kultur, id, value ) FROM STDIN');
109 $dbh->pg_putcopydata(join("\n", @aux_params));
110 $dbh->pg_putcopyend();
111
112 $dbh->do('TRUNCATE ratings');
113 $dbh->do('COPY ratings ( id, rating, rating_stddev ) FROM STDIN');
114 $dbh->pg_putcopydata(join("\n", @ratings));
115 $dbh->pg_putcopyend();
116
117 $dbh->commit;