summaryrefslogtreecommitdiff
path: root/word-aligner
diff options
context:
space:
mode:
authorChris Dyer <cdyer@allegro.clab.cs.cmu.edu>2012-11-25 00:28:07 -0500
committerChris Dyer <cdyer@allegro.clab.cs.cmu.edu>2012-11-25 00:28:07 -0500
commit6b2989db1f56257eae8209b0d8ddca2aa9b66c6d (patch)
tree36ea84656d591b2901c2ad68c031a9408507968e /word-aligner
parent6972dd2b8658bcee941e7ddaf21537326818622a (diff)
optionally optimize diagonal tension
Diffstat (limited to 'word-aligner')
-rw-r--r--word-aligner/da.h10
-rw-r--r--word-aligner/fast_align.cc47
2 files changed, 46 insertions, 11 deletions
diff --git a/word-aligner/da.h b/word-aligner/da.h
index 5e6dfa92..c979b641 100644
--- a/word-aligner/da.h
+++ b/word-aligner/da.h
@@ -17,7 +17,7 @@ struct DiagonalAlignment {
assert(m >= i);
assert(n >= j);
#endif
- return exp(feat(i, j, m, n) * alpha);
+ return exp(Feature(i, j, m, n) * alpha);
}
static double ComputeZ(const unsigned i, const unsigned m, const unsigned n, const double alpha) {
@@ -51,21 +51,21 @@ struct DiagonalAlignment {
double pct = 0;
double pcb = 0;
if (num_top) {
- pct = arithmetico_geometric_series(feat(i, ceil, m, n), UnnormalizedProb(i, ceil, m, n, alpha), ratio, d, num_top);
+ pct = arithmetico_geometric_series(Feature(i, ceil, m, n), UnnormalizedProb(i, ceil, m, n, alpha), ratio, d, num_top);
//cerr << "PCT = " << pct << endl;
}
if (floor) {
- pcb = arithmetico_geometric_series(feat(i, floor, m, n), UnnormalizedProb(i, floor, m, n, alpha), ratio, d, floor);
+ pcb = arithmetico_geometric_series(Feature(i, floor, m, n), UnnormalizedProb(i, floor, m, n, alpha), ratio, d, floor);
//cerr << "PCB = " << pcb << endl;
}
return (pct + pcb) / z;
}
- private:
- inline static double feat(const unsigned i, const unsigned j, const unsigned m, const unsigned n) {
+ inline static double Feature(const unsigned i, const unsigned j, const unsigned m, const unsigned n) {
return -fabs(double(j) / n - double(i) / m);
}
+ private:
inline static double arithmetico_geometric_series(const double a_1, const double g_1, const double r, const double d, const unsigned n) {
const double g_np1 = g_1 * pow(r, n);
const double a_n = d * (n - 1) + a_1;
diff --git a/word-aligner/fast_align.cc b/word-aligner/fast_align.cc
index 14f7cac8..9d698074 100644
--- a/word-aligner/fast_align.cc
+++ b/word-aligner/fast_align.cc
@@ -1,6 +1,9 @@
#include <iostream>
#include <cmath>
+#include <utility>
+#include <tr1/unordered_map>
+#include <boost/functional/hash.hpp>
#include <boost/program_options.hpp>
#include <boost/program_options/variables_map.hpp>
@@ -14,6 +17,7 @@
namespace po = boost::program_options;
using namespace std;
+using namespace std::tr1;
bool InitCommandLine(int argc, char** argv, po::variables_map* conf) {
po::options_description opts("Configuration options");
@@ -25,6 +29,7 @@ bool InitCommandLine(int argc, char** argv, po::variables_map* conf) {
("favor_diagonal,d", "Use a static alignment distribution that assigns higher probabilities to alignments near the diagonal")
("prob_align_null", po::value<double>()->default_value(0.08), "When --favor_diagonal is set, what's the probability of a null alignment?")
("diagonal_tension,T", po::value<double>()->default_value(4.0), "How sharp or flat around the diagonal is the alignment distribution (<1 = flat >1 = sharp)")
+ ("optimize_tension,o", "Optimize diagonal tension during EM")
("variational_bayes,v","Infer VB estimate of parameters under a symmetric Dirichlet prior")
("alpha,a", po::value<double>()->default_value(0.01), "Hyperparameter for optional Dirichlet prior")
("no_null_word,N","Do not generate from a null token")
@@ -68,7 +73,8 @@ int main(int argc, char** argv) {
const bool add_viterbi = (conf.count("no_add_viterbi") == 0);
const bool variational_bayes = (conf.count("variational_bayes") > 0);
const bool write_alignments = (conf.count("output_parameters") == 0);
- const double diagonal_tension = conf["diagonal_tension"].as<double>();
+ double diagonal_tension = conf["diagonal_tension"].as<double>();
+ bool optimize_tension = conf.count("optimize_tension");
const bool hide_training_alignments = (conf.count("hide_training_alignments") > 0);
string testset;
if (conf.count("testset")) testset = conf["testset"].as<string>();
@@ -83,8 +89,10 @@ int main(int argc, char** argv) {
TTable s2t, t2s;
TTable::Word2Word2Double s2t_viterbi;
+ unordered_map<pair<short, short>, unsigned, boost::hash<pair<short, short> > > size_counts;
double tot_len_ratio = 0;
double mean_srclen_multiplier = 0;
+ vector<double> probs;
for (int iter = 0; iter < ITERATIONS; ++iter) {
const bool final_iteration = (iter == (ITERATIONS - 1));
cerr << "ITERATION " << (iter + 1) << (final_iteration ? " (FINAL)" : "") << endl;
@@ -98,6 +106,7 @@ int main(int argc, char** argv) {
string ssrc, strg;
vector<WordID> src, trg;
double c0 = 0;
+ double emp_feat = 0;
double toks = 0;
while(true) {
getline(in, line);
@@ -115,7 +124,9 @@ int main(int argc, char** argv) {
if (iter == 0)
tot_len_ratio += static_cast<double>(trg.size()) / static_cast<double>(src.size());
denom += trg.size();
- vector<double> probs(src.size() + 1);
+ probs.resize(src.size() + 1);
+ if (iter == 0)
+ ++size_counts[make_pair<short,short>(trg.size(), src.size())];
bool first_al = true; // used for write_alignments
toks += trg.size();
for (unsigned j = 0; j < trg.size(); ++j) {
@@ -170,8 +181,11 @@ int main(int argc, char** argv) {
c0 += count;
s2t.Increment(kNULL, f_j, count);
}
- for (unsigned i = 1; i <= src.size(); ++i)
- s2t.Increment(src[i-1], f_j, probs[i] / sum);
+ for (unsigned i = 1; i <= src.size(); ++i) {
+ const double p = probs[i] / sum;
+ s2t.Increment(src[i-1], f_j, p);
+ emp_feat += DiagonalAlignment::Feature(j, i, trg.size(), src.size()) * p;
+ }
}
likelihood += log(sum);
}
@@ -186,17 +200,38 @@ int main(int argc, char** argv) {
mean_srclen_multiplier = tot_len_ratio / lc;
cerr << "expected target length = source length * " << mean_srclen_multiplier << endl;
}
+ emp_feat /= toks;
cerr << " log_e likelihood: " << likelihood << endl;
cerr << " log_2 likelihood: " << base2_likelihood << endl;
cerr << " cross entropy: " << (-base2_likelihood / denom) << endl;
cerr << " perplexity: " << pow(2.0, -base2_likelihood / denom) << endl;
+ cerr << " posterior p0: " << c0 / toks << endl;
+ cerr << " posterior al-feat: " << emp_feat << endl;
+ //cerr << " model tension: " << mod_feat / toks << endl;
+ cerr << " size counts: " << size_counts.size() << endl;
if (!final_iteration) {
+ if (favor_diagonal && optimize_tension && iter > 0) {
+ for (int ii = 0; ii < 8; ++ii) {
+ double mod_feat = 0;
+ unordered_map<pair<short,short>,unsigned>::iterator it = size_counts.begin();
+ for(; it != size_counts.end(); ++it) {
+ const pair<short,short>& p = it->first;
+ for (short j = 1; j <= p.first; ++j)
+ mod_feat += it->second * DiagonalAlignment::ComputeDLogZ(j, p.first, p.second, diagonal_tension);
+ }
+ mod_feat /= toks;
+ cerr << " " << ii + 1 << " model al-feat: " << mod_feat << " (tension=" << diagonal_tension << ")\n";
+ diagonal_tension += (emp_feat - mod_feat) * 20.0;
+ if (diagonal_tension <= 0.1) diagonal_tension = 0.1;
+ if (diagonal_tension > 14) diagonal_tension = 14;
+ }
+ cerr << " final tension: " << diagonal_tension << endl;
+ }
if (variational_bayes)
s2t.NormalizeVB(alpha);
else
s2t.Normalize();
- cerr << " p0: " << c0 / toks << endl;
- //prob_align_null *= 0.8;
+ //prob_align_null *= 0.8; // XXX
//prob_align_null += (c0 / toks) * 0.2;
prob_align_not_null = 1.0 - prob_align_null;
}