Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
9966ba4af8
|
7
.gitmodules
vendored
7
.gitmodules
vendored
@@ -3,8 +3,11 @@
|
|||||||
path = lib/json
|
path = lib/json
|
||||||
url = https://github.com/nlohmann/json.git
|
url = https://github.com/nlohmann/json.git
|
||||||
[submodule "lib/catch2"]
|
[submodule "lib/catch2"]
|
||||||
path = lib/catch2
|
path = tests/lib/catch2
|
||||||
url = https://github.com/catchorg/Catch2.git
|
url = https://github.com/catchorg/Catch2.git
|
||||||
[submodule "lib/mdlp"]
|
[submodule "lib/mdlp"]
|
||||||
path = lib/mdlp
|
path = tests/lib/mdlp
|
||||||
url = https://github.com/rmontanana/mdlp
|
url = https://github.com/rmontanana/mdlp
|
||||||
|
[submodule "tests/lib/Files"]
|
||||||
|
path = tests/lib/Files
|
||||||
|
url = https://github.com/rmontanana/ArffFiles
|
||||||
|
@@ -78,9 +78,9 @@ add_subdirectory(pyclfs)
|
|||||||
# -------
|
# -------
|
||||||
if (ENABLE_TESTING)
|
if (ENABLE_TESTING)
|
||||||
MESSAGE("Testing enabled")
|
MESSAGE("Testing enabled")
|
||||||
add_git_submodule(lib/catch2)
|
add_git_submodule(tests/lib/catch2)
|
||||||
add_git_submodule(lib/mdlp)
|
add_git_submodule(tests/lib/mdlp)
|
||||||
add_subdirectory(lib/Files)
|
add_subdirectory(tests/lib/Files)
|
||||||
include(CTest)
|
include(CTest)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
endif (ENABLE_TESTING)
|
endif (ENABLE_TESTING)
|
||||||
|
@@ -137,7 +137,7 @@
|
|||||||
|
|
||||||
include(CMakeParseArguments)
|
include(CMakeParseArguments)
|
||||||
|
|
||||||
option(CODE_COVERAGE_VERBOSE "Verbose information" FALSE)
|
option(CODE_COVERAGE_VERBOSE "Verbose information" TRUE)
|
||||||
|
|
||||||
# Check prereqs
|
# Check prereqs
|
||||||
find_program( GCOV_PATH gcov )
|
find_program( GCOV_PATH gcov )
|
||||||
@@ -160,8 +160,12 @@ foreach(LANG ${LANGUAGES})
|
|||||||
endif()
|
endif()
|
||||||
elseif(NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "GNU"
|
elseif(NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "GNU"
|
||||||
AND NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(LLVM)?[Ff]lang")
|
AND NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(LLVM)?[Ff]lang")
|
||||||
|
if ("${LANG}" MATCHES "CUDA")
|
||||||
|
message(STATUS "Ignoring CUDA")
|
||||||
|
else()
|
||||||
message(FATAL_ERROR "Compiler is not GNU or Flang! Aborting...")
|
message(FATAL_ERROR "Compiler is not GNU or Flang! Aborting...")
|
||||||
endif()
|
endif()
|
||||||
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
set(COVERAGE_COMPILER_FLAGS "-g --coverage"
|
set(COVERAGE_COMPILER_FLAGS "-g --coverage"
|
||||||
|
@@ -1,168 +0,0 @@
|
|||||||
#include "ArffFiles.h"
|
|
||||||
#include <fstream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <map>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
ArffFiles::ArffFiles() = default;
|
|
||||||
|
|
||||||
std::vector<std::string> ArffFiles::getLines() const
|
|
||||||
{
|
|
||||||
return lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long int ArffFiles::getSize() const
|
|
||||||
{
|
|
||||||
return lines.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::pair<std::string, std::string>> ArffFiles::getAttributes() const
|
|
||||||
{
|
|
||||||
return attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ArffFiles::getClassName() const
|
|
||||||
{
|
|
||||||
return className;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ArffFiles::getClassType() const
|
|
||||||
{
|
|
||||||
return classType;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::vector<float>>& ArffFiles::getX()
|
|
||||||
{
|
|
||||||
return X;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<int>& ArffFiles::getY()
|
|
||||||
{
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArffFiles::loadCommon(std::string fileName)
|
|
||||||
{
|
|
||||||
std::ifstream file(fileName);
|
|
||||||
if (!file.is_open()) {
|
|
||||||
throw std::invalid_argument("Unable to open file");
|
|
||||||
}
|
|
||||||
std::string line;
|
|
||||||
std::string keyword;
|
|
||||||
std::string attribute;
|
|
||||||
std::string type;
|
|
||||||
std::string type_w;
|
|
||||||
while (getline(file, line)) {
|
|
||||||
if (line.empty() || line[0] == '%' || line == "\r" || line == " ") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (line.find("@attribute") != std::string::npos || line.find("@ATTRIBUTE") != std::string::npos) {
|
|
||||||
std::stringstream ss(line);
|
|
||||||
ss >> keyword >> attribute;
|
|
||||||
type = "";
|
|
||||||
while (ss >> type_w)
|
|
||||||
type += type_w + " ";
|
|
||||||
attributes.emplace_back(trim(attribute), trim(type));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (line[0] == '@') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
lines.push_back(line);
|
|
||||||
}
|
|
||||||
file.close();
|
|
||||||
if (attributes.empty())
|
|
||||||
throw std::invalid_argument("No attributes found");
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArffFiles::load(const std::string& fileName, bool classLast)
|
|
||||||
{
|
|
||||||
int labelIndex;
|
|
||||||
loadCommon(fileName);
|
|
||||||
if (classLast) {
|
|
||||||
className = std::get<0>(attributes.back());
|
|
||||||
classType = std::get<1>(attributes.back());
|
|
||||||
attributes.pop_back();
|
|
||||||
labelIndex = static_cast<int>(attributes.size());
|
|
||||||
} else {
|
|
||||||
className = std::get<0>(attributes.front());
|
|
||||||
classType = std::get<1>(attributes.front());
|
|
||||||
attributes.erase(attributes.begin());
|
|
||||||
labelIndex = 0;
|
|
||||||
}
|
|
||||||
generateDataset(labelIndex);
|
|
||||||
}
|
|
||||||
void ArffFiles::load(const std::string& fileName, const std::string& name)
|
|
||||||
{
|
|
||||||
int labelIndex;
|
|
||||||
loadCommon(fileName);
|
|
||||||
bool found = false;
|
|
||||||
for (int i = 0; i < attributes.size(); ++i) {
|
|
||||||
if (attributes[i].first == name) {
|
|
||||||
className = std::get<0>(attributes[i]);
|
|
||||||
classType = std::get<1>(attributes[i]);
|
|
||||||
attributes.erase(attributes.begin() + i);
|
|
||||||
labelIndex = i;
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
throw std::invalid_argument("Class name not found");
|
|
||||||
}
|
|
||||||
generateDataset(labelIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArffFiles::generateDataset(int labelIndex)
|
|
||||||
{
|
|
||||||
X = std::vector<std::vector<float>>(attributes.size(), std::vector<float>(lines.size()));
|
|
||||||
auto yy = std::vector<std::string>(lines.size(), "");
|
|
||||||
auto removeLines = std::vector<int>(); // Lines with missing values
|
|
||||||
for (size_t i = 0; i < lines.size(); i++) {
|
|
||||||
std::stringstream ss(lines[i]);
|
|
||||||
std::string value;
|
|
||||||
int pos = 0;
|
|
||||||
int xIndex = 0;
|
|
||||||
while (getline(ss, value, ',')) {
|
|
||||||
if (pos++ == labelIndex) {
|
|
||||||
yy[i] = value;
|
|
||||||
} else {
|
|
||||||
if (value == "?") {
|
|
||||||
X[xIndex++][i] = -1;
|
|
||||||
removeLines.push_back(i);
|
|
||||||
} else
|
|
||||||
X[xIndex++][i] = stof(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (auto i : removeLines) {
|
|
||||||
yy.erase(yy.begin() + i);
|
|
||||||
for (auto& x : X) {
|
|
||||||
x.erase(x.begin() + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
y = factorize(yy);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ArffFiles::trim(const std::string& source)
|
|
||||||
{
|
|
||||||
std::string s(source);
|
|
||||||
s.erase(0, s.find_first_not_of(" '\n\r\t"));
|
|
||||||
s.erase(s.find_last_not_of(" '\n\r\t") + 1);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<int> ArffFiles::factorize(const std::vector<std::string>& labels_t)
|
|
||||||
{
|
|
||||||
std::vector<int> yy;
|
|
||||||
yy.reserve(labels_t.size());
|
|
||||||
std::map<std::string, int> labelMap;
|
|
||||||
int i = 0;
|
|
||||||
for (const std::string& label : labels_t) {
|
|
||||||
if (labelMap.find(label) == labelMap.end()) {
|
|
||||||
labelMap[label] = i++;
|
|
||||||
}
|
|
||||||
yy.push_back(labelMap[label]);
|
|
||||||
}
|
|
||||||
return yy;
|
|
||||||
}
|
|
@@ -1,32 +0,0 @@
|
|||||||
#ifndef ARFFFILES_H
|
|
||||||
#define ARFFFILES_H
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class ArffFiles {
|
|
||||||
private:
|
|
||||||
std::vector<std::string> lines;
|
|
||||||
std::vector<std::pair<std::string, std::string>> attributes;
|
|
||||||
std::string className;
|
|
||||||
std::string classType;
|
|
||||||
std::vector<std::vector<float>> X;
|
|
||||||
std::vector<int> y;
|
|
||||||
void generateDataset(int);
|
|
||||||
void loadCommon(std::string);
|
|
||||||
public:
|
|
||||||
ArffFiles();
|
|
||||||
void load(const std::string&, bool = true);
|
|
||||||
void load(const std::string&, const std::string&);
|
|
||||||
std::vector<std::string> getLines() const;
|
|
||||||
unsigned long int getSize() const;
|
|
||||||
std::string getClassName() const;
|
|
||||||
std::string getClassType() const;
|
|
||||||
static std::string trim(const std::string&);
|
|
||||||
std::vector<std::vector<float>>& getX();
|
|
||||||
std::vector<int>& getY();
|
|
||||||
std::vector<std::pair<std::string, std::string>> getAttributes() const;
|
|
||||||
static std::vector<int> factorize(const std::vector<std::string>& labels_t);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1 +0,0 @@
|
|||||||
add_library(ArffFiles ArffFiles.cc)
|
|
2
lib/json
2
lib/json
Submodule lib/json updated: 378e091795...48e7b4c23b
@@ -4,5 +4,5 @@ include_directories(
|
|||||||
${PyClassifiers_SOURCE_DIR}/lib/json/include
|
${PyClassifiers_SOURCE_DIR}/lib/json/include
|
||||||
${Bayesnet_INCLUDE_DIRS}
|
${Bayesnet_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
add_library(PyClassifiers ODTE.cc STree.cc SVC.cc RandomForest.cc XGBoost.cc PyClassifier.cc PyWrap.cc)
|
add_library(PyClassifiers ODTE.cc STree.cc SVC.cc RandomForest.cc XGBoost.cc PyClassifier.cc PyWrap.cc PBC4cip.cc)
|
||||||
target_link_libraries(PyClassifiers ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::boost Boost::python Boost::numpy)
|
target_link_libraries(PyClassifiers ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::boost Boost::python Boost::numpy)
|
8
pyclfs/PBC4cip.cc
Normal file
8
pyclfs/PBC4cip.cc
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#include "PBC4cip.h"
|
||||||
|
|
||||||
|
namespace pywrap {
|
||||||
|
PBC4cip::PBC4cip() : PyClassifier("core.PBC4cip", "PBC4cip", true)
|
||||||
|
{
|
||||||
|
validHyperparameters = { "random_state" };
|
||||||
|
}
|
||||||
|
} /* namespace pywrap */
|
13
pyclfs/PBC4cip.h
Normal file
13
pyclfs/PBC4cip.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#ifndef PBC4CIP_H
|
||||||
|
#define PBC4CIP_H
|
||||||
|
#include "PyClassifier.h"
|
||||||
|
|
||||||
|
namespace pywrap {
|
||||||
|
class PBC4cip : public PyClassifier {
|
||||||
|
public:
|
||||||
|
PBC4cip();
|
||||||
|
~PBC4cip() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace pywrap */
|
||||||
|
#endif /* PBC4CIP_H */
|
@@ -136,3 +136,13 @@ TEST_CASE("XGBoost", "[PyClassifiers]")
|
|||||||
// }
|
// }
|
||||||
// std::cout << predict << std::endl;
|
// std::cout << predict << std::endl;
|
||||||
// }
|
// }
|
||||||
|
TEST_CASE("PBC4cip", "[PyClassifiers]")
|
||||||
|
{
|
||||||
|
auto raw = RawDatasets("iris", true);
|
||||||
|
auto clf = pywrap::PBC4cip();
|
||||||
|
clf.fit(raw.Xt, raw.yt, raw.featurest, raw.classNamet, raw.statest);
|
||||||
|
nlohmann::json hyperparameters = { };
|
||||||
|
clf.setHyperparameters(hyperparameters);
|
||||||
|
auto score = clf.score(raw.Xt, raw.yt);
|
||||||
|
REQUIRE(score == Catch::Approx(0.98).epsilon(raw.epsilon));
|
||||||
|
}
|
1
tests/lib/Files
Submodule
1
tests/lib/Files
Submodule
Submodule tests/lib/Files added at a4329f5f9d
Reference in New Issue
Block a user