Commit 8c4f1db7 authored by Jussi Lindgren's avatar Jussi Lindgren
Browse files

Plugins: Further work for 0,k-1 indexing in classifiers

- Refactored OneVsOne to use map storage
- Pairwise strategies no longer use their own class
count as that can be inherited from base class
parent 5f1a3f5c
......@@ -89,9 +89,9 @@ boolean CAlgorithmClassifierOneVsAll::train(const IFeatureVectorSet& rFeatureVec
}
//And then we just change adapt the label for each feature vector but we don't copy them anymore
for(size_t l_iClassifierCounter = 1 ; l_iClassifierCounter <= m_oSubClassifierList.size() ; ++l_iClassifierCounter )
for(size_t l_iClassifierCounter = 0 ; l_iClassifierCounter < m_oSubClassifierList.size() ; ++l_iClassifierCounter )
{
TParameterHandler < IMatrix* > ip_pFeatureVectorSet(m_oSubClassifierList[l_iClassifierCounter-1]->getInputParameter(OVTK_Algorithm_Classifier_InputParameterId_FeatureVectorSet));
TParameterHandler < IMatrix* > ip_pFeatureVectorSet(m_oSubClassifierList[l_iClassifierCounter]->getInputParameter(OVTK_Algorithm_Classifier_InputParameterId_FeatureVectorSet));
ip_pFeatureVectorSet = (IMatrix*)ip_pFeatureVectorSetReference;
float64* l_pFeatureVectorSetBuffer=ip_pFeatureVectorSet->getBuffer();
......@@ -101,16 +101,16 @@ boolean CAlgorithmClassifierOneVsAll::train(const IFeatureVectorSet& rFeatureVec
const float64 l_f64Class = rFeatureVectorSet[j].getLabel();
if(static_cast<uint32>(l_f64Class) == l_iClassifierCounter)
{
l_pFeatureVectorSetBuffer[l_ui32FeatureVectorSize]=1;
l_pFeatureVectorSetBuffer[l_ui32FeatureVectorSize]=0;
}
else
{
l_pFeatureVectorSetBuffer[l_ui32FeatureVectorSize]=2;
l_pFeatureVectorSetBuffer[l_ui32FeatureVectorSize]=1;
}
l_pFeatureVectorSetBuffer+=(l_ui32FeatureVectorSize+1);
}
m_oSubClassifierList[l_iClassifierCounter-1]->process(OVTK_Algorithm_Classifier_InputTriggerId_Train);
m_oSubClassifierList[l_iClassifierCounter]->process(OVTK_Algorithm_Classifier_InputTriggerId_Train);
}
return true;
}
......@@ -158,19 +158,19 @@ boolean CAlgorithmClassifierOneVsAll::classify(const IFeatureVector& rFeatureVec
for(size_t l_iClassificationCount = 0; l_iClassificationCount < l_oClassificationVector.size() ; ++l_iClassificationCount)
{
CClassifierOutput& l_pTemp = l_oClassificationVector[l_iClassificationCount];
if(l_pTemp.first==1)
if(l_pTemp.first==0) // Predicts its "own" class, class=0
{
if(l_oBest.second == NULL)
{
l_oBest = l_pTemp;
rf64Class = l_iClassificationCount+1;
rf64Class = l_iClassificationCount;
}
else
{
if((*m_fAlgorithmComparison)((*l_oBest.second), *(l_pTemp.second)) > 0)
{
l_oBest = l_pTemp;
rf64Class = l_iClassificationCount+1;
rf64Class = l_iClassificationCount;
}
}
}
......@@ -186,7 +186,7 @@ boolean CAlgorithmClassifierOneVsAll::classify(const IFeatureVector& rFeatureVec
if(l_oBest.second == NULL)
{
l_oBest = l_pTemp;
rf64Class = (static_cast<float64>(l_iClassificationCount))+1;
rf64Class = (static_cast<float64>(l_iClassificationCount));
}
else
{
......@@ -194,7 +194,7 @@ boolean CAlgorithmClassifierOneVsAll::classify(const IFeatureVector& rFeatureVec
if((*m_fAlgorithmComparison)((*l_oBest.second), *(l_pTemp.second)) < 0)
{
l_oBest = l_pTemp;
rf64Class = l_iClassificationCount+1;
rf64Class = l_iClassificationCount;
}
}
}
......@@ -207,7 +207,7 @@ boolean CAlgorithmClassifierOneVsAll::classify(const IFeatureVector& rFeatureVec
}
//Now that we made the calculation, we send the corresponding data
IAlgorithmProxy* l_pWinner = this->m_oSubClassifierList[static_cast<uint32>(rf64Class)-1];
IAlgorithmProxy* l_pWinner = this->m_oSubClassifierList[static_cast<uint32>(rf64Class)];
TParameterHandler < IMatrix* > op_pClassificationWinnerValues(l_pWinner->getOutputParameter(OVTK_Algorithm_Classifier_OutputParameterId_ClassificationValues));
TParameterHandler < IMatrix* > op_pProbabilityWinnerValues(l_pWinner->getOutputParameter(OVTK_Algorithm_Classifier_OutputParameterId_ProbabilityValues));
......@@ -233,6 +233,9 @@ boolean CAlgorithmClassifierOneVsAll::addNewClassifierAtBack(void)
IAlgorithmProxy* l_pSubClassifier = &this->getAlgorithmManager().getAlgorithm(l_oSubClassifierAlgorithm);
l_pSubClassifier->initialize();
TParameterHandler < uint64 > ip_pNumberOfClasses(l_pSubClassifier->getInputParameter(OVTK_Algorithm_Classifier_InputParameterId_NumberOfClasses));
ip_pNumberOfClasses = 2;
//Set a references to the extra parameters input of the pairing strategy
TParameterHandler< std::map<CString, CString>* > ip_pExtraParameters(l_pSubClassifier->getInputParameter(OVTK_Algorithm_Classifier_InputParameterId_ExtraParameter));
ip_pExtraParameters.setReferenceTarget(this->getInputParameter(OVTK_Algorithm_Classifier_InputParameterId_ExtraParameter));
......
......@@ -8,6 +8,7 @@
#include <xml/IXMLNode.h>
#include <vector>
#include <map>
#define OVP_ClassId_Algorithm_ClassifierOneVsOne OpenViBE::CIdentifier(0x638C2F90, 0xEAE10226)
#define OVP_ClassId_Algorithm_ClassifierOneVsOneDesc OpenViBE::CIdentifier(0xE78E7CDB, 0x369AA9EF)
......@@ -21,13 +22,6 @@ namespace OpenViBEPlugins
extern OV_API void registerAvailableDecisionEnumeration(const OpenViBE::CIdentifier& rAlgorithmIdentifier, OpenViBE::CIdentifier pDecision);
extern OV_API OpenViBE::CIdentifier getAvailableDecisionEnumeration(const OpenViBE::CIdentifier& rAlgorithmIdentifier);
typedef struct{
OpenViBE::float64 m_f64FirstClass;
OpenViBE::float64 m_f64SecondClass;
OpenViBE::Kernel::IAlgorithmProxy* m_pSubClassifierProxy;
} SSubClassifierDescriptor;
//The aim of this structure is to record informations returned by the sub-classifier. They will be used by
// pairwise decision algorithms to compute probability vector.
// Should be use only by OneVsOne and pairwise decision algorithm
......@@ -63,21 +57,26 @@ namespace OpenViBEPlugins
protected:
virtual OpenViBE::boolean createSubClassifiers(void);
private:
std::vector<SSubClassifierDescriptor> m_oSubClassifierDescriptorList;
OpenViBE::uint32 m_ui32NumberOfClasses;
OpenViBE::uint32 m_ui32NumberOfSubClassifiers;
std::map< std::pair<OpenViBE::uint32,OpenViBE::uint32>, OpenViBE::Kernel::IAlgorithmProxy* > m_oSubClassifiers;
fClassifierComparison m_fAlgorithmComparison;
OpenViBE::Kernel::IAlgorithmProxy* m_pDecisionStrategyAlgorithm;
OpenViBE::CIdentifier m_oPairwiseDecisionIdentifier;
XML::IXMLNode* getClassifierConfiguration(SSubClassifierDescriptor &rDescriptor);
XML::IXMLNode* getClassifierConfiguration(OpenViBE::float64 f64FirstClass, OpenViBE::float64 f64SecondClass, OpenViBE::Kernel::IAlgorithmProxy* pSubClassifier);
XML::IXMLNode* getPairwiseDecisionConfiguration(void);
OpenViBE::uint32 getClassCount(void) const;
// OpenViBE::uint32 getClassCount(void) const;
OpenViBE::boolean loadSubClassifierConfiguration(XML::IXMLNode *pSubClassifiersNode);
SSubClassifierDescriptor& getSubClassifierDescriptor(const OpenViBE::uint32 f64FirstClass, const OpenViBE::uint32 f64SecondClass);
// SSubClassifierDescriptor& getSubClassifierDescriptor(const OpenViBE::uint32 f64FirstClass, const OpenViBE::uint32 f64SecondClass);
OpenViBE::boolean setSubClassifierIdentifier(const OpenViBE::CIdentifier &rId);
};
......@@ -93,7 +92,7 @@ namespace OpenViBEPlugins
virtual OpenViBE::CString getShortDescription(void) const { return OpenViBE::CString(""); }
virtual OpenViBE::CString getDetailedDescription(void) const { return OpenViBE::CString(""); }
virtual OpenViBE::CString getCategory(void) const { return OpenViBE::CString(""); }
virtual OpenViBE::CString getVersion(void) const { return OpenViBE::CString("0.1"); }
virtual OpenViBE::CString getVersion(void) const { return OpenViBE::CString("0.2"); }
virtual OpenViBE::CIdentifier getCreatedClass(void) const { return OVP_ClassId_Algorithm_ClassifierOneVsOne; }
virtual OpenViBE::Plugins::IPluginObject* create(void) { return new OpenViBEPlugins::Classification::CAlgorithmClassifierOneVsOne; }
......
......@@ -80,8 +80,8 @@ boolean CAlgorithmPairwiseDecisionHT::compute(std::vector< SClassificationInfo >
for(size_t i = 0 ; i < pClassificationValueList.size() ; ++i)
{
SClassificationInfo& l_rTemp = pClassificationValueList[i];
const uint32 l_f64FirstIndex = static_cast<uint32>(l_rTemp.m_f64FirstClass) -1;
const uint32 l_f64SecondIndex = static_cast<uint32>(l_rTemp.m_f64SecondClass) -1;
const uint32 l_f64FirstIndex = static_cast<uint32>(l_rTemp.m_f64FirstClass);
const uint32 l_f64SecondIndex = static_cast<uint32>(l_rTemp.m_f64SecondClass);
const float64* l_pValues = l_rTemp.m_pClassificationValue->getBuffer();
l_pProbabilityMatrix[l_f64FirstIndex * m_ui32ClassCount + l_f64SecondIndex] = l_pValues[0];
l_pProbabilityMatrix[l_f64SecondIndex * m_ui32ClassCount + l_f64FirstIndex] = 1 - l_pValues[0];
......
......@@ -74,11 +74,11 @@ boolean CAlgorithmPairwiseDecisionVoting::compute(std::vector< SClassificationIn
SClassificationInfo & l_rTemp = pClassificationValueList[i];
if(l_rTemp.m_f64ClassLabel == 1)
{
++(l_pWinCount[(uint32)(l_rTemp.m_f64FirstClass-1)]);
++(l_pWinCount[(uint32)(l_rTemp.m_f64FirstClass)]);
}
else
{
++(l_pWinCount[(uint32)(l_rTemp.m_f64SecondClass-1)]);
++(l_pWinCount[(uint32)(l_rTemp.m_f64SecondClass)]);
}
}
......
......@@ -65,8 +65,8 @@ boolean CAlgorithmPairwiseStrategyPKPD::compute(std::vector< SClassificationInfo
for(size_t i = 0 ; i < pClassificationValueList.size() ; ++i)
{
SClassificationInfo& l_rTemp = pClassificationValueList[i];
const uint32 l_f64FirstIndex = static_cast<uint32>(l_rTemp.m_f64FirstClass) -1;
const uint32 l_f64SecondIndex = static_cast<uint32>(l_rTemp.m_f64SecondClass) -1;
const uint32 l_f64FirstIndex = static_cast<uint32>(l_rTemp.m_f64FirstClass);
const uint32 l_f64SecondIndex = static_cast<uint32>(l_rTemp.m_f64SecondClass);
const float64* l_pValues = l_rTemp.m_pClassificationValue->getBuffer();
l_pProbabilityMatrix[l_f64FirstIndex * m_ui32ClassCount + l_f64SecondIndex] = l_pValues[0];
l_pProbabilityMatrix[l_f64SecondIndex * m_ui32ClassCount + l_f64FirstIndex] = 1 - l_pValues[0];
......
......@@ -115,17 +115,21 @@ boolean CBoxAlgorithmClassifierTrainer::initialize(void)
m_vFeatureCount.clear();
if(l_rStaticBoxContext.getInputCount()<2)
{
// This shouldn't happen.
this->getLogManager() << LogLevel_Error << "Must have at least one feature input\n";
return false;
}
// Provide the number of classes to the classifier
const uint32 l_ui32ClassCount = l_rStaticBoxContext.getInputCount() - 1;
TParameterHandler< uint64 > ip_NumClasses = m_pClassifier->getInputParameter(OVTK_Algorithm_Classifier_InputParameterId_NumberOfClasses);
ip_NumClasses = l_ui32ClassCount;
//If we have to deal with a pairing strategy we have to pass argument
if(l_bIsPairing)
{
TParameterHandler < uint64 > ip_pClassCount(m_pClassifier->getInputParameter(OVTK_Algorithm_PairingStrategy_InputParameterId_ClassCount));
if(l_rStaticBoxContext.getInputCount()==0)
{
// This shouldn't happen.
this->getLogManager() << LogLevel_Error << "Must have more than 0 inputs\n";
return false;
}
ip_pClassCount = l_rStaticBoxContext.getInputCount() -1; // >=0 by above test. -1 because one input connector is for stimulations.
TParameterHandler < CIdentifier* > ip_oClassId(m_pClassifier->getInputParameter(OVTK_Algorithm_PairingStrategy_InputParameterId_SubClassifierAlgorithm));
ip_oClassId = &l_oClassifierAlgorithmClassIdentifier;
if(!m_pClassifier->process(OVTK_Algorithm_PairingStrategy_InputTriggerId_DesignArchitecture))
......@@ -383,10 +387,6 @@ boolean CBoxAlgorithmClassifierTrainer::process(void)
l_oConfusion.setDimensionSize(0, l_ui32ClassCount);
l_oConfusion.setDimensionSize(1, l_ui32ClassCount);
// Provide the number of classes to the classifier
TParameterHandler< uint64 > ip_NumClasses = m_pClassifier->getInputParameter(OVTK_Algorithm_Classifier_InputParameterId_NumberOfClasses);
ip_NumClasses = l_ui32ClassCount;
if(m_ui64PartitionCount>=2)
{
float64 l_f64PartitionAccuracy=0;
......
......@@ -14,7 +14,6 @@
#define OVTK_ClassId_Algorithm_PairingStrategyDesc OpenViBE::CIdentifier(0x4341B8D6, 0xC65B7BBB)
#define OVTK_Algorithm_PairingStrategy_InputParameterId_SubClassifierAlgorithm OpenViBE::CIdentifier(0xD9E60DF9, 0x20EC8FC9)
#define OVTK_Algorithm_PairingStrategy_InputParameterId_ClassCount OpenViBE::CIdentifier(0x2452FF63, 0x028133C8)
#define OVTK_Algorithm_PairingStrategy_InputTriggerId_DesignArchitecture OpenViBE::CIdentifier(0x784A9CDF, 0xA41C27F8)
......@@ -66,7 +65,6 @@ namespace OpenViBEToolkit
CAlgorithmClassifierDesc::getAlgorithmPrototype(rAlgorithmPrototype);
rAlgorithmPrototype.addInputParameter (OVTK_Algorithm_PairingStrategy_InputParameterId_SubClassifierAlgorithm, "Algorithm Identifier", OpenViBE::Kernel::ParameterType_Identifier);
rAlgorithmPrototype.addInputParameter (OVTK_Algorithm_PairingStrategy_InputParameterId_ClassCount, "Number of classes", OpenViBE::Kernel::ParameterType_UInteger);
rAlgorithmPrototype.addInputTrigger (OVTK_Algorithm_PairingStrategy_InputTriggerId_DesignArchitecture, "Design Architecture");
return true;
......
......@@ -29,7 +29,7 @@ boolean CAlgorithmPairingStrategy::process(void)
if(this->isInputTriggerActive(OVTK_Algorithm_PairingStrategy_InputTriggerId_DesignArchitecture))
{
TParameterHandler < CIdentifier* > ip_pClassifierIdentifier(this->getInputParameter(OVTK_Algorithm_PairingStrategy_InputParameterId_SubClassifierAlgorithm));
TParameterHandler < uint64 > ip_pClassCount(this->getInputParameter(OVTK_Algorithm_PairingStrategy_InputParameterId_ClassCount));
TParameterHandler < uint64 > ip_pClassCount(this->getInputParameter(OVTK_Algorithm_Classifier_InputParameterId_NumberOfClasses));
const uint64 l_ui64ClassCount = (uint64) ip_pClassCount;
const CIdentifier l_oClassifierIdentifier = *((CIdentifier*)ip_pClassifierIdentifier);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment