Как использовать шаблон стратегии с контейнерами STL?

Предположим, что у меня есть интерфейс стратегии с именем BinaryClassifier это может занять Sample и вернуть double представляющих вероятность Sample Объект принадлежности к положительному классу:

struct BinaryClassifier {
virtual ~BinaryClassifier(){}
virtual double classify(std::shared_ptr<Sample> sample) const = 0;
};

У нас может быть несколько реализаций BinaryClassifierнапример, LogisticRegressionBinaryClassifier,

Sample в свою очередь это интерфейс, предоставляющий только два метода:

struct Sample {
virtual ~Sample() {}
InputFeatures const& get_input_features() const = 0;
double get_label() const = 0;
};

Помимо этих двух методов, конкретные реализации Sample раскрыть совершенно разные интерфейсы (то есть они не связаны), единственное, что у них общего, — это то, что они могут быть классифицированы двоичным классификатором.

Все идет нормально.

Проблемы возникают, когда мы решаем ввести BinaryClassifier::train метод:

struct BinaryClassifier {
virtual ~BinaryClassifier(){}
virtual double classify(std::shared_ptr<Sample> sample) const = 0;
virtual void train(std::vector<std::shared_ptr<Sample>> samples) = 0;
};

На данный момент следующее не будет работать:

std::vector<std::shared_ptr<ConcreteSample>> concreteSamples = ...;
concreteBinaryClassifier.train(concreteSamples);

это потому что std::vector<std::shared_ptr<ConcreteSample>> а также std::vector<std::shared_ptr<Sample>> два несвязанных типа.

Решением для C ++ будет использование шаблонов:

      template<class SampleType>
virtual void train(std::vector<std::shared_ptr<SampleType>> samples) = 0; // non-working code, template method cannot be virtual

Но шаблонные методы не могут быть virtual, Тем не менее, я хотел бы BinaryClassifier быть интерфейсом Стратегии как можно больше BinaryClassifier реализации могут существовать. На данный момент, хотя дизайн кажется вполне резонным, я застрял в тупике.

РЕДАКТИРОВАТЬ: Более того, это может произойти для данного BinaryClassifier объект для обучения с вектором ConcreteSampleAпри классификации объекта типа ConcreteSampleB

Как правильно моделировать эту ситуацию наиболее подходящим для C ++ способом?

0

Решение

Вы можете сделать свой BinaryClassifier классом шаблона

template<SampleType> class BinaryClassifier
{
virtual void train(std::vector<std::shared_ptr<SampleType>> samples) = 0;
}
0

Другие решения

Вы не можете тренировать BinaryClassifier на ConcreteSampleA а затем использовать его для классификации любого случайного ConcreteSampleB, Поэтому тип выборки является неотъемлемой частью BinaryClassifier, Ответ Нуллрефа вполне обоснован: сделайте тип образца параметром шаблона.

Как вы обнаружили, это означает, что больше нет необходимости Sample интерфейс. Хорошо. std::vector<int> не требует этого int происходит от некоторых Element Интерфейс тоже.

Пока ты избавляешься от вещей, InputFeatures выглядит подозрительным тоже. Я бы просто сказал, что get_input_features должен вернуть немного std::tuple чьи типы членов все имеют std::less определены. Поскольку он больше не является виртуальным, вам все равно, что разные типы семплов возвращают разные кортежи. И я определенно не стал бы это жестко кодировать get_label должен вернуть double, В любом случае, это странный тип ярлыка.

Теперь вы сказали, что, возможно, имеет смысл потренироваться с типом выборки A, а затем классифицировать тип выборки B. Вот где вы получите уточнение: кажется, что реальное требование совместимости состоит в том, что они возвращают один и тот же кортеж. Следовательно, лучшее решение, которое Nullref’s, — это шаблонизировать BinaryClassifier на тип кортежа, возвращаемый get_input_sample,

[редактировать] Более того, classify не нужно принимать совладение. Пройти Sample const&, train() на самом деле следует взять только пару итераторов. Соглашение C ++ — передавать группу объектов как диапазон.

0

По вопросам рекламы [email protected]