@Override
		public boolean afterEpoch(Inference inferenceImpl, Model model,
				int epoch, double loss, int iteration) {

			if (averaged) {
				try {
					// Clone the current model to average it, if necessary.
					LOG.info(String.format(
							"Cloning current model with %d parameters...",
							((DPGSModel) model).getParameters().size()));
					model = (Model) model.clone();
				} catch (CloneNotSupportedException e) {
					LOG.error(
							String.format(
									"Cloning current model with %d parameters on epoch %d and iteration %d",
									((DPGSModel) model).getParameters().size(),
									epoch, iteration), e);
					return true;
				}

				/*
				 * The averaged perceptron averages the final model only in the
				 * end of the training process, hence we need to average the
				 * temporary model here in order to have a better picture of its
				 * current (intermediary) performance.
				 */
				LOG.info("Averaging model...");
				model.average(iteration);
			}

			LOG.info("Predicting outputs...");

			// Use other inference if it has been given in constructor.
			if (inference != null)
				inferenceImpl = inference;
			// Fill the list of predicted outputs.
			DPGSInput[] inputs = testset.getInputs();
			// DPOutput[] outputs = testset.getOutputs();
			for (int idx = 0; idx < inputs.length; ++idx) {
				// Predict (tag the output sequence).
				inferenceImpl.inference(model, inputs[idx], predicteds[idx]);
				if ((idx + 1) % 100 == 0) {
					System.out.print(".");
					System.out.flush();
				}
			}

			// TODO test
			LOG.info(String.format("# subgradient steps / prediction: %d",
					((DPGSDualInference) inferenceImpl)
							.getMaxNumberOfSubgradientSteps()));

			try {
				// Delete previous epoch output file if it exists.
				File o = new File(conllPredicted);
				if (o.exists())
					o.delete();

				LOG.info(String
						.format("Saving input CoNLL file (%s) to output file (%s) with predicted columns",
								conllGolden, conllPredicted));
				testset.save(conllGolden, conllPredicted, predicteds);

				try {
					LOG.info("Evaluation after epoch " + epoch + ":");
					// Execute CoNLL evaluation scripts.
					evaluateWithConllScripts(script, conllGolden,
							conllPredicted, quiet);
				} catch (Exception e) {
					LOG.error("Running evaluation scripts", e);
				}

			} catch (IOException e) {
				LOG.error("Saving test file with predicted column", e);
			} catch (DatasetException e) {
				LOG.error("Saving test file with predicted column", e);
			}

			return true;
		}