summaryrefslogtreecommitdiff
path: root/word-aligner/aligner.pl
blob: 7eec0e423f11b136559e1b6f7aa61ac2881e9467 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#!/usr/bin/perl -w
use strict;

my $SCRIPT_DIR; BEGIN { use Cwd qw/ abs_path getcwd /; use File::Basename; $SCRIPT_DIR = dirname(abs_path($0)); push @INC, $SCRIPT_DIR; }
use Getopt::Long;
my $training_dir = "$SCRIPT_DIR/../training";
die "Can't find training dir: $training_dir" unless -d $training_dir;

my $mkcls = '/Users/redpony/software/giza/giza-pp/mkcls-v2/mkcls';
my $num_classes = 50;
my $nodes = 40;
my $pmem = "2500mb";
my $DECODER = "cdec";
GetOptions("cdec=s" => \$DECODER,
           "jobs=i" => \$nodes,
           "pmem=s" => \$pmem,
           "mkcls=s" => \$mkcls,
          ) or usage();
usage() unless (scalar @ARGV == 1);
die "Cannot find mkcls (specify with --mkcls=/path/to/mkcls) at $mkcls\n" unless -f $mkcls;
die "Cannot execute mkcls at $mkcls\n" unless -x $mkcls;

my $in_file = shift @ARGV;
die "Expected format corpus.l1-l2 where l1 & l2 are two-letter abbreviations\nfor the source and target language respectively\n" unless ($in_file =~ /^.+\.([a-z][a-z])-([a-z][a-z])$/);
my $f_lang = $1;
my $e_lang = $2;

print STDERR "Source language: $f_lang\n";
print STDERR "Target language: $e_lang\n";
print STDERR " Using mkcls in: $mkcls\n\n";
die "Don't have an orthographic normalizer for $f_lang\n" unless -f "$SCRIPT_DIR/ortho-norm/$f_lang.pl";
die "Don't have an orthographic normalizer for $e_lang\n" unless -f "$SCRIPT_DIR/ortho-norm/$e_lang.pl";

my @stages = qw(nopos relpos markov);
my @directions = qw(f-e e-f);

my $corpus = 'c';

my $cwd = getcwd();
my $align_dir = "$cwd/talign";

mkdir $align_dir;
mkdir "$align_dir/grammars";
open IN, "<$in_file" or die "Can't read $in_file: $!";
open E, ">$align_dir/grammars/corpus.e" or die "Can't write: $!";
open F, ">$align_dir/grammars/corpus.f" or die "Can't write: $!";
while(<IN>) {
  chomp;
  my ($f, $e) = split / \|\|\| /;
  die "Bad format, excepted ||| separated line" unless defined $f && defined $e;
  print F "$f\n";
  print E "$e\n";
}
close F;
close E;
close IN;
`cp $SCRIPT_DIR/makefiles/makefile.grammars $align_dir/grammars/Makefile`;
die unless $? == 0;

my @targets = qw(grammars);

for my $direction (@directions) {
  my $prev_stage = undef;
  for my $stage (@stages) {
    push @targets, "$stage-$direction";
    make_stage($stage, $direction, $prev_stage);
    $prev_stage = $stage;
  }
}

open TOPLEVEL, ">$align_dir/Makefile" or die "Can't write $align_dir/Makefile: $!";

print TOPLEVEL <<EOT;
E_LANG = $e_lang
F_LANG = $f_lang
SCRIPT_DIR = $SCRIPT_DIR
TRAINING_DIR = $training_dir
MKCLS = $mkcls
NCLASSES = $num_classes

TARGETS = @targets
PTRAIN = \$(TRAINING_DIR)/cluster-ptrain.pl --restart_if_necessary
PTRAIN_PARAMS = --gaussian_prior --sigma_squared 1.0 --max_iteration 15

export

all:
	\@failcom='exit 1'; \\
	list='\$(TARGETS)'; for subdir in \$\$list; do \\
	echo "Making \$\$subdir ..."; \\
	(cd \$\$subdir && \$(MAKE)) || eval \$\$failcom; \\
	done

clean:
	\@failcom='exit 1'; \\
	list='\$(TARGETS)'; for subdir in \$\$list; do \\
	echo "Making \$\$subdir ..."; \\
	(cd \$\$subdir && \$(MAKE) clean) || eval \$\$failcom; \\
	done
EOT
close TOPLEVEL;

print STDERR "Created alignment task. chdir to talign/ then type make.\n\n";
exit 0;

sub make_stage {
  my ($stage, $direction, $prev_stage) = @_;
  my $stage_dir = "$align_dir/$stage-$direction";
  my $first = $direction;
  $first =~ s/^(.+)-.*$/$1/;
  mkdir $stage_dir;
  my $RELPOS = "feature_function=RelativeSentencePosition $align_dir/grammars/corpus.class.$first\n";
  open CDEC, ">$stage_dir/cdec.ini" or die;
  print CDEC <<EOT;
formalism=lexcrf
intersection_strategy=full
grammar=$align_dir/grammars/corpus.$direction.lex-grammar.gz
EOT
  if ($stage =~ /relpos/) {
    print CDEC "$RELPOS\n";
  } elsif ($stage =~ /markov/) {
    print CDEC "$RELPOS\n";
    print CDEC "feature_function=MarkovJump\n";
    print CDEC "feature_function=MarkovJumpFClass $align_dir/grammars/corpus.class.$first\n";
    print CDEC "feature_function=SourcePOSBigram $align_dir/grammars/corpus.class.$first\n";
  }
  close CDEC;

  my $init_weights = "weights.init.gz: ../grammars/weights.init.gz\n\tcp \$< \$\@\n";
  if ($prev_stage) {
    $init_weights = "weights.init.gz: ../$prev_stage-$direction/weights.final.gz\n\tcp \$< \$\@\n";
  }

  open MAKE, ">$stage_dir/Makefile" or die;
  print MAKE <<EOT;
all: weights.final.gz

clean:
	\$(RM) -r ptrain weights.init.gz weights.final.gz

$init_weights

weights.final.gz: weights.init.gz cdec.ini
	\$(PTRAIN) \$(PTRAIN_PARAMS) cdec.ini ../grammars/corpus.$direction weights.init.gz
	cp ptrain/weights.final.gz weights.final.gz
	\$(RM) -r ptrain
EOT
  close MAKE;
}

sub usage {
  die <<EOT;

Usage: $0 [OPTIONS] training_corpus.fr-en

EOT
}