template<class LearnerInput> struct OneVsAllConfiguration { OneVsAllConfiguration() { Factory = NULL; } OneVsAllConfiguration(BinaryClassifierFactory<LearnerInput> *_Factory) { Factory = _Factory; } BinaryClassifierFactory<LearnerInput> *Factory; }; template<class LearnerInput> class MulticlassClassifierOneVsAll : public MulticlassClassifier<LearnerInput> { public: MulticlassClassifierOneVsAll() { _Configured = false; } MulticlassClassifierOneVsAll(const OneVsAllConfiguration<LearnerInput> &Config) { _Configured = true; _Config = Config; } MulticlassClassifierType Type() const { return MulticlassClassifierTypeOneVsAll; } void Configure(const OneVsAllConfiguration<LearnerInput> &Config) { _Configured = true; _Config = Config; } void Train(const Dataset &Examples) { Console::WriteLine(String("Training multiclass one-vs-all classifier, ") + String(Examples.Entries().Length()) + String(" examples")); PersistentAssert(_Configured, "Classifier not configured"); const UINT ExampleCount = Examples.Entries().Length(); const UINT ClassCount = Examples.ClassCount(); _Classifiers.Allocate(Examples.ClassCount()); for(UINT ClassIndex = 0; ClassIndex < ClassCount; ClassIndex++) { _Classifiers[ClassIndex] = _Config.Factory->MakeClassifier(); BinaryClassifier<LearnerInput> &CurClassifier = *(_Classifiers[ClassIndex]); ClassifierDataset<LearnerInput> LocalDataset = Examples; LocalDataset.ClassCount() = ClassCount + 1; for(UINT ExampleIndex = 0; ExampleIndex < ExampleCount; ExampleIndex++) { Example &CurExample = LocalDataset.Entries()[ExampleIndex]; if(CurExample.Class != ClassIndex) { CurExample.Class = ClassCount; } } Console::WriteLine(String("Training classfier ") + String(ClassIndex) + String("(") + String(LocalDataset.CountExamplesOfClass(ClassIndex)) + String(" positive samples)")); CurClassifier.Train(LocalDataset, ClassIndex, ClassCount); } } void Evaluate(const LearnerInput &Input, UINT &Class, Vector<double> &ClassProbabilities) const { const UINT ClassCount = _Classifiers.Length(); if(ClassProbabilities.Length() != ClassCount) { ClassProbabilities.Allocate(ClassCount); } Class = 0; double MaxProbability = 0.0; for(UINT ClassIndex = 0; ClassIndex < ClassCount; ClassIndex++) { BinaryClassifier<LearnerInput> &CurClassifier = *(_Classifiers[ClassIndex]); UINT LocalClass; CurClassifier.Evaluate(Input, LocalClass, ClassProbabilities[ClassIndex]); if(ClassProbabilities[ClassIndex] > MaxProbability) { MaxProbability = ClassProbabilities[ClassIndex]; Class = ClassIndex; } } } void SaveToBinaryStream(OutputDataStream &Stream) const { SignalError("Not implemented"); } void LoadFromBinaryStream(InputDataStream &Stream) { SignalError("Not implemented"); } private: bool _Configured; OneVsAllConfiguration<LearnerInput> _Config; Vector<BinaryClassifier<LearnerInput>*> _Classifiers; };