41 : learning_rate(l_rate), num_iterations(num_iters), lambda(lda) {
48 const std::vector<int> &y_train) {
50 weights.assign(X_train[0].size() + 1, 0.0);
52 for (
int iter = 0; iter < num_iterations; ++iter) {
53 std::vector<double> gradient(X_train[0].size() + 1, 0.0);
55 for (
size_t i = 0; i < X_train.size(); ++i) {
57 std::vector<double> input = {1.0};
58 input.insert(input.end(), X_train[i].begin(), X_train[i].end());
61 double predicted = sigmoid(std::inner_product(input.begin(),
67 for (
size_t j = 0; j < gradient.size(); ++j) {
68 gradient[j] += (predicted - y_train[i]) * input[j];
73 for (
size_t j = 0; j < weights.size(); ++j) {
74 weights[j] -= learning_rate *
75 (gradient[j] / X_train.size() + lambda * weights[j]);
82 std::vector<double> predictions;
83 for (
size_t i = 0; i < X_test.size(); ++i) {
85 std::vector<double> input = {1.0};
86 input.insert(input.end(), X_test[i].begin(), X_test[i].end());
89 double predicted = sigmoid(std::inner_product(input.begin(),
93 predictions.push_back(predicted);
100 const std::vector<int> &y_test) {
101 std::vector<double> predictions = predict(X_test);
103 for (
size_t i = 0; i < predictions.size(); ++i) {
104 if ((predictions[i] >= 0.5 && y_test[i] == 1) ||
105 (predictions[i] < 0.5 && y_test[i] == 0)) {
109 return static_cast<double>(correct) / y_test.size();
113 return 1.0 / (1.0 + exp(-z));
118 throw std::invalid_argument(
"Input feature matrix is empty.");
121 size_t num_features = X[0].size();
122 for (
size_t j = 0; j < num_features; ++j) {
123 double min_val = X[0][j], max_val = X[0][j];
124 for (
size_t i = 1; i < X.size(); ++i) {
125 if (X[i][j] < min_val) {
128 if (X[i][j] > max_val) {
133 if (fabs(min_val - max_val) < std::numeric_limits<double>::epsilon()) {
137 double range = max_val - min_val;
138 for (
size_t i = 0; i < X.size(); ++i) {
139 X[i][j] = (X[i][j] - min_val) / range;
146 const std::vector<int> &y) {
148 for (
size_t i = 0; i < X.size(); ++i) {
150 std::vector<double> input = {1.0};
151 input.insert(input.end(), X[i].begin(), X[i].end());
153 double predicted = sigmoid(std::inner_product(input.begin(),
157 cost += -y[i] * log(predicted) - (1 - y[i]) * log(1 - predicted);
165 std::vector<int> classifications;
166 for (
size_t i = 0; i < X.size(); ++i) {
168 std::vector<double> input = {1.0};
169 input.insert(input.end(), X[i].begin(), X[i].end());
172 double predicted = sigmoid(std::inner_product(input.begin(),
176 int classification = predicted >= 0.5 ? 1 : 0;
177 classifications.push_back(classification);
179 return classifications;
double sigmoid(double z)
Computes the sigmoid function value for the given input.
std::vector< int > classify(const std::vector< std::vector< double >> &X)
Predicts the class labels for the given test data.
std::vector< double > predict(const std::vector< std::vector< double >> &X_test)
Computes the predicted probabilities for the given test data.
~LogReg()
Destructor for the LogReg class.
double accuracy(const std::vector< std::vector< double >> &X_test, const std::vector< int > &y_test)
Computes the accuracy of the model on the given test data.
LogReg(double l_rate=001, int num_iters=1000, double lda=001)
Constructor for the LogReg class.
void train(const std::vector< std::vector< double >> &X_train, const std::vector< int > &y_train)
Trains the logistic regression model on the given training data.
double cost_function(const std::vector< std::vector< double >> &X, const std::vector< int > &y)
Computes the cost function value for the given input data and labels.
void feature_scaling(std::vector< std::vector< double >> &X)
Performs feature scaling on the input feature matrix.