Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ jobs:

- name: Configure with CMake
working-directory: ./build
run: cmake ..
run: cmake -DCMAKE_BUILD_TYPE=Debug ..

- name: Build
working-directory: ./build
run: cmake --build .
run: cmake --build . --config Debug

- name: Run tests
working-directory: ./build
run: ctest --output-on-failure
run: ctest -C Debug --output-on-failure
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,6 @@ docs/doxygen/
.DS_Store
Thumbs.db
.cache/

# Remove solution
cpp-ml/
57 changes: 33 additions & 24 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Option to build examples (enabled by default)
option(BUILD_EXAMPLES "Build examples" ON)

# Global include directories for headers
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/ml_library_include)

# Source files
file(GLOB_RECURSE SOURCES "src/*.cpp")
file(GLOB_RECURSE SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")

# Define the library target
add_library(cpp_ml_library STATIC ${SOURCES})

# Include directory for headers
target_include_directories(cpp_ml_library PUBLIC ${PROJECT_SOURCE_DIR}/ml_library_include)
target_include_directories(cpp_ml_library PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/ml_library_include)

# Installation
install(TARGETS cpp_ml_library DESTINATION lib)
Expand All @@ -23,33 +24,41 @@ install(DIRECTORY ml_library_include/ DESTINATION include)
# Enable testing
enable_testing()

# Add Catch2 for testing
include(FetchContent)
FetchContent_Declare(
Catch2
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
GIT_TAG v3.0.1 # Use the latest stable release of Catch2 v3 for improved compatibility
)
FetchContent_MakeAvailable(Catch2)

# Add tests with Catch2 v3
file(GLOB_RECURSE TEST_SOURCES "tests/**/*.cpp")
foreach(TEST_SOURCE ${TEST_SOURCES})
get_filename_component(TEST_NAME ${TEST_SOURCE} NAME_WE)
add_executable(${TEST_NAME} ${TEST_SOURCE})
target_link_libraries(${TEST_NAME} cpp_ml_library Catch2::Catch2WithMain)
target_include_directories(${TEST_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/ml_library_include)
add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME})
endforeach()
# Add individual test files as separate executables and define a macro for each
add_executable(LogisticRegressionTest tests/regression/LogisticRegressionTest.cpp)
target_compile_definitions(LogisticRegressionTest PRIVATE TEST_LOGISTIC_REGRESSION)
target_link_libraries(LogisticRegressionTest cpp_ml_library)

add_executable(PolynomialRegressionTest tests/regression/PolynomialRegressionTest.cpp)
target_compile_definitions(PolynomialRegressionTest PRIVATE TEST_POLYNOMIAL_REGRESSION)
target_link_libraries(PolynomialRegressionTest cpp_ml_library)

add_executable(MultiLinearRegressionTest tests/regression/MultilinearRegressionTest.cpp)
target_compile_definitions(MultiLinearRegressionTest PRIVATE TEST_MULTILINEAR_REGRESSION)
target_link_libraries(MultiLinearRegressionTest cpp_ml_library)

# Register individual tests
add_test(NAME LogisticRegressionTest COMMAND LogisticRegressionTest)
add_test(NAME PolynomialRegressionTest COMMAND PolynomialRegressionTest)
add_test(NAME MultiLinearRegressionTest COMMAND MultiLinearRegressionTest)

# Add example executables if BUILD_EXAMPLES is ON
if(BUILD_EXAMPLES)
file(GLOB_RECURSE EXAMPLE_SOURCES "examples/*.cpp")
file(GLOB_RECURSE EXAMPLE_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/examples/*.cpp")
foreach(EXAMPLE_SOURCE ${EXAMPLE_SOURCES})
get_filename_component(EXAMPLE_NAME ${EXAMPLE_SOURCE} NAME_WE)
set(EXAMPLE_TARGET "example_${EXAMPLE_NAME}") # Add a prefix to the executable name
add_executable(${EXAMPLE_TARGET} ${EXAMPLE_SOURCE}) # Use prefixed name for executable
target_link_libraries(${EXAMPLE_TARGET} cpp_ml_library)
target_include_directories(${EXAMPLE_TARGET} PUBLIC ${PROJECT_SOURCE_DIR}/ml_library_include)
target_include_directories(${EXAMPLE_TARGET} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/ml_library_include)

# Define specific macros to control main() inclusion if necessary
if(EXAMPLE_NAME STREQUAL "LogisticRegressionExample")
target_compile_definitions(${EXAMPLE_TARGET} PRIVATE TEST_LOGISTIC_REGRESSION)
elseif(EXAMPLE_NAME STREQUAL "MultilinearRegressionExample")
target_compile_definitions(${EXAMPLE_TARGET} PRIVATE TEST_MULTILINEAR_REGRESSION)
elseif(EXAMPLE_NAME STREQUAL "PolynomialRegressionExample")
target_compile_definitions(${EXAMPLE_TARGET} PRIVATE TEST_POLYNOMIAL_REGRESSION)
endif()
endforeach()
endif()
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,10 @@ To use this library in your C++ project, include the master header file:
The following machine learning algorithms are planned, inspired by concepts and techniques taught in the Udemy course:

1. **Regression**
- [ ] Polynomial Regression
- [ ] Multi-Linear Regression
- [x] Polynomial Regression
- [x] Multi-Linear Regression
- [x] Logistic Regression


2. **Classification**
- [ ] Decision Tree Classifier
Expand All @@ -85,8 +87,9 @@ The following machine learning algorithms are planned, inspired by concepts and

| Algorithm Category | Algorithm | Implemented | Tests | Examples |
|--------------------------|------------------------------|-------------|-------|----------|
| **Regression** | Polynomial Regression | [ ] | [ ] | [ ] |
| | Multi-Linear Regression | [ ] | [ ] | [ ] |
| **Regression** | Polynomial Regression | [x] | [ ] | [x] |
| | Logistic Regression | [x] | [ ] | [x] |
| | Multi-Linear Regression | [x] | [ ] | [x] |
| **Classification** | Decision Tree Classifier | [ ] | [ ] | [ ] |
| | Random Forest Classifier | [ ] | [ ] | [ ] |
| | K-Nearest Neighbors | [ ] | [ ] | [ ] |
Expand Down
41 changes: 41 additions & 0 deletions examples/LogisticRegressionExample.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include "../ml_library_include/ml/regression/LogisticRegression.hpp"
#include <iostream>
#include <vector>
#include <cmath>

// Test function for Logistic Regression
void testLogisticRegression() {
LogisticRegression model(0.1, 1000);

std::vector<std::vector<double>> features = {
{0.0, 0.0},
{1.0, 1.0},
{1.0, 0.0},
{0.0, 1.0}
};

std::vector<int> labels = { 0, 1, 1, 0 };

model.train(features, labels);

std::vector<double> testInput = { 1.0, 1.0 };
int predictedClass = model.predict(testInput);

std::cout << "Predicted class for {1.0, 1.0}: " << predictedClass << std::endl;

// Optionally add a check to verify the predicted class
if (predictedClass == 1) {
std::cout << "Test passed: Correct prediction." << std::endl;
}
else {
std::cerr << "Test failed: Prediction was " << predictedClass << ", expected 1." << std::endl;
}
}

// Only include main if TEST_LOGISTIC_REGRESSION is defined
#ifdef TEST_LOGISTIC_REGRESSION
int main() {
testLogisticRegression();
return 0;
}
#endif
49 changes: 49 additions & 0 deletions examples/MultilinearRegressionExample.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include "../ml_library_include/ml/regression/MultiLinearRegression.hpp"
#include <vector>
#include <iostream>
#include <cmath>

// Helper function for approximate equality check
inline bool approxEqual(double a, double b, double tolerance = 0.1) {
return std::fabs(a - b) < tolerance;
}

void testMultilinearRegression() {
MultilinearRegression model(0.01, 1000);

std::vector<std::vector<double>> features = {
{1.0, 2.0},
{2.0, 3.0},
{3.0, 4.0},
{4.0, 5.0}
};

std::vector<double> target = { 3.0, 5.0, 7.0, 9.0 };

try {
model.train(features, target);
std::cout << "Training passed." << std::endl;
}
catch (...) {
std::cerr << "Training failed with an exception!" << std::endl;
return;
}

std::vector<double> testFeatures = { 5.0, 6.0 };
double prediction = model.predict(testFeatures);

if (approxEqual(prediction, 11.0)) {
std::cout << "Test passed: Prediction is within tolerance." << std::endl;
}
else {
std::cerr << "Test failed: Prediction is " << prediction << ", expected ~11.0." << std::endl;
}
}

// Only include main if TEST_MULTILINEAR_REGRESSION is defined
#ifdef TEST_MULTILINEAR_REGRESSION
int main() {
testMultilinearRegression();
return 0;
}
#endif
40 changes: 40 additions & 0 deletions examples/PolynomialRegressionExample.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "../ml_library_include/ml/regression/PolynomialRegression.hpp"
#include <iostream>
#include <vector>
#include <cmath>

// Helper function for approximate equality check
inline bool approxEqual(double a, double b, double tolerance = 0.1) {
return std::fabs(a - b) < tolerance;
}

// Test function for Polynomial Regression
void testPolynomialRegression() {
PolynomialRegression model(2); // Quadratic regression

std::vector<double> x = { 1.0, 2.0, 3.0, 4.0 };
std::vector<double> y = { 3.0, 5.0, 7.0, 9.0 };

model.train(x, y);

double testInput = 5.0;
double prediction = model.predict(testInput);

std::cout << "Predicted value for " << testInput << ": " << prediction << std::endl;

// Check if prediction is close to the expected value
if (approxEqual(prediction, 11.0)) {
std::cout << "Test passed: Prediction is within tolerance." << std::endl;
}
else {
std::cerr << "Test failed: Prediction is " << prediction << ", expected ~11.0." << std::endl;
}
}

// Only include main if TEST_POLYNOMIAL_REGRESSION is defined
#ifdef TEST_POLYNOMIAL_REGRESSION
int main() {
testPolynomialRegression();
return 0;
}
#endif
17 changes: 0 additions & 17 deletions ml_library_include/ml/ml.h

This file was deleted.

17 changes: 17 additions & 0 deletions ml_library_include/ml/ml.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// ml.h - Master header file
#ifndef ML_H
#define ML_H

#include "tree/DecisionTreeClassifier.hpp"
#include "tree/DecisionTreeRegressor.hpp"
#include "tree/RandomForestClassifier.hpp"
#include "tree/RandomForestRegressor.hpp"
#include "regression/PolynomialRegression.hpp"
#include "regression/MultiLinearRegression.hpp"
#include "neural_network/ANN.hpp"
#include "neural_network/CNN.hpp"
#include "clustering/KMeans.hpp"
#include "association/Apriori.hpp"
#include "association/Eclat.hpp"

#endif // ML_H
Loading
Loading