9 #include "Helpers/XmlHelper.h" 18 SupportVectorMachine::SupportVectorMachine() :
19 m_isInitialized(false),
20 m_enableProbability(false),
23 m_standardizeFeatures(true),
27 m_kernelType(QUADRATIC),
28 m_kernelFunction(QuadraticKernel),
39 std::cout <<
"SupportVectorMachine: svm was already initialized" << std::endl;
40 return STATUS_CODE_ALREADY_INITIALIZED;
50 if (featureInfo.m_sigmaValue < std::numeric_limits<double>::epsilon())
52 std::cout <<
"SupportVectorMachine: could not standardize parameters because sigma value was too small" << std::endl;
53 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
65 std::cout <<
"SupportVectorMachine: the number of features in the xml file was inconsistent" << std::endl;
66 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
73 std::cout <<
"SupportVectorMachine: could not evaluate kernel because scale factor was too small" << std::endl;
74 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
78 return STATUS_CODE_SUCCESS;
85 TiXmlDocument xmlDocument(svmFileName);
87 if (!xmlDocument.LoadFile())
89 std::cout <<
"SupportVectorMachine::Initialize - Invalid xml file." << std::endl;
90 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
93 const TiXmlHandle xmlDocumentHandle(&xmlDocument);
94 TiXmlNode *pContainerXmlNode(TiXmlHandle(xmlDocumentHandle).FirstChildElement().Element());
97 while (pContainerXmlNode)
99 if (pContainerXmlNode->ValueStr() !=
"SupportVectorMachine")
100 throw StatusCodeException(STATUS_CODE_FAILURE);
102 const TiXmlHandle currentHandle(pContainerXmlNode);
104 std::string currentName;
105 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(currentHandle,
"Name", currentName));
107 if (currentName.empty() || (currentName.size() > 1000))
109 std::cout <<
"SupportVectorMachine::Initialize - Implausible svm name extracted from xml." << std::endl;
110 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
113 if (currentName == svmName)
116 pContainerXmlNode = pContainerXmlNode->NextSibling();
119 if (!pContainerXmlNode)
121 std::cout <<
"SupportVectorMachine: Could not find an svm by the name " << svmName << std::endl;
122 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
126 TiXmlHandle localHandle(pContainerXmlNode);
127 TiXmlElement *pCurrentXmlElement = localHandle.FirstChild().Element();
129 while (pCurrentXmlElement)
131 if (STATUS_CODE_SUCCESS != this->
ReadComponent(pCurrentXmlElement))
133 std::cout <<
"SupportVectorMachine: Unknown component in xml file" << std::endl;
134 throw StatusCodeException(STATUS_CODE_FAILURE);
137 pCurrentXmlElement = pCurrentXmlElement->NextSiblingElement();
145 const std::string componentName(pCurrentXmlElement->ValueStr());
146 const TiXmlHandle currentHandle(pCurrentXmlElement);
148 if ((std::string(
"Name") == componentName) || (std::string(
"Timestamp") == componentName))
149 return STATUS_CODE_SUCCESS;
151 if (std::string(
"Machine") == componentName)
154 if (std::string(
"Features") == componentName)
157 if (std::string(
"SupportVector") == componentName)
160 return STATUS_CODE_INVALID_PARAMETER;
168 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(currentHandle,
"KernelType", kernelType));
171 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(currentHandle,
"Bias", bias));
173 double scaleFactor(0.);
174 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(currentHandle,
"ScaleFactor", scaleFactor));
176 bool standardize(
true);
177 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(currentHandle,
"Standardize", standardize));
179 bool enableProbability(
false);
180 PANDORA_RETURN_RESULT_IF_AND_IF(
181 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(currentHandle,
"EnableProbability", enableProbability));
183 double probAParameter(0.);
184 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(currentHandle,
"ProbAParameter", probAParameter));
186 double probBParameter(0.);
187 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(currentHandle,
"ProbBParameter", probBParameter));
199 return STATUS_CODE_SUCCESS;
206 std::vector<double> muValues;
207 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadVectorOfValues(currentHandle,
"MuValues", muValues));
209 std::vector<double> sigmaValues;
210 PANDORA_RETURN_RESULT_IF_AND_IF(
211 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadVectorOfValues(currentHandle,
"SigmaValues", sigmaValues));
213 if (muValues.size() != sigmaValues.size())
215 std::cout <<
"SupportVectorMachine: could not add feature info because the size of mu (" << muValues.size()
216 <<
") did not match " 217 "the size of sigma (" 218 << sigmaValues.size() <<
")" << std::endl;
219 return STATUS_CODE_INVALID_PARAMETER;
224 for (std::size_t i = 0; i < muValues.size(); ++i)
227 return STATUS_CODE_SUCCESS;
235 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(currentHandle,
"AlphaY", yAlpha));
237 std::vector<double>
values;
238 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadVectorOfValues(currentHandle,
"Values", values));
241 for (
const double &
value : values)
242 valuesFeatureVector.emplace_back(
value);
245 return STATUS_CODE_SUCCESS;
254 std::cout <<
"SupportVectorMachine: could not perform classification because the svm was uninitialized" << std::endl;
255 throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
260 std::cout <<
"SupportVectorMachine: could not perform classification because the initialized svm had no support vectors in the model" 262 throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
271 standardizedFeatures.push_back(
m_featureInfoList.at(i).StandardizeParameter(features.at(i).Get()));
274 double classScore(0.);
277 classScore += supportVectorInfo.m_yAlpha *
281 return classScore +
m_bias;
static double CubicKernel(const LArMvaHelper::MvaFeatureVector &supportVector, const LArMvaHelper::MvaFeatureVector &features, const double scaleFactor=1.)
An inhomogeneous cubic kernel.
pandora::StatusCode ReadComponent(pandora::TiXmlElement *pCurrentXmlElement)
Read the component at the current xml element.
pandora::StatusCode ReadSupportVector(const pandora::TiXmlHandle ¤tHandle)
Read the support vector component at the current xml handle.
MvaTypes::MvaFeatureVector MvaFeatureVector
bool m_enableProbability
Whether to enable probability calculations.
double m_scaleFactor
The kernel scale factor.
FeatureInfoVector m_featureInfoList
The list of FeatureInfo objects.
SVInfoList m_svInfoList
The list of SupportVectorInfo objects.
static double QuadraticKernel(const LArMvaHelper::MvaFeatureVector &supportVector, const LArMvaHelper::MvaFeatureVector &features, const double scaleFactor=1.)
An inhomogeneous quadratic kernel.
static double LinearKernel(const LArMvaHelper::MvaFeatureVector &supportVector, const LArMvaHelper::MvaFeatureVector &features, const double scaleFactor=1.)
A linear kernel.
pandora::StatusCode ReadMachine(const pandora::TiXmlHandle ¤tHandle)
Read the machine component at the current xml handle.
bool m_standardizeFeatures
Whether to standardize the features.
Header file for the lar support vector machine class.
decltype(auto) values(Coll &&coll)
Range-for loop helper iterating across the values of the specified collection.
double m_bias
The bias term.
void ReadXmlFile(const std::string &svmFileName, const std::string &svmName)
Read the svm parameters from an xml file.
KernelMap m_kernelMap
Map from the kernel types to the kernel functions.
KernelFunction m_kernelFunction
The kernel function.
KernelType m_kernelType
The kernel type.
pandora::StatusCode Initialize(const std::string ¶meterLocation, const std::string &svmName)
Initialize the svm using a serialized model.
double m_probAParameter
The first-order score coefficient for mapping to a probability using the logistic function...
unsigned int m_nFeatures
The number of features.
static double GaussianRbfKernel(const LArMvaHelper::MvaFeatureVector &supportVector, const LArMvaHelper::MvaFeatureVector &features, const double scaleFactor=1.)
A gaussian RBF kernel.
double CalculateClassificationScoreImpl(const LArMvaHelper::MvaFeatureVector &features) const
Implementation method for calculating the classification score using the trained model.
bool m_isInitialized
Whether this svm has been initialized.
KernelType
KernelType enum.
double m_probBParameter
The score offset parameter for mapping to a probability using the logistic function.
pandora::StatusCode ReadFeatures(const pandora::TiXmlHandle ¤tHandle)
Read the feature component at the current xml handle.