From c59298d4b5ef78bf8019474e2eed14e284c4f25e Mon Sep 17 00:00:00 2001 From: Brett Date: Fri, 19 Jul 2024 03:16:51 -0400 Subject: [PATCH] linear regressioin --- CMakeLists.txt | 2 +- GSab4SWWcAA1TNR.png | Bin 0 -> 22083 bytes include/slr.h | 97 ++++++++++++++++++++++ lib/blt-gp | 2 +- src/main.cpp | 197 ++++++++++++++++++++++++++++++++++---------- 5 files changed, 251 insertions(+), 47 deletions(-) create mode 100644 GSab4SWWcAA1TNR.png create mode 100644 include/slr.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 623fc33..4f55395 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(image-gp-6 VERSION 0.0.11) +project(image-gp-6 VERSION 0.0.12) include(FetchContent) diff --git a/GSab4SWWcAA1TNR.png b/GSab4SWWcAA1TNR.png new file mode 100644 index 0000000000000000000000000000000000000000..cd122b7de190f91d6ab68544c386c250a3fe1a07 GIT binary patch literal 22083 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 literal 0 HcmV?d00001 diff --git a/include/slr.h b/include/slr.h new file mode 100644 index 0000000..a0cedbc --- /dev/null +++ b/include/slr.h @@ -0,0 +1,97 @@ +#pragma once +/* + * Copyright (C) 2024 Brett Terpstra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef IMAGE_GP_6_SLR_H +#define IMAGE_GP_6_SLR_H + +template +float mean(const std::array& data) +{ + T x = 0; + for (blt::size_t n = 0; n < sample_size; n++) + { + x = x + data[n]; + } + x = x / sample_size; + return x; +} + +// https://github.com/georgemaier/simple-linear-regression/blob/master/slr.cpp +template +class slr +{ + private: + T WN1 = 0, WN2 = 0, WN3 = 0, WN4 = 0, Sy = 0, Sx = 0; + + public: + T r = 0, rsquared = 0, alpha = 0, beta = 0, x = 0, y = 0; + T yhat = 0, ybar = 0, xbar = 0; + T SSR = 0, SSE = 0, SST = 0; + T residualSE = 0, residualmax = 0, residualmin = 0, residualmean = 0, t = 0; + T SEBeta = 0, sample = 0, residuals[sample_size]{}; + + slr(const std::array& datax, const std::array& datay) + { + //This is the main regression function that is called when a new SLR object is created. + + //Calculate means + sample = sample_size; + xbar = mean(datax); + ybar = mean(datay); + + //Calculate r correlation + for (blt::size_t n = 0; n < sample_size; ++n) + { + WN1 += (datax[n] - xbar) * (datay[n] - ybar); + WN2 += pow((datax[n] - xbar), 2); + WN3 += pow((datay[n] - ybar), 2); + } + WN4 = WN2 * WN3; + r = WN1 / (std::sqrt(WN4)); + + //Calculate alpha and beta + Sy = std::sqrt(WN3 / (sample_size - 1)); + Sx = std::sqrt(WN2 / (sample_size - 1)); + beta = r * (Sy / Sx); + alpha = ybar - beta * xbar; + + //Calculate SSR, SSE, R-Squared, residuals + for (blt::size_t n = 0; n < sample_size; n++) + { + yhat = alpha + (beta * datax[n]); + SSE += std::pow((yhat - ybar), 2); + SSR += std::pow((datay[n] - yhat), 2); + residuals[n] = (datay[n] - yhat); + if (residuals[n] > residualmax) + residualmax = residuals[n]; + if (residuals[n] < residualmin) + residualmin = residuals[n]; + residualmean += std::fabs(residuals[n]); + } + residualmean = (residualmean / sample_size); + SST = SSR + SSE; + rsquared = SSE / SST; //Can also be obtained by r ^ 2 for simple regression (i.e. 1 independent variable) + + //Calculate T-test for Beta + residualSE = std::sqrt(SSR / (sample_size - 2)); + SEBeta = (residualSE / (Sx * std::sqrt(sample_size - 1))); + t = beta / SEBeta; + } +}; + +#endif //IMAGE_GP_6_SLR_H diff --git a/lib/blt-gp b/lib/blt-gp index c7bb4a4..8e5a3f3 160000 --- a/lib/blt-gp +++ b/lib/blt-gp @@ -1 +1 @@ -Subproject commit c7bb4a434b25d3c918cc7908e0b527aa0101b73d +Subproject commit 8e5a3f3b7c52a361a47199108be082730b1aeddd diff --git a/src/main.cpp b/src/main.cpp index 8e7bf47..618c0b0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,14 +35,23 @@ #include "opencv2/imgcodecs.hpp" #include "opencv2/imgproc.hpp" #include +#include "slr.h" + +constexpr size_t log2(size_t n) // NOLINT +{ + return ((n < 2) ? 1 : 1 + log2(n / 2)); +} static const blt::u64 SEED = std::random_device()(); -static constexpr long IMAGE_SIZE = 128; -static constexpr long IMAGE_PADDING = 16; -static constexpr long POP_SIZE = 64; +static constexpr blt::size_t IMAGE_SIZE = 128; +static constexpr blt::size_t IMAGE_PADDING = 16; +static constexpr blt::size_t POP_SIZE = 64; static constexpr blt::size_t CHANNELS = 3; static constexpr blt::size_t DATA_SIZE = IMAGE_SIZE * IMAGE_SIZE; static constexpr blt::size_t DATA_CHANNELS_SIZE = DATA_SIZE * CHANNELS; +static constexpr blt::size_t BOX_COUNT = static_cast(log2(IMAGE_SIZE / 2)); +static constexpr float THRESHOLD = 0.3; +static constexpr auto load_image = "../silly.png"; blt::gfx::matrix_state_manager global_matrices; blt::gfx::resource_manager resources; @@ -72,11 +81,17 @@ inline context get_pop_ctx(blt::size_t i) return ctx; } +inline blt::size_t get_index(blt::size_t x, blt::size_t y) +{ + return y * IMAGE_SIZE + x; +} + struct full_image_t { float rgb_data[DATA_SIZE * CHANNELS]{}; - full_image_t() { + full_image_t() + { for (auto& v : rgb_data) v = 0; } @@ -110,19 +125,30 @@ blt::i32 time_between_runs = 100; bool is_running = false; blt::gp::prog_config_t config = blt::gp::prog_config_t() - .set_initial_min_tree_size(2) - .set_initial_max_tree_size(6) - .set_elite_count(1) + .set_initial_min_tree_size(4) + .set_initial_max_tree_size(8) + .set_elite_count(2) .set_max_generations(50) - .set_mutation_chance(0.8) + .set_mutation_chance(1.0) .set_crossover_chance(1.0) - .set_reproduction_chance(0) + .set_reproduction_chance(0.5) .set_pop_size(POP_SIZE) - .set_thread_count(0); + .set_thread_count(16); blt::gp::type_provider type_system; blt::gp::gp_program program{type_system, SEED, config}; +template +constexpr static auto make_single(SINGLE_FUNC&& func) +{ + return [func](const full_image_t& a) { + full_image_t img{}; + for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) + img.rgb_data[i] = func(a.rgb_data[i]); + return img; + }; +} + blt::gp::operation_t add([](const full_image_t& a, const full_image_t& b) { full_image_t img{}; for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) @@ -147,30 +173,12 @@ blt::gp::operation_t pro_div([](const full_image_t& a, const full_image_t& b) { img.rgb_data[i] = b.rgb_data[i] == 0 ? 0 : (a.rgb_data[i] / b.rgb_data[i]); return img; }, "div"); -blt::gp::operation_t op_sin([](const full_image_t& a) { - full_image_t img{}; - for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) - img.rgb_data[i] = std::sin(a.rgb_data[i]); - return img; -}, "sin"); -blt::gp::operation_t op_cos([](const full_image_t& a) { - full_image_t img{}; - for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) - img.rgb_data[i] = std::cos(a.rgb_data[i]); - return img; -}, "cos"); -blt::gp::operation_t op_exp([](const full_image_t& a) { - full_image_t img{}; - for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) - img.rgb_data[i] = std::exp(a.rgb_data[i]); - return img; -}, "exp"); -blt::gp::operation_t op_log([](const full_image_t& a) { - full_image_t img{}; - for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) - img.rgb_data[i] = a.rgb_data[i] == 0 ? 0 : std::log(a.rgb_data[i]); - return img; -}, "log"); +blt::gp::operation_t op_sin(make_single((float (*)(float)) &std::sin), "sin"); +blt::gp::operation_t op_cos(make_single((float (*)(float)) &std::cos), "cos"); +blt::gp::operation_t op_atan(make_single((float (*)(float)) &std::atan), "atan"); +blt::gp::operation_t op_exp(make_single((float (*)(float)) &std::exp), "exp"); +blt::gp::operation_t op_abs(make_single((float (*)(float)) &std::abs), "abs"); +blt::gp::operation_t op_log(make_single((float (*)(float)) &std::log), "log"); blt::gp::operation_t op_v_mod([](const full_image_t& a, const full_image_t& b) { full_image_t img{}; for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) @@ -209,8 +217,15 @@ blt::gp::operation_t bitwise_xor([](const full_image_t& a, const full_image_t& b blt::gp::operation_t lit([]() { full_image_t img{}; - for (auto& i : img.rgb_data) - i = program.get_random().get_float(0.0f, 1.0f); + auto r = program.get_random().get_float(0.0f, 1.0f); + auto g = program.get_random().get_float(0.0f, 1.0f); + auto b = program.get_random().get_float(0.0f, 1.0f); + for (blt::size_t i = 0; i < DATA_SIZE; i++) + { + img.rgb_data[i * CHANNELS] = r; + img.rgb_data[i * CHANNELS + 1] = g; + img.rgb_data[i * CHANNELS + 2] = b; + } return img; }, "lit"); blt::gp::operation_t random_val([]() { @@ -309,6 +324,80 @@ static blt::gp::operation_t op_y_b([]() { return img; }, "y_b"); +constexpr float compare_values(float a, float b) +{ + if (std::isnan(a) || std::isnan(b) || std::isinf(a) || std::isinf(b)) + return IMAGE_SIZE; + auto dist = a - b; + //BLT_TRACE(std::sqrt(dist * dist)); + return std::sqrt(dist * dist); +} + +struct fractal_stats +{ + blt::f64 box_size, num_boxes, xy, x2, y2; +}; + +bool in_box(full_image_t& image, blt::size_t channel, blt::size_t box_size, blt::size_t i, blt::size_t j) +{ + // TODO: this could be made better by starting from the smallest boxes, moving upwards and using the last set of boxes + // instead of pixels, since they contain already computed information about if a box is in foam + for (blt::size_t x = i; x < i + box_size; x++) + { + for (blt::size_t y = j; y < j + box_size; y++) + { + if (image.rgb_data[get_index(x, y) * CHANNELS + channel] > THRESHOLD) + return true; + } + } + return false; +} + +blt::f64 get_fractal_value(full_image_t& image, blt::size_t channel) +{ + std::array box_data{}; + std::array x_data{}; + std::array y_data{}; + for (blt::size_t box_size = IMAGE_SIZE / 2; box_size > 1; box_size /= 2) + { + blt::ptrdiff_t num_boxes = 0; + for (blt::size_t i = 0; i < IMAGE_SIZE; i += box_size) + { + for (blt::size_t j = 0; j < IMAGE_SIZE; j += box_size) + { + if (in_box(image, channel, box_size, i, j)) + num_boxes++; + } + } + auto x = static_cast(std::log2(box_size)); + auto y = static_cast(num_boxes == 0 ? 0 : std::log2(num_boxes)); + //auto y = static_cast(num_boxes); + box_data[static_cast(std::log2(box_size)) - 1] = {x, y, x * y, x * x, y * y}; + x_data[static_cast(std::log2(box_size)) - 1] = x; + y_data[static_cast(std::log2(box_size)) - 1] = y; + //BLT_DEBUG("%lf vs %lf", x, y); + } +// fractal_stats total{}; +// for (const auto& b : box_data) +// { +// total.box_size += b.box_size; +// total.num_boxes += b.num_boxes; +// total.xy += b.xy; +// total.x2 += b.x2; +// total.y2 += b.y2; +// } +// +// auto n = static_cast(BOX_COUNT); +// auto b0 = ((total.num_boxes * total.x2) - (total.box_size * total.xy)) / ((n * total.x2) - (total.box_size * total.box_size)); +// auto b1 = ((n * total.xy) - (total.box_size * total.num_boxes)) / ((n * total.x2) - (total.box_size * total.box_size)); +// +// return b1; + + slr count{x_data, y_data}; + + return count.beta; +} + constexpr auto create_fitness_function() { return [](blt::gp::tree_t& current_tree, blt::gp::fitness_t& fitness, blt::size_t index) { @@ -317,17 +406,23 @@ constexpr auto create_fitness_function() fitness.raw_fitness = 0; for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) + fitness.raw_fitness += compare_values(v.rgb_data[i], base_image.rgb_data[i]); + + fitness.raw_fitness /= (IMAGE_SIZE * IMAGE_SIZE); + + for (blt::size_t channel = 0; channel < CHANNELS; channel++) { - auto base = base_image.rgb_data[i]; - auto set = v.rgb_data[i]; - if (std::isnan(set)) - set = 1 - base; - auto dist = set - base; - fitness.raw_fitness += std::sqrt(dist * dist); + auto raw = -get_fractal_value(v, channel); + auto fit = 1.0 - std::max(0.0, 1.0 - std::abs(1.35 - raw)); + BLT_DEBUG("Fitness %lf (raw: %lf) for channel %lu", fit, raw, channel); + if (std::isnan(raw)) + fitness.raw_fitness += 400; + else + fitness.raw_fitness += raw; } //BLT_TRACE("Raw fitness: %lf for %ld", fitness.raw_fitness, index); - fitness.standardized_fitness = fitness.raw_fitness / IMAGE_SIZE; + fitness.standardized_fitness = fitness.raw_fitness; fitness.adjusted_fitness = (1.0 / (1.0 + fitness.standardized_fitness)); }; } @@ -370,13 +465,13 @@ void init(const blt::gfx::window_data&) BLT_INFO("Using Seed: %ld", SEED); BLT_START_INTERVAL("Image Test", "Main"); BLT_DEBUG("Setup Base Image"); - base_image.load("../my_pride_flag.png"); + base_image.load(load_image); BLT_DEBUG("Setup Types and Operators"); type_system.register_type(); blt::gp::operator_builder builder{type_system}; - builder.add_operator(perlin); + //builder.add_operator(perlin); builder.add_operator(perlin_terminal); builder.add_operator(add); @@ -385,8 +480,10 @@ void init(const blt::gfx::window_data&) builder.add_operator(pro_div); builder.add_operator(op_sin); builder.add_operator(op_cos); + builder.add_operator(op_atan); builder.add_operator(op_exp); builder.add_operator(op_log); + builder.add_operator(op_abs); builder.add_operator(op_v_mod); builder.add_operator(bitwise_and); builder.add_operator(bitwise_or); @@ -471,6 +568,11 @@ void update(const blt::gfx::window_data& data) if (io.WantCaptureMouse) continue; + + if (blt::gfx::mousePressedLastFrame()) + { + program.get_current_pop().get_individuals()[i].tree.print(program, std::cout, false); + } // if (blt::gfx::mousePressedLastFrame()) // { @@ -515,6 +617,11 @@ int main() BLT_END_INTERVAL("Image Test", "Main"); base_image.save("input.png"); + for (blt::size_t i = 0; i < CHANNELS; i++) + { + auto v = -get_fractal_value(base_image, i); + BLT_INFO("Base image values per channel: %lf", v); + } BLT_PRINT_PROFILE("Image Test", blt::PRINT_CYCLES | blt::PRINT_THREAD | blt::PRINT_WALL);