public void train() {

        // Build vocab
        Vocabulary vocab = new Vocabulary();
        try {
            vocab.loadRawText(conf.trainFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return;
        }
        conf.vocab = vocab;

        // Train
        LMSaver saver = null;
        double entropy = 1000000;
        while (true) {
            Pair<Double, LMSaver> scoreSaverPair = trainAndMerge(saver);
            double averageEntropy = scoreSaverPair.getKey();
            if (averageEntropy > entropy) break;
            entropy = averageEntropy;
            Logger.info(String.format("[Overall] average entropy: %.4f", averageEntropy));
            saver = scoreSaverPair.getValue();
        }

        // Final Valid
        double finalEntropy = 0;
        try {
            RNNLM lm = new RNNLM(conf);
            if (lm != null && saver != null) {
                saver.restore(lm);
                Pair<Double, Integer> logpPair = lm.estimate(new FileScanner(vocab, conf.validFile));
                finalEntropy = -logpPair.getKey()/Math.log10(2)/logpPair.getValue();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (finalEntropy != 0) {
            Logger.info(String.format("Final Valid Entropy: %.4f", finalEntropy));
        }
        else {
            Logger.info(String.format("Final Valid failed"));
        }

    }