Skip to content

Commit

Permalink
normalize input, fix data aggregation phase
Browse files Browse the repository at this point in the history
  • Loading branch information
buensons committed Nov 16, 2020
1 parent 7c8e8de commit a0e7d01
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 18 deletions.
2 changes: 2 additions & 0 deletions include/TimeSeriesPredictor.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <random>
#include <vector>
#include <random>
#include <chrono>
#include <cuda.h>
#include <cuda_runtime.h>

Expand Down Expand Up @@ -39,6 +40,7 @@ private:
int numberOfNodes;
int populationSize;
int windowSize;
float currentMean;
std::mt19937 mt;
std::uniform_real_distribution<float> distribution;

Expand Down
14 changes: 14 additions & 0 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
#include <fstream>
#include <string>
#include <sstream>
#include <algorithm>

#include "include/TimeSeriesPredictor.cuh"

auto readDataToMemory() -> std::vector<float>;
auto normalizeData(std::vector<float> &data) -> void;
auto usage(char * arg) -> void;

int main(int argc, char ** argv) {
Expand All @@ -29,7 +31,9 @@ int main(int argc, char ** argv) {
return 1;
}

std::cout << "Reading input data...\n";
auto timeSeries = readDataToMemory();
normalizeData(timeSeries);

TimeSeriesPredictor predictor(timeSeries, nodes, populationSize, windowSize);
std::vector<float> weights = predictor.train();
Expand All @@ -40,6 +44,16 @@ auto usage(char * arg) -> void {
std::cerr << "Usage: " << arg << " <num_of_nodes> <population_size> <window_size>" << std::endl;
}

auto normalizeData(std::vector<float> &data) -> void {
const auto [a, b] = std::minmax_element(begin(data), end(data));
float min = *a;
float max = *b;

for(int i = 0; i < data.size(); ++i) {
data[i] = (data[i] - min) / (max - min);
}
}

auto readDataToMemory() -> std::vector<float> {
std::string dataFolder = "./data/";
std::vector<float> dataVector;
Expand Down
6 changes: 4 additions & 2 deletions src/FitnessFunctionKernel.cu
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,17 @@ __global__ void calculate_fitness(
int i = 0;

while(i < data_size - window_size * node_number) {

// data aggregation
for(int j = 0; j < window_size * node_number; ++j) {
mapInput[j % node_number + index * node_number] += dataWeights[j + window_size * node_number * index] * data[i + j];
}

// squashing function for map input
for(int j = 0; j < node_number; ++j) {
mapInput[j + index * node_number] = 1.0 / (1.0 + expf(-5 * mapInput[j + index * node_number]));
}

// one step of cognitive map computation for each node
for(int j = 0; j < node_number; ++j) {

float x = 0.0f;
Expand All @@ -35,7 +37,7 @@ __global__ void calculate_fitness(
}

float y = 1.0 / (1.0 + expf(-5 * x));
float prediction_error = abs(y - data[j+i+1]);
float prediction_error = abs(y - data[window_size * node_number + i + j]);
cumulative_error += prediction_error;
}
i += node_number;
Expand Down
51 changes: 35 additions & 16 deletions src/TimeSeriesPredictor.cu
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "../include/TimeSeriesPredictor.cuh"
#include <chrono>

TimeSeriesPredictor::TimeSeriesPredictor(std::vector<float> data, int numberOfNodes, int populationSize, int windowSize) : distribution(0.0, 1.0) {
this->data = data;
std::random_device rd;
Expand All @@ -8,6 +8,7 @@ TimeSeriesPredictor::TimeSeriesPredictor(std::vector<float> data, int numberOfNo
this->populationSize = populationSize;
this->windowSize = windowSize;
this->k = 5.0;
this->currentMean = 0;
}

TimeSeriesPredictor::~TimeSeriesPredictor() {
Expand All @@ -33,18 +34,25 @@ auto TimeSeriesPredictor::prepareGpuMemory() -> void {
}

auto TimeSeriesPredictor::train() -> std::vector<float> {
this->generatePopulation();
this->prepareGpuMemory();
int generation = 0;
Chromosome bestCandidate, previousBestCandidate;
previousBestCandidate.fitness = 0.0f;

std::cout << "Generating initial population...\n";
this->generatePopulation();
this->prepareGpuMemory();

std::cout << "Training started...\n";
while(true) {
std::vector<Chromosome> nextGen;
this->launchCudaKernel();
Chromosome bestCandidate = this->maxFitness(this->population);
if(generation == 500 || abs(1.0 - bestCandidate.fitness) < 1e-5) break;
bestCandidate = this->maxFitness(this->population);

std::cout << "-----GEN " << generation << " -------" << std::endl;
std::cout << "Best fitness: " << bestCandidate.fitness << std::endl;
std::cout << "Mean fitness: " << this->currentMean << std::endl;

if(generation == 100 || abs(1.0 - bestCandidate.fitness) < 1e-4) break;

while(nextGen.size() < this->populationSize) {
auto parents = this->tournamentSelection();
Expand All @@ -58,10 +66,12 @@ auto TimeSeriesPredictor::train() -> std::vector<float> {
nextGen.push_back(this->mutate(parents[0]));
}
}
this->population = nextGen;
this->population = nextGen;
previousBestCandidate = bestCandidate;
++generation;
}
return this->maxFitness(this->population).genes;
// return this->maxFitness(this->population).genes;
return bestCandidate.genes;
}

auto TimeSeriesPredictor::printPopulation() -> void {
Expand All @@ -79,7 +89,7 @@ auto TimeSeriesPredictor::maxFitness(std::vector<Chromosome> population) -> Chro
float maxFitness = -1.0;
Chromosome max;

for(auto chr: this->population) {
for(auto chr: population) {
if(chr.fitness > maxFitness) {
maxFitness = chr.fitness;
max = chr;
Expand All @@ -101,7 +111,7 @@ auto TimeSeriesPredictor::crossover(Chromosome chr1, Chromosome chr2) -> std::ve

auto TimeSeriesPredictor::mutate(Chromosome chr) -> Chromosome {
for(int i = 0; i < chr.genes.size(); ++i) {
if(this->distribution(mt) < 0.18) {
if(this->distribution(mt) < 0.1) {
chr.genes[i] = distribution(mt) * 2 - 1;
}
}
Expand Down Expand Up @@ -146,7 +156,6 @@ auto TimeSeriesPredictor::randomSampleFromPopulation(int size) -> std::vector<Ch
}

auto TimeSeriesPredictor::launchCudaKernel() -> void {
int dataSize = this->data.size();
int w = this->windowSize;
int n = this->numberOfNodes;

Expand All @@ -156,20 +165,30 @@ auto TimeSeriesPredictor::launchCudaKernel() -> void {
gpuErrchk(cudaMemcpy(&this->mapWeightsGpu[i * n * n], &weights[w * n], n * n * sizeof(float), cudaMemcpyHostToDevice));
}

gpuErrchk(cudaMemset(this->mapInputGpu, 0, n * sizeof(float)));
gpuErrchk(cudaMemset(this->mapInputGpu, 0, this->populationSize * n * sizeof(float)));

calculate_fitness<<<4, 512>>>(
this->dataWeightsGpu,
this->mapWeightsGpu,
this->dataGpu,
this->fitnessGpu,
this->mapInputGpu,
w,
n,
this->populationSize,
this->data.size()
);

calculate_fitness<<<4, 512>>>(this->dataWeightsGpu, this->mapWeightsGpu, this->dataGpu, this->fitnessGpu, this->mapInputGpu, w, n, this->populationSize, dataSize);
gpuErrchk(cudaPeekAtLastError());
gpuErrchk(cudaDeviceSynchronize());

gpuErrchk(cudaMemcpy(fitnessHost, fitnessGpu, this->populationSize * sizeof(float), cudaMemcpyDeviceToHost));

auto sum = 0.0;
auto ehh = 0;
auto count = 0;
for(int i = 0; i < this->populationSize; ++i) {
sum += fitnessHost[i];
++ehh;
++count;
this->population[i].fitness = fitnessHost[i];
}
printf("The mean is %f \n", sum / ehh);
this->currentMean = sum / count;
}

0 comments on commit a0e7d01

Please sign in to comment.