summaryrefslogtreecommitdiff
path: root/regmtl.py
diff options
context:
space:
mode:
Diffstat (limited to 'regmtl.py')
-rwxr-xr-xregmtl.py203
1 files changed, 203 insertions, 0 deletions
diff --git a/regmtl.py b/regmtl.py
new file mode 100755
index 0000000..8a976f4
--- /dev/null
+++ b/regmtl.py
@@ -0,0 +1,203 @@
+#!/usr/bin/env python2.6
+
+"""
+mmert v0.2
+multi-task mert
+Copyright 2011
+Patrick Simianer
+Heidelberg University, ICL
+"""
+
+# This file is part of MMERT.
+#
+# MMERT is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# MMERT is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MMERT. If not, see <http://www.gnu.org/licenses/>.
+
+
+import os, sys, shutil
+
+
+def read_vec_from_file(fname):
+ """ File looks like: "w1 w2 ... wn" (on one line). """
+ return [float(el) for el in open(fname, 'r').read().strip().split()]
+
+def vec2str(vector):
+ """ vec looks like: [0., 1.1, 2.2, ..., d] """
+ return " ".join([str(el) for el in vector])
+
+def get_biggest_change(vector1, vector2):
+ """ Biggest difference of two vectors (element-wise) in abs value. """
+ biggest = 0
+ idx_ = 0
+ for element in vector1:
+ diff = abs(element - vector2[idx_])
+ if diff > biggest:
+ biggest = diff
+ idx_ += 1
+ return biggest
+
+def get_avg_vec(vecs, vec_len):
+ """ 'vecs' is a list of vectors; calc arithmetic mean element-wise. """
+ avg_vec = []
+ num_vecs = len(vecs)
+ for idx_ in range(vec_len):
+ mysum = 0.
+ for vector in vecs:
+ mysum += vector[idx_]
+ avg = mysum/num_vecs
+ avg_vec.append(avg)
+ return avg_vec
+
+def get_best_points_line_idx(lines):
+ """ Line number where to find best point in a mert.log. """
+ idx_ = 0
+ for line in lines:
+ if line.startswith("Best point: "):
+ break
+ idx_ += 1
+ return idx_
+
+def get_weights_from_log(fname):
+ """ Get weights from a mert.log. """
+ logfile = open(fname, "r")
+ lines = logfile.readlines()
+ logfile.close()
+ idx_ = get_best_points_line_idx(lines)
+ return [float(el) for el in \
+ lines[idx_].split("Best point: ")[1].split("=>")[0].split()]
+
+def write_new_log_file(fname, vec_):
+ """ Write a new mert.log file with weights found in vec. """
+ logfile = open(fname, "r")
+ lines = logfile.readlines()
+ logfile.close()
+ idx_ = get_best_points_line_idx(lines)
+ log = "".join(lines[0:idx_])
+ log += "Best point: "+vec2str(vec_)+" => 99\n"
+ log += "".join(lines[idx_+1:])
+ open(fname, "w+").write(log)
+
+
+
+
+# parameters
+DIR_PREFIX = sys.argv[1] # directory prefix
+ # (for task specific directories)
+WORKDIR = sys.argv[2] # work directory
+TASKS = sys.argv[3].split(",") # task list "a,b,c..."
+CUR_IT = int(sys.argv[4]) # current (global) iteration
+NUM_WEIGHTS = int(sys.argv[5]) # dimensionality of a weight vector?
+MIN_CHANGE = float(sys.argv[6]) # min change in a vector
+ # to still continue
+LAMBDA = float(sys.argv[7]) # lambda for regularization
+FIRST_AVERAGE = bool(int(sys.argv[8])) # first average vector,
+ # 0 or self provided
+
+print " CUR_IT %s" % str(CUR_IT)
+if CUR_IT == 1:
+ print " DIR_PREFIX %s" % DIR_PREFIX
+ print " WORKDIR %s" % WORKDIR
+ print " TASKS %s" % str(TASKS)
+ print " NUM_WEIGHTS %s" % str(NUM_WEIGHTS)
+ print " MIN_CHANGE %s" % str(MIN_CHANGE)
+ print " LAMBDA %s" % str(LAMBDA)
+ print " FIRST_AVERAGE %s" % str(FIRST_AVERAGE)
+ if not FIRST_AVERAGE:
+ print " first average is 0 vector, creating file.."
+ open(WORKDIR+"/run0.avector.txt", "w+").write(\
+ " ".join(["0.0" for i in range(NUM_WEIGHTS)]))
+ else:
+ print " looking for pre-defined first average.."
+ if not os.path.exists(WORKDIR+"/run0.avector.txt"):
+ sys.stderr.write(sys.argv[0] + \
+ " ERROR: You have to provide your own run0.avector.txt \
+ containing the first average vector! arg FIRST_AVERAGE=" \
+ +str(FIRST_AVERAGE)+"\n")
+ sys.exit (1)
+
+ITERATIONS = {} # current iteration(s)
+CUR_VECS = {} # current weight vectors (from latest mert iteration)
+VEC_LEN = 0 # check vector length
+for t in TASKS:
+ print " reading vector from task %s" % t
+ ITERATIONS[t] = int(open(DIR_PREFIX + "_" + t +\
+ "/finished_step.txt").read().strip())
+ cur = get_weights_from_log(DIR_PREFIX+"_"+t+"/run"+str((ITERATIONS[t])) + \
+ ".mert.log")
+ print cur
+ VEC_LEN = len(cur)
+ if VEC_LEN != NUM_WEIGHTS:
+ sys.stderr.write(sys.argv[0] + \
+ " ERROR: vector lengths differ! (task: "+t+", len: "+str(VEC_LEN) + \
+ ", expected: "+str(NUM_WEIGHTS)+")\n")
+ CUR_VECS[t] = cur
+
+# get previous average vector
+PREV_AVG_VEC = read_vec_from_file(WORKDIR+"/run"+str(CUR_IT-1)+".avector.txt")
+print " Previous average vector (clip against):"
+print PREV_AVG_VEC
+
+# new weight vecs
+print " Calculating new weight vectors (clipping).."
+NEXT_VECS = {}
+for (t, vec) in CUR_VECS.items():
+ print " Task %s, before (current)" % t
+ print vec
+ idx = 0
+ nxt = []
+ for w in vec:
+ if w == 0:
+ nxt.append(0.0)
+ idx += 1
+ continue
+ if (w - PREV_AVG_VEC[idx] > 0):
+ nxt.append(max(PREV_AVG_VEC[idx], w - LAMBDA))
+ elif (w - PREV_AVG_VEC[idx] < 0):
+ nxt.append(min(PREV_AVG_VEC[idx], w + LAMBDA))
+ else:
+ nxt.append(w)
+ idx += 1
+ NEXT_VECS[t] = nxt
+ print " Task %s, after (next)" % t
+ print nxt
+
+# get current average vector
+AVG_VEC = get_avg_vec(NEXT_VECS.values(), VEC_LEN)
+
+print " Current average vector (after clipping):"
+print AVG_VEC
+
+# convergence?
+print " Previous average:", PREV_AVG_VEC
+print " Current average:", AVG_VEC
+BIGGEST_CHANGE = get_biggest_change(PREV_AVG_VEC, AVG_VEC)
+print " Biggest change:", BIGGEST_CHANGE
+# note: use weights from latest mert.log for eval!
+if BIGGEST_CHANGE < MIN_CHANGE:
+ print " Converged!"
+ open(WORKDIR+"/CONVERGED", "w+").close()
+
+# overwrite (and backup) mert.log
+for t in TASKS:
+ logfilename = DIR_PREFIX+"_"+t+"/run"+str(ITERATIONS[t])+".mert.log"
+ shutil.copy(logfilename, logfilename+".bak")
+ write_new_log_file(logfilename, NEXT_VECS[t])
+ open(DIR_PREFIX+"_"+t+"/weightshist", "a+").write(str(ITERATIONS[t])+"\n"+ \
+ "cur "+str(CUR_VECS[t])+"\n"+ \
+ "prev avg "+str(PREV_AVG_VEC)+"\n"+ \
+ "next "+str(NEXT_VECS[t])+"\n"+ \
+ "cur avg "+str(AVG_VEC)+"\n---\n")
+
+# write out current avg vector
+open(WORKDIR+"/run"+str(CUR_IT)+".avector.txt", "w+").write(vec2str(AVG_VEC))
+