Created
December 11, 2014 20:28
-
-
Save fxfactorial/b488cff19104e316eba7 to your computer and use it in GitHub Desktop.
How to make a smooth gif animation?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <ctype.h> | |
#include <string.h> | |
#include <sys/mman.h> | |
#include "perceptron.h" | |
double dot_product(float *a, float *b, int len) | |
{ | |
double sum = 0; | |
for (int i = 0; i < len; i++) | |
sum += a[i] * b[i]; | |
return sum; | |
} | |
struct sample_data* class_error(float *weights) | |
{ | |
/* Pick a random sample, if our w vector would have made a | |
mistake, then that means we needed to have updated */ | |
double result; | |
for (int i = 0; i < p.num_samples; i++) { | |
result = dot_product(weights, p.data[i].x, 3); | |
if ((result > 0 ? 1: -1) != p.data[i].label) | |
return &p.data[i]; | |
} | |
return NULL; | |
} | |
void __setup_gnuplot(FILE *gp) | |
{ | |
float a = -(p.v[1] / p.v[2]); | |
float b = -(p.v[0] / p.v[2]); | |
fprintf(gp, "set terminal gif animate delay 50\n"); | |
fprintf(gp, "set output \"test.gif\"\n"); | |
fprintf(gp, "set key outside\n"); | |
fprintf(gp, "set xrange [-1:1]\n"); | |
fprintf(gp, "set yrange [-1:1]\n"); | |
fprintf(gp, "set style line 1 lc rgb 'blue' pt 7\n"); | |
fprintf(gp, "set style line 2 lc rgb 'red' pt 7\n"); | |
fprintf(gp, "a=%f\n", a); | |
fprintf(gp, "b=%f\n", b); | |
fprintf(gp, "c(x)=a*x + b\n"); | |
fprintf(gp, | |
"plot c(x) title 'Target'," | |
" '-' u 1:2 w p ls 1 title 'Positive'," | |
" '-' u 1:2 w p ls 2 title 'Negative'\n"); | |
/* Pretty inefficient, but I just don't know gnuplot all that well */ | |
for (int i = 0; i < p.num_samples; i++) | |
if (p.data[i].label == 1) | |
fprintf(gp, "%f %f\n", p.data[i].x[1], p.data[i].x[2]); | |
fprintf(gp, "e\n"); | |
for (int i = 0; i < p.num_samples; i++) | |
if (p.data[i].label == -1) | |
fprintf(gp, "%f %f\n", p.data[i].x[1], p.data[i].x[2]); | |
fprintf(gp, "e\n"); | |
} | |
void run_percep(int save_plot) | |
{ | |
float weights[] = {0, 0, 0}; | |
struct sample_data *xs; | |
FILE *gp; | |
int iteration = 0; | |
/* Maybe refactor later with mmap*/ | |
FILE *temp = fopen("temp.dat", "w+"); | |
while ((xs = class_error(weights))) { | |
iteration++; | |
weights[0] = weights[0] + (xs->label * xs->x[0]); | |
weights[1] = weights[1] + (xs->label * xs->x[1]); | |
weights[2] = weights[2] + (xs->label * xs->x[2]); | |
fprintf(temp, "%f %f\n", weights[1], weights[2]); | |
} | |
fflush(temp); | |
rewind(temp); | |
gp = popen("gnuplot -persist", "w"); | |
__setup_gnuplot(gp); | |
fprintf(gp, "h(x) = a*x + b\n"); | |
fprintf(gp, "stats 'temp.dat' nooutput\n"); | |
fprintf(gp, "N = int(STATS_records) - 1\n"); | |
fprintf(gp, "do for [i=0:N]{\n"); | |
fprintf(gp, "stats 'temp.dat' every ::i::i nooutput\n"); | |
fprintf(gp, "a = STATS_min_x\n"); | |
fprintf(gp, "b = STATS_min_y\n"); | |
fprintf(gp, "plot h(x) with lines title sprintf(\"Iteration: %%d\", i)\n"); | |
fprintf(gp, "}\n"); | |
fclose(temp); | |
// unlink("temp.dat"); | |
pclose(gp); | |
} | |
static void init_percep(int N) | |
{ | |
int min = -1, max = 1; | |
float vs[4]; | |
double dotp; | |
p.num_samples = N; | |
/* Setting up the target vector */ | |
for (int i = 0; i < 4; i++) | |
vs[i] = ((float)arc4random() / ARC4RANDOM_MAX * (max - min)) + min; | |
p.v[0] = vs[2] * vs[1] - vs[0] * vs[3]; | |
p.v[1] = vs[3] - vs[2]; | |
p.v[2] = vs[0] - vs[1]; | |
/* Setting up the sample data */ | |
p.data = malloc(sizeof(struct sample_data) * N); | |
for (int i = 0; i < N; i++) { | |
p.data[i].x[0] = 1; | |
p.data[i].x[1] = ((float)arc4random() / ARC4RANDOM_MAX * (max - min)) + min; | |
p.data[i].x[2] = ((float)arc4random() / ARC4RANDOM_MAX * (max - min)) + min; | |
dotp = dot_product(p.v, p.data[i].x, 3); | |
if (dotp > 0) | |
p.data[i].label = 1; | |
else | |
p.data[i].label = -1; | |
} | |
} | |
int main (int argc, char **argv) | |
{ | |
int n = 200; | |
init_percep(n); | |
run_percep(SAVE_PLOT); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment