Try to fix the superlative error + refactored a bunch

This commit is contained in:
Panupong Pasupat 2017-08-30 20:49:51 -07:00
parent 8a987add98
commit bc878e69e5
9 changed files with 156 additions and 211 deletions

View File

@ -31,7 +31,7 @@ public class Rule {
public final SemanticFn sem; // Takes derivations corresponding to RHS categories and produces a set of derivations corresponding to LHS.
public List<Pair<String, Double>> info; // Extra info
public RuleSource source = null; // for tracking where the rule comes from when they are induced
// Cache the semanticRepn
public String getSemRepn() {
if (semRepn == null) semRepn = sem.getClass().getSimpleName();
@ -51,9 +51,9 @@ public class Rule {
public String toString() {
if (stringRepn == null) {
String semStr = sem == null? "NullSemanticFn" : sem.toString();
int maxLength = 100;
if (semStr.length() > maxLength)
semStr = String.format("%s...(%d total)", semStr.substring(0,maxLength), semStr.length());
//int maxLength = 100;
//if (semStr.length() > maxLength)
// semStr = String.format("%s...(%d total)", semStr.substring(0,maxLength), semStr.length());
stringRepn = lhs + " -> " + (rhs == null ? "" : Joiner.on(' ').join(rhs)) + " " + semStr;
}
return stringRepn;
@ -139,13 +139,13 @@ public class Rule {
else
return f == 1.0 ? false : !FloatingParser.opts.defaultIsFloating;
}
public boolean isInduced() {
double a = getInfoTag("induced");
if (a == 1.0) return true;
return false;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Rule)) return false;
@ -155,7 +155,7 @@ public class Rule {
public int hashCode() {
return this.toString().hashCode();
}
public String toJson() {
Map<String, Object> jsonMap = new LinkedHashMap<>();
jsonMap.put("lhs", lhs);

View File

@ -16,7 +16,7 @@ public class CPruneFloatingParser extends FloatingParser {
@Override
public void onBeginDataGroup(int iter, int numIters, String group) {
if (CollaborativePruner.neighbors == null) {
if (CollaborativePruner.uidToCachedNeighbors == null) {
CollaborativePruner.customGrammar.init(grammar);
CollaborativePruner.loadNeighbors();
}
@ -77,8 +77,8 @@ class CPruneFloatingParserState extends ParserState {
public boolean exploit() {
LogInfo.begin_track("Exploit");
CollaborativePruner.initialize(ex, CollaborativePruner.Mode.EXPLOIT);
Parser exploitParser = new FloatingParser(
new Parser.Spec(new MiniGrammar(CollaborativePruner.predictedRules), parser.extractor, parser.executor, parser.valueEvaluator));
Grammar miniGrammar = new MiniGrammar(CollaborativePruner.predictedRules);
Parser exploitParser = new FloatingParser(new Parser.Spec(miniGrammar, parser.extractor, parser.executor, parser.valueEvaluator));
ParserState exploitParserState = exploitParser.newParserState(params, ex, computeExpectedCounts);
exploitParserState.infer();
predDerivations.clear();
@ -105,6 +105,9 @@ class MiniGrammar extends Grammar {
public MiniGrammar(List<Rule> rules) {
this.rules.addAll(rules);
LogInfo.begin_track("MiniGrammar Rules");
for (Rule rule : rules) LogInfo.logs("%s", rule);
LogInfo.end_track();
}
}

View File

@ -5,7 +5,6 @@ import java.util.*;
import fig.basic.*;
import edu.stanford.nlp.sempre.*;
import fig.basic.LogInfo;
/**
* Static class for collaborative pruning.
@ -20,7 +19,7 @@ public class CollaborativePruner {
public int maxPredictedPatterns = Integer.MAX_VALUE;
@Option(gloss = "Maximum number of derivations per example")
public int maxDerivations = 5000;
@Option(gloss = "Maximum number of exporation iterations")
@Option(gloss = "Maximum number of times to fall back to exploration")
public int maxExplorationIters = Integer.MAX_VALUE;
}
@ -37,9 +36,9 @@ public class CollaborativePruner {
// Global variables
// Nearest neighbors
static Map<String, List<String>> neighbors;
static Map<String, List<String>> uidToCachedNeighbors;
// uid => pattern
static Map<String, Pattern> consistentPattern = new HashMap<>();
static Map<String, FormulaPattern> consistentPattern = new HashMap<>();
// patternString => customRuleString
static Map<String, Set<String>> customRules = new HashMap<>();
// set of patternStrings
@ -47,7 +46,7 @@ public class CollaborativePruner {
// Example-level variables
public static boolean foundConsistentDerivation = false;
public static Map<String, Pattern> predictedPatterns;
public static Map<String, FormulaPattern> predictedPatterns;
public static List<Rule> predictedRules;
/**
@ -59,8 +58,8 @@ public class CollaborativePruner {
LogInfo.logs("neighborFilePath is null.");
return;
}
LogInfo.logs("loading Neighbors " + opts.neighborFilePath);
Map<String, List<String>> tmpMap = new HashMap<>();
LogInfo.begin_track("Loading cached neighbors from %s", opts.neighborFilePath);
uidToCachedNeighbors = new HashMap<>();
try {
BufferedReader reader = IOUtils.openIn(opts.neighborFilePath);
String line;
@ -68,28 +67,13 @@ public class CollaborativePruner {
String[] tokens = line.split("\t");
String uid = tokens[0];
String[] nids = tokens[1].split(",");
tmpMap.put(uid, Arrays.asList(nids));
uidToCachedNeighbors.put(uid, Arrays.asList(nids));
}
reader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
neighbors = tmpMap;
}
public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
List<Map.Entry<K, V>> list = new LinkedList<Map.Entry<K, V>>(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<K, V>>() {
public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) {
return (o1.getValue()).compareTo(o2.getValue());
}
});
Map<K, V> result = new LinkedHashMap<K, V>();
for (Map.Entry<K, V> entry : list) {
result.put(entry.getKey(), entry.getValue());
}
return result;
LogInfo.end_track();
}
public static void initialize(Example ex, Mode mode) {
@ -103,39 +87,42 @@ public class CollaborativePruner {
}
static void preprocessExample(Example ex) {
Map<String, Pattern> patternFreqMap = new HashMap<>();
List<String> cachedNeighbors = neighbors.get(ex.id);
Map<String, FormulaPattern> patternFreqMap = new HashMap<>();
List<String> cachedNeighbors = uidToCachedNeighbors.get(ex.id);
int total = 0;
// Gather the neighbors
if (opts.maxNumNeighbors > 0) {
for (String nid : cachedNeighbors) {
// Only get examples that have been previously processed
// Only get examples that have been previously processed + found a consistent formula
if (!consistentPattern.containsKey(nid))
continue;
String neighborPattern = consistentPattern.get(nid).pattern;
if (!patternFreqMap.containsKey(neighborPattern))
patternFreqMap.put(neighborPattern, new Pattern(neighborPattern, 0, 0));
patternFreqMap.get(neighborPattern).frequency += 1;
patternFreqMap.put(neighborPattern, new FormulaPattern(neighborPattern, 0));
patternFreqMap.get(neighborPattern).frequency++;
total++;
if (total >= opts.maxNumNeighbors)
break;
}
} else {
for (String patternString : allConsistentPatterns) {
patternFreqMap.put(patternString, new Pattern(patternString, 0, 1));
patternFreqMap.put(patternString, new FormulaPattern(patternString, 1));
}
}
// Sort by frequency (more frequent = smaller; see FormulaPattern.compareTo)
List<Map.Entry<String, FormulaPattern>> patternFreqEntries = new ArrayList<>(patternFreqMap.entrySet());
patternFreqEntries.sort(new ValueComparator<>(false));
// Gather the patterns
patternFreqMap = sortByValue(patternFreqMap);
LogInfo.begin_track("Predicted patterns");
int rank = 0;
Set<String> predictedRulesStrings = new HashSet<>();
predictedPatterns = new HashMap<>();
LogInfo.begin_track("Predicted patterns");
for (Map.Entry<String, Pattern> entry : patternFreqMap.entrySet()) {
Pattern newPattern = entry.getValue();
for (Map.Entry<String, FormulaPattern> entry : patternFreqEntries) {
FormulaPattern newPattern = entry.getValue();
predictedPatterns.put(newPattern.pattern, newPattern);
predictedRulesStrings.addAll(customRules.get(newPattern.pattern));
LogInfo.logs((rank + 1) + ". " + newPattern.pattern + " (" + newPattern.frequency + ")");
@ -143,7 +130,6 @@ public class CollaborativePruner {
if (rank >= opts.maxPredictedPatterns)
break;
}
// Gather the rules
predictedRules = customGrammar.getRules(predictedRulesStrings);
LogInfo.end_track();
@ -154,7 +140,7 @@ public class CollaborativePruner {
|| deriv.cat.equals("$LEMMA_TOKEN") || deriv.cat.equals("$LEMMA_PHRASE")) {
return deriv.cat;
} else {
return PatternInfo.convertToIndexedPattern(deriv);
return FormulaPattern.convertToIndexedPattern(deriv);
}
}
@ -176,33 +162,20 @@ public class CollaborativePruner {
LogInfo.logs("Found consistent deriv: %s", deriv);
String patternString = getPatternString(deriv);
Pattern newConsistentPattern = new Pattern(patternString, 0, 0);
FormulaPattern newConsistentPattern = new FormulaPattern(patternString, 0);
newConsistentPattern.score = deriv.getScore();
if (!consistentPattern.containsKey(uid)) {
FormulaPattern oldConsistentPattern = consistentPattern.get(uid);
if (oldConsistentPattern == null || newConsistentPattern.score > oldConsistentPattern.score) {
addRules(patternString, deriv, ex);
consistentPattern.put(uid, newConsistentPattern);
allConsistentPatterns.add(patternString);
} else {
Pattern oldConsistentPattern = consistentPattern.get(uid);
if (newConsistentPattern.score > oldConsistentPattern.score) {
addRules(patternString, deriv, ex);
consistentPattern.put(uid, newConsistentPattern);
allConsistentPatterns.add(patternString);
}
}
}
}
public static Pattern getConsistentPattern(Example ex) {
public static FormulaPattern getConsistentPattern(Example ex) {
return consistentPattern.get(ex.id);
}
public static Pattern getPattern(Example ex, Derivation deriv) {
if (mode == Mode.EXPLORE)
return null;
if (!deriv.isRootCat())
return null;
return predictedPatterns.get(getPatternString(deriv));
}
}

View File

@ -13,10 +13,11 @@ public class CustomGrammar extends Grammar {
public static Options opts = new Options();
public static final Set<String> baseCategories = new HashSet<String>(Arrays.asList("$Unary", "$Binary", "$Entity", "$Property"));
public static final Set<String> baseCategories = new HashSet<String>(Arrays.asList(
Rule.tokenCat, Rule.phraseCat, Rule.lemmaTokenCat, Rule.lemmaPhraseCat,
"$Unary", "$Binary", "$Entity", "$Property"));
ArrayList<Rule> baseRules = new ArrayList<>();
// symbolicFormulas => symbolicFormula ID
Map<String, Integer> symbolicFormulas = new HashMap<>();
// indexedSymbolicFormula => customRuleString
@ -25,11 +26,6 @@ public class CustomGrammar extends Grammar {
Map<String, Set<Rule>> customBinarizedRules = new HashMap<>();
public void init(Grammar initGrammar) {
baseCategories.add(Rule.tokenCat);
baseCategories.add(Rule.phraseCat);
baseCategories.add(Rule.lemmaTokenCat);
baseCategories.add(Rule.lemmaPhraseCat);
baseRules = new ArrayList<>();
for (Rule rule : initGrammar.getRules()) {
if (baseCategories.contains(rule.lhs)) {
@ -116,8 +112,17 @@ public class CustomGrammar extends Grammar {
// ============================================================
private static String safeReplace(String formula, String target, String replacement) {
// (argmin 1 1 ...) and (argmax 1 1 ...) are troublesome
String before = formula, targetBefore = target;
formula = formula.replace("(argmin (number 1) (number 1)", "(ARGMIN");
formula = formula.replace("(argmax (number 1) (number 1)", "(ARGMAX");
target = target.replace("(argmin (number 1) (number 1)", "(ARGMIN");
target = target.replace("(argmax (number 1) (number 1)", "(ARGMAX");
formula = formula.replace(target + ")", replacement + ")");
formula = formula.replace(target + " ", replacement + " ");
formula = formula.replace("(ARGMIN", "(argmin (number 1) (number 1)");
formula = formula.replace("(ARGMAX", "(argmax (number 1) (number 1)");
LogInfo.logs("REPLACE: [%s | %s] %s | %s", targetBefore, replacement, before, formula);
return formula;
}

View File

@ -0,0 +1,102 @@
package edu.stanford.nlp.sempre.cprune;
import java.util.regex.Pattern;
import edu.stanford.nlp.sempre.Derivation;
import fig.basic.LogInfo;
public class FormulaPattern implements Comparable<FormulaPattern> {
public String pattern;
public Integer frequency;
public Double score;
public FormulaPattern(String pattern, Integer frequency) {
this.pattern = pattern;
this.frequency = frequency;
}
public Double complexity() {
return (double) (pattern.length() - pattern.replace("(@R", "***").replace("(", "").length());
}
@Override
public String toString() {
return "(" + pattern + ", " + frequency + ")";
}
@Override
public int compareTo(FormulaPattern that) {
if (this.frequency > that.frequency) {
return -1;
} else if (this.frequency < that.frequency) {
return 1;
} else {
return this.complexity().compareTo(that.complexity());
}
}
// ============================================================
// Utilities
// ============================================================
private static Pattern reverseRelation = Pattern.compile("!(fb:[._a-z0-9]+)");
private static Pattern varName = Pattern.compile("\\((lambda|var) [a-z0-9]+");
private static Pattern compare = Pattern.compile("(<=|>=|>|<)");
public static String convertToIndexedPattern(Derivation deriv) {
String formula = deriv.formula.toString();
// These can interfere with (number 1)
formula = formula.replace("argmax (number 1) (number 1)", "argmax");
formula = formula.replace("argmin (number 1) (number 1)", "argmin");
formula = removePropertyPredicates(formula);
formula = CustomGrammar.getIndexedSymbolicFormula(deriv, formula);
formula = formula.replace("fb:type.object.type fb:type.row", "@type @row");
formula = reverseRelation.matcher(formula).replaceAll("(reverse $1)");
formula = formula.replace("fb:row.row.index", "(reverse (lambda x ((reverse @index) (var x))))");
formula = formula.replace("fb:row.row.next", "@next");
formula = varName.matcher(formula).replaceAll("($1 x");
formula = formula.replaceAll("\\s+", " ");
formula = formula.replace("reverse", "@R");
formula = compare.matcher(formula).replaceAll("@compare");
LogInfo.logs("PATTERN: %s -> %s", deriv.formula, formula);
return formula;
}
private static Pattern cellProperty = Pattern.compile("!?fb:cell\\.cell\\.[_a-z0-9]+|\\(reverse fb:cell\\.cell\\.[_a-z0-9]+\\)");
/**
* Remove cell property relations (fb:cell.cell.*)
*/
public static String removePropertyPredicates(String formula) {
formula = cellProperty.matcher(formula).replaceAll("@PPT");
while (formula.contains("@PPT")) {
int begin = formula.indexOf("(@PPT");
if (begin == -1) {
formula = formula.replace("@PPT", "");
break;
}
// Find the matching parenthesis
int count = 1;
for (int i = begin + 1; i < formula.length(); i++) {
if (formula.charAt(i) == '(') {
count++;
} else if (formula.charAt(i) == ')') {
count--;
if (count == 0) {
int end = i;
formula = formula.substring(0, begin) + formula.substring(begin + 6, end) + formula.substring(end + 1, formula.length());
break;
}
}
if (i == formula.length() - 1) {
LogInfo.fails("Unbalanced parentheses: %s", formula);
}
}
}
return formula;
}
}

View File

@ -1,34 +0,0 @@
package edu.stanford.nlp.sempre.cprune;
public class Pattern implements Comparable<Pattern> {
public String pattern;
public Integer rank;
public Integer frequency;
public Double score;
public Pattern(String pattern, Integer rank, Integer frequency) {
this.pattern = pattern;
this.rank = rank;
this.frequency = frequency;
}
public Double complexity() {
return (double) (pattern.length() - pattern.replace("(@R", "***").replace("(", "").length());
}
@Override
public String toString() {
return "(" + pattern + ", " + rank + ", " + frequency + ")";
}
@Override
public int compareTo(Pattern that) {
if (this.frequency > that.frequency) {
return -1;
} else if (this.frequency < that.frequency) {
return 1;
} else {
return this.complexity().compareTo(that.complexity());
}
}
}

View File

@ -1,92 +0,0 @@
package edu.stanford.nlp.sempre.cprune;
import java.util.*;
import edu.stanford.nlp.sempre.*;
public class PatternInfo {
Set<String> baseCategories = new HashSet<String>(Arrays.asList("$Unary", "$Binary", "$Entity", "$Property"));
public static String removePropertyPredicates(String formula) {
formula = RegexReplaceManager.replace(formula, "fb:cell\\.cell\\.[_0-9a-z]+", "@PPT");
formula = formula.replace("(reverse @PPT)", "@PPT");
while (formula.contains("@PPT")) {
int begin = formula.indexOf("(@PPT");
if (begin == -1) {
formula = formula.replace("@PPT", "");
;
break;
}
int count = 1;
for (int i = begin + 1; i < formula.length(); i++) {
if (formula.charAt(i) == '(') {
count += 1;
} else if (formula.charAt(i) == ')') {
count -= 1;
}
if (count == 0) {
int end = i;
formula = formula.substring(0, begin) + formula.substring(begin + 6, end) + formula.substring(end + 1, formula.length());
break;
}
if (i == formula.length() - 1) {
System.out.println(formula);
}
}
}
return formula;
}
public static String convertToPattern(Derivation deriv) {
String formula = deriv.formula.toString();
// These can interfere with (number 1)
formula = formula.replace("argmax (number 1) (number 1)", "argmax");
formula = formula.replace("argmin (number 1) (number 1)", "argmin");
formula = removePropertyPredicates(formula);
formula = formula.replace("fb:type.object.type fb:type.row", "@type @row");
formula = RegexReplaceManager.replace(formula, "!fb:[._0-9a-z]+", "(reverse $0)").replace("reverse !fb", "reverse fb");
formula = formula.replace("fb:row.row.index", "(reverse (lambda x ((reverse @index) (var x))))");
formula = formula.replace("fb:row.row.next", "@next");
formula = RegexReplaceManager.replace(formula, "\\(lambda [a-z]", "\\(lambda x");
formula = RegexReplaceManager.replace(formula, "\\(var [a-z]\\)", "\\(var x\\)");
formula = RegexReplaceManager.replace(formula, "fb:row\\.row\\.[_0-9a-z]+", "\\$Binary");
formula = RegexReplaceManager.replace(formula, "fb:cell\\.cell\\.[_0-9a-z]+", "\\$Property");
formula = RegexReplaceManager.replace(formula, "fb:cell_[_0-9a-z]+\\.[_0-9a-z]+", "\\$Entity");
formula = RegexReplaceManager.replace(formula, "\\(number [0-9]+[.]?[0-9]+\\)", "\\$Entity");
formula = RegexReplaceManager.replace(formula, "\\(number [0-9]+\\)", "\\$Entity");
formula = RegexReplaceManager.replace(formula, "\\(date [-]?[0-9]+ [-]?[0-9]+ [-]?[0-9]+\\)", "\\$Entity");
formula = RegexReplaceManager.replace(formula, "[ ]+", " ");
formula = formula.replace("reverse", "@R");
formula = RegexReplaceManager.replace(formula, "(<=|>=|>|<)", "@compare");
return formula;
}
public static String convertToIndexedPattern(Derivation deriv) {
String formula = deriv.formula.toString();
// These can interfere with (number 1)
formula = formula.replace("argmax (number 1) (number 1)", "argmax");
formula = formula.replace("argmin (number 1) (number 1)", "argmin");
formula = removePropertyPredicates(formula);
formula = CustomGrammar.getIndexedSymbolicFormula(deriv, formula);
formula = formula.replace("fb:type.object.type fb:type.row", "@type @row");
formula = RegexReplaceManager.replace(formula, "!fb:[._0-9a-z]+", "(reverse $0)").replace("reverse !fb", "reverse fb");
formula = formula.replace("fb:row.row.index", "(reverse (lambda x ((reverse @index) (var x))))");
formula = formula.replace("fb:row.row.next", "@next");
formula = RegexReplaceManager.replace(formula, "\\(lambda [a-z]", "\\(lambda x");
formula = RegexReplaceManager.replace(formula, "\\(var [a-z]\\)", "\\(var x\\)");
formula = RegexReplaceManager.replace(formula, "[ ]+", " ");
formula = formula.replace("reverse", "@R");
formula = RegexReplaceManager.replace(formula, "(<=|>=|>|<)", "@compare");
return formula;
}
}

View File

@ -1,15 +0,0 @@
package edu.stanford.nlp.sempre.cprune;
import java.util.*;
public class RegexReplaceManager {
static Map<String, java.util.regex.Pattern> dict = new HashMap<>();
public static String replace(String source, String regex, String replacement) {
if (!dict.containsKey(regex)) {
dict.put(regex, java.util.regex.Pattern.compile(regex));
}
java.util.regex.Pattern regexPattern = dict.get(regex);
return regexPattern.matcher(source).replaceAll(replacement);
}
}

View File

@ -292,6 +292,9 @@ class LambdaDCSCoreLogic {
computeUnary(superlative.rank, typeHint.unrestrictedUnary()).range());
int count = DenotationUtils.getSinglePositiveInteger(
computeUnary(superlative.count, typeHint.unrestrictedUnary()).range());
if (rank != 1 || count != 1) {
LogInfo.logs("Superlative WTF: %s | rank %d | count %d", formula, rank, count);
}
Unarylike headD = computeUnary(superlative.head, typeHint);
Binarylike relationD;
if (superlative.relation instanceof ReverseFormula) {