predictor_type operator()(const DataIterator& begin, const DataIterator& end,
			    const InputOf& input_of, const OutputOf& label_of) const {

    // Let us apply a variable selection process.
    GenericLearner generic_learner;

    // We need a real risk estimator for evaluating the algorithms when variables are selected.
    auto real_risk_estimator = gaml::risk::cross_validation(gaml::loss::Quadratic<double>(),
							    gaml::partition::kfold(10), false);
    // Wrapping evaluator
    auto evaluator = gaml::varsel::make_wrapper_evaluator(generic_learner, real_risk_estimator,
							  begin, end, input_of, label_of);
    // Make the evaluator verbose.
    if(verbosity) evaluator.verbose();
    
    // The result of a search is a subset of variables with its risk.
    std::vector<int> variable_subset;
    double           best_risk = gaml::varsel::SFFS(evaluator, variable_subset, verbosity);

    if(verbosity) {
      std::cout << std::endl
		<< "Risk is : " << best_risk << ", with the following variable selection:" << std::endl
		<< "  {";
      for(auto attr : variable_subset) std::cout << ' ' << toString(attr);
      std::cout << " }" << std::endl << std::endl;
    }

    // Let us set up the predictor from the projection of the data.
    auto projection = gaml::project(begin, end, 
				    variable_subset.begin(), variable_subset.end(), 
				    input_of, label_of);
    return projection.teach(generic_learner); // The predictor is computed here.
  }
			decltype(auto) async_make_next_batch() {
				return std::async(std::launch::async, [this](){
					cpu_vector cpu_train_data;
					cpu_vector cpu_teach_data;
					for(auto i = 0; i < label_num_; ++i) {
						std::shuffle(data_[i].begin(), data_[i].end(), g_);
						for(auto j = 0; j < data_num_per_label_; ++j) {
							cpu_train_data.insert(cpu_train_data.end(),
								data_[i][j].begin(), data_[i][j].end());
						}

						cpu_vector teach(label_num_, 0.f); teach[i] = 1.f;
						for(auto j = 0; j < data_num_per_label_; ++j) {
							cpu_teach_data.insert(cpu_teach_data.end(),
								teach.begin(), teach.end());
						}
					}
					boost::compute::copy(
						cpu_train_data.begin(), cpu_train_data.end(),
						batch_.train_data.begin());
					boost::compute::copy(
						cpu_teach_data.begin(), cpu_teach_data.end(),
						batch_.teach_data.begin());
				});
			}