{"action":"created","comment":{"url":"https://api.github.com/repos/IllinoisCogComp/saul/pulls/comments/81505340","pull_request_review_id":2480301,"id":81505340,"diff_hunk":"@@ -0,0 +1,587 @@\n+package edu.illinois.cs.cogcomp.saul.learn;\n+\n+import akka.japi.tuple.Tuple4;\n+import edu.illinois.cs.cogcomp.core.datastructures.vectors.ExceptionlessInputStream;\n+import edu.illinois.cs.cogcomp.core.datastructures.vectors.ExceptionlessOutputStream;\n+import edu.illinois.cs.cogcomp.lbjava.classify.*;\n+import edu.illinois.cs.cogcomp.lbjava.learn.Learner;\n+\n+import weka.core.Attribute;\n+import weka.core.FastVector;\n+import weka.core.Instance;\n+import weka.core.Instances;\n+\n+import java.io.ObjectInputStream;\n+import java.io.ObjectOutputStream;\n+import java.io.PrintStream;\n+import java.util.ArrayList;\n+import java.util.Enumeration;\n+import java.util.List;\n+\n+\n+/**\n+ * Translates Saul's internal problem representation into that which can be handled by WEKA\n+ * learning algorithms. This translation involves storing all lbjavaInstances in memory so they can be\n+ * passed to WEKA at one time.\n+ * <p>\n+ * <p>\n+ * WEKA must be available on your <code>CLASSPATH</code> in order to use this class. WEKA source\n+ * code and pre-compiled jar distributions are available at: <a\n+ * href=\"http://www.cs.waikato.ac.nz/ml/weka/\">http://www.cs.waikato.ac.nz/ml/weka/</a>\n+ * <p>\n+ * <p>\n+ * To use this class in a Java application, the following restrictions must be recognized:\n+ * <ul>\n+ * <li> {@link #doneLearning()} must be called before calls to {@link #classify(Object)} can be made.\n+ * <li>After {@link #doneLearning()} is called, {@link #learn(Object)} may not be called without\n+ * first calling {@link #forget()}.\n+ * </ul>\n+ *\n+ * @author Taher Rahgooy\n+ **/\n+\n+public class SaulWekaWrapper extends Learner {\n+    /**\n+     * Default for the {@link #baseClassifier} field.\n+     */\n+    public static final weka.classifiers.Classifier defaultBaseClassifier =\n+            new weka.classifiers.bayes.NaiveBayes();\n+\n+    /**\n+     * Stores the instance of the WEKA classifier which we are training; default is\n+     * <code>weka.classifiers.bayes.NaiveBayes</code>.\n+     **/\n+    protected weka.classifiers.Classifier baseClassifier;\n+    /**\n+     * Stores a fresh instance of the WEKA classifier for the purposes of forgetting.\n+     **/\n+    protected weka.classifiers.Classifier freshClassifier;\n+    /**\n+     * Information about the features this learner takes as input stored here.\n+     **/\n+    protected FastVector attributeInfo;\n+    /**\n+     * The main collection of weka Instance objects.\n+     */\n+    protected Instances wekaInstances;\n+    /**\n+     * A buffer for lbjava instances.\n+     */\n+    protected List<Tuple4<int[], double[], int[], double[]>> lbjavaInstances;\n+    /**\n+     * Indicates whether the {@link #doneLearning()} method has been called and the\n+     * {@link #forget()} method has not yet been called.\n+     **/\n+    protected boolean trained = false;\n+    /**\n+     * The label producing classifier's allowable values.\n+     */\n+    protected String[] allowableValues;\n+\n+\n+    /**\n+     * Empty constructor. Instantiates this wrapper with the default learning algorithm:\n+     * <code>weka.classifiers.bayes.NaiveBayes</code>. Attribute information must be provided before\n+     * any learning can occur.\n+     **/\n+    public SaulWekaWrapper() {\n+        this(\"\");\n+    }\n+\n+    /**\n+     * Partial constructor; attribute information must be provided before any learning can occur.\n+     *\n+     * @param base The classifier to be used in this system.\n+     **/\n+    public SaulWekaWrapper(weka.classifiers.Classifier base) {\n+        this(\"\", base);\n+    }\n+\n+    /**\n+     * Empty constructor. Instantiates this wrapper with the default learning algorithm:\n+     * <code>weka.classifiers.bayes.NaiveBayes</code>. Attribute information must be provided before\n+     * any learning can occur.\n+     *\n+     * @param n The name of the classifier.\n+     **/\n+    public SaulWekaWrapper(String n) {\n+        this(n, defaultBaseClassifier);\n+    }\n+\n+\n+    /**\n+     * Full Constructor.\n+     *\n+     * @param n    The name of the classifier\n+     * @param base The classifier to be used in this system.\n+     *             have.\n+     **/\n+    public SaulWekaWrapper(String n, weka.classifiers.Classifier base) {\n+        super(n);\n+        baseClassifier = base;\n+        freshClassifier = base;\n+        lbjavaInstances = new ArrayList<>();\n+    }\n+\n+\n+    /**\n+     * This learner's output type is <code>\"mixed%\"</code>.\n+     */\n+    public String getOutputType() {\n+        return \"mixed%\";\n+    }\n+\n+\n+    /**\n+     * Sets the labeler.\n+     *\n+     * @param l A labeling classifier.\n+     **/\n+    public void setLabeler(Classifier l) {\n+        super.setLabeler(l);\n+        allowableValues = l == null ? null : l.allowableValues();\n+    }\n+\n+\n+    /**\n+     * Returns the array of allowable values that a feature returned by this classifier may take.\n+     *\n+     * @return The allowable values of this learner's labeler, or an array of length zero if the\n+     * labeler has not yet been established or does not specify allowable values.\n+     **/\n+    public String[] allowableValues() {\n+        if (allowableValues == null)\n+            return new String[0];\n+        return allowableValues;\n+    }\n+\n+\n+    /**\n+     * Since WEKA classifiers cannot learn online, this method causes no actual learning to occur,\n+     * it simply creates an object from this example and adds it to a set of\n+     * lbjavaInstances from which the classifier will be built once {@link #doneLearning()} is called.\n+     **/\n+    public void learn(int[] exampleFeatures, double[] exampleValues, int[] exampleLabels,\n+                      double[] labelValues) {\n+        lbjavaInstances.add(new Tuple4<>(exampleFeatures, exampleValues, exampleLabels, labelValues));\n+    }\n+\n+\n+    /**\n+     * This method makes one or more decisions about a single object, returning those decisions as\n+     * Features in a vector.\n+     *\n+     * @param exampleFeatures The example's array of feature indices.\n+     * @param exampleValues   The example's array of feature values.\n+     * @return A feature vector with a single feature containing the prediction for this example.\n+     **/\n+    public FeatureVector classify(int[] exampleFeatures, double[] exampleValues) {\n+        if (!trained) {\n+            System.err.println(\"WekaWrapper: Error - Cannot make a classification with an \"\n+                    + \"untrained classifier.\");\n+            new Exception().printStackTrace();\n+            System.exit(1);\n+        }\n+\n+        /*\n+         * Assuming that the first Attribute in our attributeInfo vector is the class attribute,\n+         * decide which case we are in\n+         */\n+        Attribute classAtt = (Attribute) attributeInfo.elementAt(0);\n+\n+        if (classAtt.isNominal() || classAtt.isString()) {\n+            double[] dist = getDistribution(exampleFeatures, exampleValues);\n+            int best = 0;\n+            for (int i = 1; i < dist.length; ++i)\n+                if (dist[i] > dist[best])\n+                    best = i;\n+\n+            Feature label = labelLexicon.lookupKey(best);\n+            if (label == null)\n+                return new FeatureVector();\n+            String value = label.getStringValue();\n+\n+            return new FeatureVector(new DiscretePrimitiveStringFeature(containingPackage, name,\n+                    \"\", value, valueIndexOf(value), (short) allowableValues().length));\n+        } else if (classAtt.isNumeric()) {\n+            return new FeatureVector(new RealPrimitiveStringFeature(containingPackage, name, \"\",\n+                    getDistribution(exampleFeatures, exampleValues)[0]));\n+        } else {\n+            System.err.println(\"WekaWrapper: Error - illegal class type.\");\n+            new Exception().printStackTrace();\n+            System.exit(1);\n+        }\n+\n+        return new FeatureVector();\n+    }\n+\n+    public String discreteValue(int[] f, double[] v) {\n+        return classify(f, v).discreteValueArray()[0];\n+    }\n+\n+    public double realValue(int[] f, double[] v) {\n+        return classify(f, v).realValueArray()[0];\n+    }\n+\n+    /**\n+     * Returns a discrete distribution of the classifier's prediction values.\n+     *\n+     * @param exampleFeatures The example's array of feature indices.\n+     * @param exampleValues   The example's array of feature values.\n+     **/\n+    protected double[] getDistribution(int[] exampleFeatures, double[] exampleValues) {\n+        if (!trained) {\n+            System.err.println(\"WekaWrapper: Error - Cannot make a classification with an \"\n+                    + \"untrained classifier.\");\n+            new Exception().printStackTrace();\n+            System.exit(1);\n+        }\n+\n+        Instance inQuestion =\n+                makeInstance(exampleFeatures, exampleValues, new int[0], new double[0]);\n+\n+        /*\n+         * For Numerical class values, this will return an array of size 1, containing the class\n+         * prediction. For Nominal classes, an array of size equal to that of the class list,\n+         * representing probabilities. For String classes, ?\n+         */\n+        double[] dist = null;\n+        try {\n+            dist = baseClassifier.distributionForInstance(inQuestion);\n+        } catch (Exception e) {\n+            System.err.println(\"WekaWrapper: Error while computing distribution.\");\n+            e.printStackTrace();\n+            System.exit(1);\n+        }\n+\n+        if (dist.length == 0) {\n+            System.err.println(\"WekaWrapper: Error - The base classifier returned an empty \"\n+                    + \"probability distribution when attempting to classify an \" + \"example.\");\n+            new Exception().printStackTrace();\n+            System.exit(1);\n+        }\n+\n+        return dist;\n+    }\n+\n+\n+    /**\n+     * Destroys the learned version of the WEKA classifier and empties the {@link #wekaInstances}\n+     * collection of wekaInstances.\n+     **/\n+    public void forget() {\n+        super.forget();\n+\n+        try {\n+            baseClassifier = weka.classifiers.Classifier.makeCopy(freshClassifier);\n+        } catch (Exception e) {\n+            System.err.println(\"LBJava ERROR: WekaWrapper.forget: Can't copy classifier:\");\n+            e.printStackTrace();\n+            System.exit(1);\n+        }\n+\n+        lbjavaInstances = new ArrayList<>();\n+        wekaInstances = new Instances(name, attributeInfo, 0);\n+        wekaInstances.setClassIndex(0);\n+        trained = false;\n+    }\n+\n+\n+    private void initializeAttributes() {\n+        attributeInfo = new FastVector(lexicon.size() + 1);\n+        /*\n+         * Here, we assume that if either the labels FeatureVector is empty of features, or is null,\n+         * then this example is to be considered unlabeled.\n+         */\n+        if (labelLexicon.size() < 1) {\n+            System.err.println(\"WekaWrapper: Error - Weka Instances may only take a single class \"\n+                    + \"value, \");\n+            new Exception().printStackTrace();\n+            System.exit(1);\n+        } else {\n+            Feature label = labelLexicon.lookupKey(0);\n+            if (!label.isDiscrete()) {\n+                Attribute a = new Attribute(label.getStringIdentifier());\n+                attributeInfo.addElement(a);\n+            } else {\n+                FastVector valueVector = new FastVector(labelLexicon.size());\n+                for (int v = 0; v < labelLexicon.size(); v++)\n+                    valueVector.addElement(labelLexicon.lookupKey(v).getStringValue());\n+                Attribute a = new Attribute(label.getGeneratingClassifier(), valueVector);\n+                attributeInfo.addElement(a);\n+            }\n+        }\n+        /*\n+         * Construct weka attribute for each lexicon entry.\n+         * If entry is discrete use a binary attribute\n+         * If it is real, use a numerical attribute\n+         */\n+        FastVector binaryValues = new FastVector(2);\n+        binaryValues.addElement(\"0\");\n+        binaryValues.addElement(\"1\");\n+        for (int featureIndex = 0; featureIndex < lexicon.size(); ++featureIndex) {\n+            Feature f = lexicon.lookupKey(featureIndex);\n+            Attribute a = f.isDiscrete() ?\n+                    new Attribute(f.toString(), binaryValues) :\n+                    new Attribute(f.toString());\n+\n+            attributeInfo.addElement(a);\n+        }\n+\n+        // The first attribute is the label\n+        wekaInstances = new Instances(name, attributeInfo, 0);\n+        wekaInstances.setClassIndex(0);\n+    }\n+\n+\n+    /**\n+     * Creates a WEKA Instance object out of a {@link FeatureVector}.\n+     **/\n+    private Instance makeInstance(int[] exampleFeatures, double[] exampleValues,\n+                                  int[] exampleLabels, double[] labelValues) {\n+\n+        // Initialize an Instance object\n+        Instance inst = new Instance(attributeInfo.size());\n+\n+        // Acknowledge that this instance will be a member of our dataset 'wekaInstances'\n+        inst.setDataset(wekaInstances);\n+\n+        // set all nominal feature values to 0, which means those features are not used in this example\n+        for(int i=1; i< attributeInfo.size();i++)\n+            if(inst.attribute(i).isNominal())\n+                inst.setValue(i, \"0\");\n+\n+        // Assign values for its attributes\n+        /*\n+         * Since we are iterating through this example's feature list, which does not contain the\n+         * label feature (the label feature is the first in the 'attribute' list), we set attIndex\n+         * to at exampleFeatures[featureIndex] + 1, while we start featureIndex at 0.\n+         */\n+        for (int featureIndex = 0; featureIndex < exampleFeatures.length; ++featureIndex) {\n+            int attIndex = exampleFeatures[featureIndex] + 1;\n+            Feature f = lexicon.lookupKey(exampleFeatures[featureIndex]);\n+\n+            // if the feature does not exist, do nothing. this may occur in test set.\n+            if (f == null)\n+                continue;\n+            Attribute att = (Attribute) attributeInfo.elementAt(attIndex);\n+\n+            // make sure the feature and the attribute match\n+            if (!(att.name().equals(f.toString()))) {\n+                System.err.println(\"WekaWrapper: Error - makeInstance encountered a misaligned \"\n+                        + \"attribute-feature pair.\");\n+                System.err.println(\"  \" + att.name() + \" and \" + f.toString()\n+                        + \" should have been identical.\");\n+                new Exception().printStackTrace();\n+                System.exit(1);\n+            }\n+            if (f.isDiscrete())\n+                inst.setValue(attIndex, \"1\"); // this feature is used in this example so we set it to \"1\"\n+            else\n+                inst.setValue(attIndex, exampleValues[featureIndex]);\n+\n+        }\n+\n+        /*\n+         * Here, we assume that if either the labels FeatureVector is empty of features, or is null,\n+         * then this example is to be considered unlabeled.\n+         */\n+        if (exampleLabels.length == 0) {\n+            inst.setClassMissing();\n+        } else if (exampleLabels.length > 1) {\n+            System.err.println(\"WekaWrapper: Error - Weka Instances may only take a single class \"\n+                    + \"value, \");\n+            new Exception().printStackTrace();\n+            System.exit(1);\n+        } else {\n+            Feature label = labelLexicon.lookupKey(exampleLabels[0]);\n+\n+            // make sure the label feature matches the n 0'th attribute\n+            if (!(label.getGeneratingClassifier().equals(((Attribute) attributeInfo.elementAt(0))\n+                    .name()))) {\n+                System.err.println(\"WekaWrapper: Error - makeInstance found the wrong label name.\");\n+                new Exception().printStackTrace();\n+                System.exit(1);\n+            }\n+\n+            if (!label.isDiscrete())\n+                inst.setValue(0, labelValues[0]);\n+            else\n+                inst.setValue(0, label.getStringValue());\n+        }\n+\n+        return inst;\n+    }\n+\n+\n+    /**\n+     * Produces a set of scores indicating the degree to which each possible discrete classification\n+     * value is associated with the given example object.\n+     **/\n+    public ScoreSet scores(int[] exampleFeatures, double[] exampleValues) {\n+        double[] dist = getDistribution(exampleFeatures, exampleValues);\n+\n+        /*\n+         * Assuming that the first Attribute in our attributeInfo vector is the class attribute,\n+         * decide which case we are in\n+         */\n+        Attribute classAtt = (Attribute) attributeInfo.elementAt(0);\n+\n+        ScoreSet scores = new ScoreSet();\n+\n+        if (classAtt.isNominal() || classAtt.isString()) {\n+            Enumeration enumeratedValues = classAtt.enumerateValues();\n+\n+            int i = 0;\n+            while (enumeratedValues.hasMoreElements()) {\n+                if (i >= dist.length) {\n+                    System.err\n+                            .println(\"WekaWrapper: Error - scores found more possible values than \"\n+                                    + \"probabilities.\");\n+                    new Exception().printStackTrace();\n+                    System.exit(1);\n+                }\n+                double s = dist[i];\n+                String v = (String) enumeratedValues.nextElement();\n+                scores.put(v, s);\n+                ++i;\n+            }\n+        } else if (classAtt.isNumeric()) {\n+            System.err.println(\"WekaWrapper: Error - The 'scores' function should not be called \"\n+                    + \"when the class attribute is numeric.\");\n+            new Exception().printStackTrace();\n+            System.exit(1);\n+        } else {\n+            System.err.println(\"WekaWrapper: Error - ScoreSet: Class Types must be either \"\n+                    + \"Nominal, String, or Numeric.\");\n+            new Exception().printStackTrace();\n+            System.exit(1);\n+        }\n+\n+        return scores;\n+    }\n+\n+\n+    /**\n+     * Indicates that the classifier is finished learning. This method <I>must</I> be called if the\n+     * WEKA classifier is to learn anything. Since WEKA classifiers cannot learn online, all of the\n+     * training lbjavaInstances must be gathered and committed to first. This method invokes the WEKA\n+     * classifier's <code>buildClassifier(Instances)</code> method.\n+     **/\n+    public void doneLearning() {\n+        if (trained) {\n+            System.err.println(\"WekaWrapper: Error - Cannot call 'doneLearning()' again without \"\n+                    + \"first calling 'forget()'\");\n+            new Exception().printStackTrace();\n+            System.exit(1);\n+        }\n+\n+        /*\n+         * System.out.println(\"\\nWekaWrapper Data Summary:\");\n+         * System.out.println(wekaInstances.toSummaryString());\n+         */\n+\n+        try {\n+            initializeAttributes();\n+            for (Tuple4<int[], double[], int[], double[]> t : lbjavaInstances)\n+                wekaInstances.add(makeInstance(t.t1(), t.t2(), t.t3(), t.t4()));\n+\n+            baseClassifier.buildClassifier(wekaInstances);\n+        } catch (Exception e) {\n+            System.err.println(\"WekaWrapper: Error - There was a problem building the classifier\");\n+            if (baseClassifier == null)\n+                System.out.println(\"WekaWrapper: baseClassifier was null.\");\n+            e.printStackTrace();\n+            System.exit(1);\n+        }\n+\n+        trained = true;\n+        wekaInstances = new Instances(name, attributeInfo, 0);\n+        wekaInstances.setClassIndex(0);\n+    }\n+\n+\n+    /**\n+     * Writes the settings of the classifier in use, and a string describing the classifier, if\n+     * available.\n+     **/\n+    public void write(PrintStream out) {\n+        out.print(name + \": \");\n+        String[] options = baseClassifier.getOptions();\n+        for (int i = 0; i < options.length; ++i)\n+            out.println(options[i]);\n+        out.println(baseClassifier);\n+    }\n+\n+\n+    /**\n+     * Writes the learned function's internal representation in binary form.\n+     *\n+     * @param out The output stream.\n+     **/\n+    public void write(ExceptionlessOutputStream out) {\n+        super.write(out);\n+        out.writeBoolean(trained);\n+\n+        if (allowableValues == null)\n+            out.writeInt(0);\n+        else {\n+            out.writeInt(allowableValues.length);\n+            for (int i = 0; i < allowableValues.length; ++i)\n+                out.writeString(allowableValues[i]);\n+        }\n+\n+        ObjectOutputStream oos = null;\n+        try {\n+            oos = new ObjectOutputStream(out);\n+        } catch (Exception e) {\n+            System.err.println(\"Can't create object stream for '\" + name + \"': \" + e);\n+            System.exit(1);\n+        }\n+\n+        try {\n+            oos.writeObject(baseClassifier);\n+            oos.writeObject(freshClassifier);\n+            oos.writeObject(attributeInfo);\n+            oos.writeObject(wekaInstances);\n+        } catch (Exception e) {\n+            System.err.println(\"Can't write to object stream for '\" + name + \"': \" + e);\n+            System.exit(1);\n+        }\n+    }\n+\n+\n+    /**\n+     * Reads the binary representation of a learner with this object's run-time type, overwriting\n+     * any and all learned or manually specified parameters as well as the label lexicon but without\n+     * modifying the feature lexicon.\n+     *\n+     * @param in The input stream.\n+     **/\n+    public void read(ExceptionlessInputStream in) {\n+        super.read(in);\n+        trained = in.readBoolean();\n+        allowableValues = new String[in.readInt()];\n+        for (int i = 0; i < allowableValues.length; ++i)\n+            allowableValues[i] = in.readString();\n+\n+        ObjectInputStream ois = null;\n+        try {\n+            ois = new ObjectInputStream(in);\n+        } catch (Exception e) {\n+            System.err.println(\"Can't create object stream for '\" + name + \"': \" + e);\n+            System.exit(1);\n+        }\n+\n+        try {\n+            baseClassifier = (weka.classifiers.Classifier) ois.readObject();\n+            freshClassifier = (weka.classifiers.Classifier) ois.readObject();\n+            attributeInfo = (FastVector) ois.readObject();\n+            wekaInstances = (Instances) ois.readObject();","path":"saul-core/src/main/java/edu/illinois/cs/cogcomp/saul/learn/SaulWekaWrapper.java","position":580,"original_position":580,"commit_id":"d9045818b3584fd405436101e3ad14fb0046c3b6","original_commit_id":"d9045818b3584fd405436101e3ad14fb0046c3b6","user":{"login":"Rahgooy","id":5499744,"avatar_url":"https://avatars.githubusercontent.com/u/5499744?v=3","gravatar_id":"","url":"https://api.github.com/users/Rahgooy","html_url":"https://github.com/Rahgooy","followers_url":"https://api.github.com/users/Rahgooy/followers","following_url":"https://api.github.com/users/Rahgooy/following{/other_user}","gists_url":"https://api.github.com/users/Rahgooy/gists{/gist_id}","starred_url":"https://api.github.com/users/Rahgooy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Rahgooy/subscriptions","organizations_url":"https://api.github.com/users/Rahgooy/orgs","repos_url":"https://api.github.com/users/Rahgooy/repos","events_url":"https://api.github.com/users/Rahgooy/events{/privacy}","received_events_url":"https://api.github.com/users/Rahgooy/received_events","type":"User","site_admin":false},"body":"I have not change this part. It is from `WekaWrapper`. I think in some cases you need all the training data, for example for lazy classifiers.","created_at":"2016-10-03T08:01:33Z","updated_at":"2016-10-03T08:01:33Z","html_url":"https://github.com/IllinoisCogComp/saul/pull/407#discussion_r81505340","pull_request_url":"https://api.github.com/repos/IllinoisCogComp/saul/pulls/407","_links":{"self":{"href":"https://api.github.com/repos/IllinoisCogComp/saul/pulls/comments/81505340"},"html":{"href":"https://github.com/IllinoisCogComp/saul/pull/407#discussion_r81505340"},"pull_request":{"href":"https://api.github.com/repos/IllinoisCogComp/saul/pulls/407"}}},"pull_request":{"url":"https://api.github.com/repos/IllinoisCogComp/saul/pulls/407","id":87634695,"html_url":"https://github.com/IllinoisCogComp/saul/pull/407","diff_url":"https://github.com/IllinoisCogComp/saul/pull/407.diff","patch_url":"https://github.com/IllinoisCogComp/saul/pull/407.patch","issue_url":"https://api.github.com/repos/IllinoisCogComp/saul/issues/407","number":407,"state":"open","locked":false,"title":"saul-weka-wrapper","user":{"login":"Rahgooy","id":5499744,"avatar_url":"https://avatars.githubusercontent.com/u/5499744?v=3","gravatar_id":"","url":"https://api.github.com/users/Rahgooy","html_url":"https://github.com/Rahgooy","followers_url":"https://api.github.com/users/Rahgooy/followers","following_url":"https://api.github.com/users/Rahgooy/following{/other_user}","gists_url":"https://api.github.com/users/Rahgooy/gists{/gist_id}","starred_url":"https://api.github.com/users/Rahgooy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Rahgooy/subscriptions","organizations_url":"https://api.github.com/users/Rahgooy/orgs","repos_url":"https://api.github.com/users/Rahgooy/repos","events_url":"https://api.github.com/users/Rahgooy/events{/privacy}","received_events_url":"https://api.github.com/users/Rahgooy/received_events","type":"User","site_admin":false},"body":"A weka wrapper for saul","created_at":"2016-10-02T14:00:25Z","updated_at":"2016-10-03T08:01:33Z","closed_at":null,"merged_at":null,"merge_commit_sha":"7bfcdfca8d037d74c7fec7173c4a913c0c898547","assignee":{"login":"bhargav","id":331970,"avatar_url":"https://avatars.githubusercontent.com/u/331970?v=3","gravatar_id":"","url":"https://api.github.com/users/bhargav","html_url":"https://github.com/bhargav","followers_url":"https://api.github.com/users/bhargav/followers","following_url":"https://api.github.com/users/bhargav/following{/other_user}","gists_url":"https://api.github.com/users/bhargav/gists{/gist_id}","starred_url":"https://api.github.com/users/bhargav/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bhargav/subscriptions","organizations_url":"https://api.github.com/users/bhargav/orgs","repos_url":"https://api.github.com/users/bhargav/repos","events_url":"https://api.github.com/users/bhargav/events{/privacy}","received_events_url":"https://api.github.com/users/bhargav/received_events","type":"User","site_admin":false},"assignees":[{"login":"bhargav","id":331970,"avatar_url":"https://avatars.githubusercontent.com/u/331970?v=3","gravatar_id":"","url":"https://api.github.com/users/bhargav","html_url":"https://github.com/bhargav","followers_url":"https://api.github.com/users/bhargav/followers","following_url":"https://api.github.com/users/bhargav/following{/other_user}","gists_url":"https://api.github.com/users/bhargav/gists{/gist_id}","starred_url":"https://api.github.com/users/bhargav/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bhargav/subscriptions","organizations_url":"https://api.github.com/users/bhargav/orgs","repos_url":"https://api.github.com/users/bhargav/repos","events_url":"https://api.github.com/users/bhargav/events{/privacy}","received_events_url":"https://api.github.com/users/bhargav/received_events","type":"User","site_admin":false},{"login":"danyaljj","id":2441454,"avatar_url":"https://avatars.githubusercontent.com/u/2441454?v=3","gravatar_id":"","url":"https://api.github.com/users/danyaljj","html_url":"https://github.com/danyaljj","followers_url":"https://api.github.com/users/danyaljj/followers","following_url":"https://api.github.com/users/danyaljj/following{/other_user}","gists_url":"https://api.github.com/users/danyaljj/gists{/gist_id}","starred_url":"https://api.github.com/users/danyaljj/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/danyaljj/subscriptions","organizations_url":"https://api.github.com/users/danyaljj/orgs","repos_url":"https://api.github.com/users/danyaljj/repos","events_url":"https://api.github.com/users/danyaljj/events{/privacy}","received_events_url":"https://api.github.com/users/danyaljj/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/IllinoisCogComp/saul/pulls/407/commits","review_comments_url":"https://api.github.com/repos/IllinoisCogComp/saul/pulls/407/comments","review_comment_url":"https://api.github.com/repos/IllinoisCogComp/saul/pulls/comments{/number}","comments_url":"https://api.github.com/repos/IllinoisCogComp/saul/issues/407/comments","statuses_url":"https://api.github.com/repos/IllinoisCogComp/saul/statuses/d9045818b3584fd405436101e3ad14fb0046c3b6","head":{"label":"Rahgooy:saul-weka-wrapper","ref":"saul-weka-wrapper","sha":"d9045818b3584fd405436101e3ad14fb0046c3b6","user":{"login":"Rahgooy","id":5499744,"avatar_url":"https://avatars.githubusercontent.com/u/5499744?v=3","gravatar_id":"","url":"https://api.github.com/users/Rahgooy","html_url":"https://github.com/Rahgooy","followers_url":"https://api.github.com/users/Rahgooy/followers","following_url":"https://api.github.com/users/Rahgooy/following{/other_user}","gists_url":"https://api.github.com/users/Rahgooy/gists{/gist_id}","starred_url":"https://api.github.com/users/Rahgooy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Rahgooy/subscriptions","organizations_url":"https://api.github.com/users/Rahgooy/orgs","repos_url":"https://api.github.com/users/Rahgooy/repos","events_url":"https://api.github.com/users/Rahgooy/events{/privacy}","received_events_url":"https://api.github.com/users/Rahgooy/received_events","type":"User","site_admin":false},"repo":{"id":63954451,"name":"saul","full_name":"Rahgooy/saul","owner":{"login":"Rahgooy","id":5499744,"avatar_url":"https://avatars.githubusercontent.com/u/5499744?v=3","gravatar_id":"","url":"https://api.github.com/users/Rahgooy","html_url":"https://github.com/Rahgooy","followers_url":"https://api.github.com/users/Rahgooy/followers","following_url":"https://api.github.com/users/Rahgooy/following{/other_user}","gists_url":"https://api.github.com/users/Rahgooy/gists{/gist_id}","starred_url":"https://api.github.com/users/Rahgooy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Rahgooy/subscriptions","organizations_url":"https://api.github.com/users/Rahgooy/orgs","repos_url":"https://api.github.com/users/Rahgooy/repos","events_url":"https://api.github.com/users/Rahgooy/events{/privacy}","received_events_url":"https://api.github.com/users/Rahgooy/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/Rahgooy/saul","description":"Saul : Declarative Learning-Based Programming","fork":true,"url":"https://api.github.com/repos/Rahgooy/saul","forks_url":"https://api.github.com/repos/Rahgooy/saul/forks","keys_url":"https://api.github.com/repos/Rahgooy/saul/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Rahgooy/saul/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Rahgooy/saul/teams","hooks_url":"https://api.github.com/repos/Rahgooy/saul/hooks","issue_events_url":"https://api.github.com/repos/Rahgooy/saul/issues/events{/number}","events_url":"https://api.github.com/repos/Rahgooy/saul/events","assignees_url":"https://api.github.com/repos/Rahgooy/saul/assignees{/user}","branches_url":"https://api.github.com/repos/Rahgooy/saul/branches{/branch}","tags_url":"https://api.github.com/repos/Rahgooy/saul/tags","blobs_url":"https://api.github.com/repos/Rahgooy/saul/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Rahgooy/saul/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Rahgooy/saul/git/refs{/sha}","trees_url":"https://api.github.com/repos/Rahgooy/saul/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Rahgooy/saul/statuses/{sha}","languages_url":"https://api.github.com/repos/Rahgooy/saul/languages","stargazers_url":"https://api.github.com/repos/Rahgooy/saul/stargazers","contributors_url":"https://api.github.com/repos/Rahgooy/saul/contributors","subscribers_url":"https://api.github.com/repos/Rahgooy/saul/subscribers","subscription_url":"https://api.github.com/repos/Rahgooy/saul/subscription","commits_url":"https://api.github.com/repos/Rahgooy/saul/commits{/sha}","git_commits_url":"https://api.github.com/repos/Rahgooy/saul/git/commits{/sha}","comments_url":"https://api.github.com/repos/Rahgooy/saul/comments{/number}","issue_comment_url":"https://api.github.com/repos/Rahgooy/saul/issues/comments{/number}","contents_url":"https://api.github.com/repos/Rahgooy/saul/contents/{+path}","compare_url":"https://api.github.com/repos/Rahgooy/saul/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Rahgooy/saul/merges","archive_url":"https://api.github.com/repos/Rahgooy/saul/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Rahgooy/saul/downloads","issues_url":"https://api.github.com/repos/Rahgooy/saul/issues{/number}","pulls_url":"https://api.github.com/repos/Rahgooy/saul/pulls{/number}","milestones_url":"https://api.github.com/repos/Rahgooy/saul/milestones{/number}","notifications_url":"https://api.github.com/repos/Rahgooy/saul/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Rahgooy/saul/labels{/name}","releases_url":"https://api.github.com/repos/Rahgooy/saul/releases{/id}","deployments_url":"https://api.github.com/repos/Rahgooy/saul/deployments","created_at":"2016-07-22T13:13:12Z","updated_at":"2016-07-22T13:13:13Z","pushed_at":"2016-10-03T04:52:00Z","git_url":"git://github.com/Rahgooy/saul.git","ssh_url":"git@github.com:Rahgooy/saul.git","clone_url":"https://github.com/Rahgooy/saul.git","svn_url":"https://github.com/Rahgooy/saul","homepage":"","size":13481,"stargazers_count":0,"watchers_count":0,"language":"Scala","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"base":{"label":"IllinoisCogComp:master","ref":"master","sha":"ab6ce771d641d4bbb2a848f53a4d0cb55b07d44e","user":{"login":"IllinoisCogComp","id":14893101,"avatar_url":"https://avatars.githubusercontent.com/u/14893101?v=3","gravatar_id":"","url":"https://api.github.com/users/IllinoisCogComp","html_url":"https://github.com/IllinoisCogComp","followers_url":"https://api.github.com/users/IllinoisCogComp/followers","following_url":"https://api.github.com/users/IllinoisCogComp/following{/other_user}","gists_url":"https://api.github.com/users/IllinoisCogComp/gists{/gist_id}","starred_url":"https://api.github.com/users/IllinoisCogComp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/IllinoisCogComp/subscriptions","organizations_url":"https://api.github.com/users/IllinoisCogComp/orgs","repos_url":"https://api.github.com/users/IllinoisCogComp/repos","events_url":"https://api.github.com/users/IllinoisCogComp/events{/privacy}","received_events_url":"https://api.github.com/users/IllinoisCogComp/received_events","type":"Organization","site_admin":false},"repo":{"id":43462781,"name":"saul","full_name":"IllinoisCogComp/saul","owner":{"login":"IllinoisCogComp","id":14893101,"avatar_url":"https://avatars.githubusercontent.com/u/14893101?v=3","gravatar_id":"","url":"https://api.github.com/users/IllinoisCogComp","html_url":"https://github.com/IllinoisCogComp","followers_url":"https://api.github.com/users/IllinoisCogComp/followers","following_url":"https://api.github.com/users/IllinoisCogComp/following{/other_user}","gists_url":"https://api.github.com/users/IllinoisCogComp/gists{/gist_id}","starred_url":"https://api.github.com/users/IllinoisCogComp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/IllinoisCogComp/subscriptions","organizations_url":"https://api.github.com/users/IllinoisCogComp/orgs","repos_url":"https://api.github.com/users/IllinoisCogComp/repos","events_url":"https://api.github.com/users/IllinoisCogComp/events{/privacy}","received_events_url":"https://api.github.com/users/IllinoisCogComp/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/IllinoisCogComp/saul","description":"Saul : Declarative Learning-Based Programming","fork":false,"url":"https://api.github.com/repos/IllinoisCogComp/saul","forks_url":"https://api.github.com/repos/IllinoisCogComp/saul/forks","keys_url":"https://api.github.com/repos/IllinoisCogComp/saul/keys{/key_id}","collaborators_url":"https://api.github.com/repos/IllinoisCogComp/saul/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/IllinoisCogComp/saul/teams","hooks_url":"https://api.github.com/repos/IllinoisCogComp/saul/hooks","issue_events_url":"https://api.github.com/repos/IllinoisCogComp/saul/issues/events{/number}","events_url":"https://api.github.com/repos/IllinoisCogComp/saul/events","assignees_url":"https://api.github.com/repos/IllinoisCogComp/saul/assignees{/user}","branches_url":"https://api.github.com/repos/IllinoisCogComp/saul/branches{/branch}","tags_url":"https://api.github.com/repos/IllinoisCogComp/saul/tags","blobs_url":"https://api.github.com/repos/IllinoisCogComp/saul/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/IllinoisCogComp/saul/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/IllinoisCogComp/saul/git/refs{/sha}","trees_url":"https://api.github.com/repos/IllinoisCogComp/saul/git/trees{/sha}","statuses_url":"https://api.github.com/repos/IllinoisCogComp/saul/statuses/{sha}","languages_url":"https://api.github.com/repos/IllinoisCogComp/saul/languages","stargazers_url":"https://api.github.com/repos/IllinoisCogComp/saul/stargazers","contributors_url":"https://api.github.com/repos/IllinoisCogComp/saul/contributors","subscribers_url":"https://api.github.com/repos/IllinoisCogComp/saul/subscribers","subscription_url":"https://api.github.com/repos/IllinoisCogComp/saul/subscription","commits_url":"https://api.github.com/repos/IllinoisCogComp/saul/commits{/sha}","git_commits_url":"https://api.github.com/repos/IllinoisCogComp/saul/git/commits{/sha}","comments_url":"https://api.github.com/repos/IllinoisCogComp/saul/comments{/number}","issue_comment_url":"https://api.github.com/repos/IllinoisCogComp/saul/issues/comments{/number}","contents_url":"https://api.github.com/repos/IllinoisCogComp/saul/contents/{+path}","compare_url":"https://api.github.com/repos/IllinoisCogComp/saul/compare/{base}...{head}","merges_url":"https://api.github.com/repos/IllinoisCogComp/saul/merges","archive_url":"https://api.github.com/repos/IllinoisCogComp/saul/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/IllinoisCogComp/saul/downloads","issues_url":"https://api.github.com/repos/IllinoisCogComp/saul/issues{/number}","pulls_url":"https://api.github.com/repos/IllinoisCogComp/saul/pulls{/number}","milestones_url":"https://api.github.com/repos/IllinoisCogComp/saul/milestones{/number}","notifications_url":"https://api.github.com/repos/IllinoisCogComp/saul/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/IllinoisCogComp/saul/labels{/name}","releases_url":"https://api.github.com/repos/IllinoisCogComp/saul/releases{/id}","deployments_url":"https://api.github.com/repos/IllinoisCogComp/saul/deployments","created_at":"2015-09-30T22:21:38Z","updated_at":"2016-09-26T04:23:40Z","pushed_at":"2016-10-03T05:06:18Z","git_url":"git://github.com/IllinoisCogComp/saul.git","ssh_url":"git@github.com:IllinoisCogComp/saul.git","clone_url":"https://github.com/IllinoisCogComp/saul.git","svn_url":"https://github.com/IllinoisCogComp/saul","homepage":"","size":14584,"stargazers_count":7,"watchers_count":7,"language":"Scala","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":9,"mirror_url":null,"open_issues_count":111,"forks":9,"open_issues":111,"watchers":7,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/IllinoisCogComp/saul/pulls/407"},"html":{"href":"https://github.com/IllinoisCogComp/saul/pull/407"},"issue":{"href":"https://api.github.com/repos/IllinoisCogComp/saul/issues/407"},"comments":{"href":"https://api.github.com/repos/IllinoisCogComp/saul/issues/407/comments"},"review_comments":{"href":"https://api.github.com/repos/IllinoisCogComp/saul/pulls/407/comments"},"review_comment":{"href":"https://api.github.com/repos/IllinoisCogComp/saul/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/IllinoisCogComp/saul/pulls/407/commits"},"statuses":{"href":"https://api.github.com/repos/IllinoisCogComp/saul/statuses/d9045818b3584fd405436101e3ad14fb0046c3b6"}}}}
{"actor":{"display_login":"Rahgooy"}}