PageRenderTime 51ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/experiments/fase2/train.c

https://github.com/briglia/dissertacao
C | 565 lines | 356 code | 69 blank | 140 comment | 48 complexity | 58eb7eb60cb54b64b08b6138f61933ad MD5 | raw file
  1. #define _GNU_SOURCE
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <errno.h>
  5. #include <time.h>
  6. #include <math.h>
  7. #include <string.h>
  8. #include "util.h"
  9. #include "som.h"
  10. #include "ui.h"
  11. extern void status_bar_push_item(char *info);
  12. extern void update_percentual_trained(void);
  13. /*
  14. * Read the input from file for Self Organizing Maps (SOM)
  15. * and return the length of inputs
  16. */
  17. int read_som_input(struct input_pattern * inputs[], int maxlen) {
  18. char filename[] = "input.txt";
  19. FILE * fp;
  20. ssize_t bytes_read;
  21. size_t len = 0;
  22. char * line = NULL;
  23. unsigned int pages;
  24. int veloc, acel;
  25. int i = 0;
  26. fp = fopen(filename, "r");
  27. if (fp == NULL) {
  28. /*
  29. fprintf(stderr,
  30. "error opening file %s: %s\n",
  31. filename, strerror(errno));
  32. exit(EXIT_FAILURE);
  33. */
  34. return -1 ; // Error
  35. }
  36. maxlen--;
  37. while((bytes_read = getline(&line, &len, fp)) != -1) {
  38. if (maxlen < i) {
  39. fprintf(stdout,
  40. "input array is not large enough "
  41. "to fit the input file: %u < %u\n",
  42. maxlen, i);
  43. break;
  44. }
  45. sscanf(line, "(%u, %d, %d)", &pages, &veloc, &acel);
  46. inputs[i] = (struct input_pattern *)
  47. malloc(sizeof(struct input_pattern));
  48. inputs[i]->weights[0] = normalize((double)pages,
  49. MEM_MAX,
  50. MEM_MIN);
  51. inputs[i]->weights[1] = normalize((double)veloc,
  52. VELOC_MAX,
  53. VELOC_MIN);
  54. inputs[i]->weights[2] = normalize((double)acel,
  55. ACEL_MAX,
  56. ACEL_MIN);
  57. i++;
  58. };
  59. if (line)
  60. free(line);
  61. if (fclose(fp)) {
  62. fprintf(stderr,
  63. "error closing file %s: %s\n",
  64. filename, strerror(errno));
  65. exit(EXIT_FAILURE);
  66. }
  67. return i;
  68. }
  69. /*
  70. * Read the trained Self Organizing Maps (SOM) from filename
  71. */
  72. int read_trained_som(char filename[], struct som_node * grids[][GRIDS_YSIZE]) {
  73. FILE * fp;
  74. ssize_t bytes_read;
  75. size_t len = 0;
  76. char * line = NULL;
  77. char * input[WEIGHTS_SIZE];
  78. int i, j;
  79. fp = fopen(filename, "r");
  80. if (fp == NULL) {
  81. /*
  82. fprintf(stderr,
  83. "error opening file %s: %s\n",
  84. filename, strerror(errno));
  85. exit(EXIT_FAILURE);
  86. */
  87. return 0;
  88. }
  89. for (i=0; i<WEIGHTS_SIZE; i++)
  90. input[i] = (char *)malloc(10);
  91. while((bytes_read = getline(&line, &len, fp)) != -1) {
  92. sscanf(line, "(%d, %d) %s %s %s",
  93. &i, &j, input[0], input[1], input[2]);
  94. grids[i][j] = (struct som_node *)
  95. malloc(sizeof(struct som_node));
  96. grids[i][j]->xp = i;
  97. grids[i][j]->yp = j;
  98. grids[i][j]->weights[0] = strtod(input[0], NULL);
  99. grids[i][j]->weights[1] = strtod(input[1], NULL);
  100. grids[i][j]->weights[2] = strtod(input[2], NULL);
  101. }
  102. for (i=0; i<WEIGHTS_SIZE; i++)
  103. free(input[i]);
  104. if (line)
  105. free(line);
  106. if (fclose(fp)) {
  107. fprintf(stderr,
  108. "error closing file %s: %s\n",
  109. filename, strerror(errno));
  110. exit(EXIT_FAILURE);
  111. }
  112. return 1;
  113. }
  114. /*
  115. * Save the trained Self Organizing Maps (SOM) to filename
  116. */
  117. void save_trained_som(char filename[], struct som_node * grids[][GRIDS_YSIZE]) {
  118. FILE * fp;
  119. int i, j;
  120. char * line;
  121. fp = fopen(filename, "w");
  122. if (fp == NULL) {
  123. fprintf(stderr,
  124. "error opening file %s: %s\n",
  125. filename, strerror(errno));
  126. exit(EXIT_FAILURE);
  127. }
  128. for (i=0; i<GRIDS_XSIZE; i++) {
  129. for (j=0; j<GRIDS_YSIZE; j++) {
  130. line = (char *)malloc(50);
  131. sprintf(line, "(%d, %d) %f %f %f\n",
  132. i, j,
  133. grids[i][j]->weights[0],
  134. grids[i][j]->weights[1],
  135. grids[i][j]->weights[2]);
  136. fputs(line, fp);
  137. free(line);
  138. }
  139. }
  140. if (fclose(fp)) {
  141. fprintf(stderr,
  142. "error closing file %s: %s\n",
  143. filename, strerror(errno));
  144. exit(EXIT_FAILURE);
  145. }
  146. }
  147. /*
  148. * Allocate and initiate all nodes in the grid with their
  149. * weights set randomly
  150. */
  151. void init_grid(struct som_node * grids[][GRIDS_YSIZE]) {
  152. int i, j, k;
  153. srand(time(0));
  154. for (i=0; i<GRIDS_XSIZE; i++) {
  155. for (j=0; j<GRIDS_YSIZE; j++) {
  156. grids[i][j] = (struct som_node *)
  157. malloc(sizeof(struct som_node));
  158. grids[i][j]->xp = i;
  159. grids[i][j]->yp = j;
  160. for (k=0; k<WEIGHTS_SIZE; k++) {
  161. grids[i][j]->weights[k] = rand_float();
  162. }
  163. }
  164. }
  165. }
  166. /*
  167. * Print all nodes with their weights from the grid for
  168. * debugging purpose
  169. */
  170. void print_grid(struct som_node * grids[][GRIDS_YSIZE]) {
  171. int i, j;
  172. for (i=0; i<GRIDS_YSIZE; i++) {
  173. printf("\n\n");
  174. for (j=0; j<GRIDS_XSIZE; j++) {
  175. printf("(%d %d %d)",
  176. (int)(grids[i][j]->weights[0] * 255),
  177. (int)(grids[i][j]->weights[1] * 255),
  178. (int)(grids[i][j]->weights[2] * 255)
  179. );
  180. }
  181. }
  182. }
  183. /*
  184. * Train Kohonen's Self Organizing Map (SOM).
  185. * This training code is animated
  186. */
  187. void train(struct input_pattern * inputs[], int input_len) {
  188. int lw = GRIDS_XSIZE;
  189. int lh = GRIDS_YSIZE;
  190. int xstart, ystart, xend, yend;
  191. double dist, influence;
  192. double grid_radius = max(lw, lh)/2;
  193. double time_constant = NUM_ITERATIONS / log(grid_radius);
  194. int iteration = 0;
  195. double nbh_radius;
  196. struct som_node * bmu = NULL;
  197. struct som_node * temp = NULL;
  198. double * new_input = NULL;
  199. double learning_rate = START_LEARNING_RATE;
  200. int i, x, y ,j , k ;
  201. time_t start_time = 0;
  202. time_t end_time = 0;
  203. /* Train NUM_ITERATIONS times */
  204. while (iteration < NUM_ITERATIONS) {
  205. time(&start_time);
  206. /* Get the neighborhood radius */
  207. nbh_radius = neighborhood_radius(grid_radius,
  208. iteration,
  209. time_constant);
  210. /* For each input pattern, determine the BMU and adjust */
  211. /* the weights for the BMU's neighborhood */
  212. for (i=0; i<input_len; i++) {
  213. new_input = inputs[i]->weights;
  214. /* Get the BMU */
  215. bmu = get_bmu(new_input, WEIGHTS_SIZE, grids);
  216. xstart = (int)(bmu->xp - nbh_radius - 1);
  217. ystart = (int)(bmu->yp - nbh_radius - 1);
  218. xend = (int)(bmu->xp + nbh_radius + 1);
  219. yend = (int)(bmu->yp + nbh_radius + 1);
  220. if (xend > lw)
  221. xend = lw;
  222. if (xstart < 0)
  223. xstart = 0;
  224. if (yend > lh)
  225. yend = lh;
  226. if (ystart < 0)
  227. ystart = 0;
  228. /* Optimization: Only go through the (x,y) values */
  229. /* that fall within the radius */
  230. for (x=xstart; x<xend; x++) {
  231. for (y=ystart; y<yend; y++) {
  232. temp = grids[x][y];
  233. dist = distance_to(bmu, temp);
  234. if (dist <= (nbh_radius * nbh_radius)) {
  235. influence = get_influence
  236. (dist, nbh_radius);
  237. adjust_weights
  238. (temp,
  239. inputs[i],
  240. WEIGHTS_SIZE,
  241. learning_rate,
  242. influence);
  243. }
  244. }
  245. }
  246. }
  247. iteration++;
  248. /* Calculate the learning rate */
  249. learning_rate = START_LEARNING_RATE *
  250. exp(-(double)iteration/NUM_ITERATIONS);
  251. time(&end_time);
  252. /*printf("Iteration..: %d -> %f s\n",
  253. iteration,
  254. (difftime(end_time, start_time)));*/
  255. // UI changes - Keppler Alecrim
  256. //Updating grid
  257. for (k=0; k<GRIDS_XSIZE; k++) {
  258. for (j=0; j<GRIDS_YSIZE; j++) {
  259. color.red = (int)(grids[k][j]->weights[0] * 65535);
  260. color.blue = (int)(grids[k][j]->weights[1] * 65535);
  261. color.green = (int)(grids[k][j]->weights[2] * 65535);
  262. gtk_widget_modify_bg(drawingarea[k][j], GTK_STATE_NORMAL, &color);
  263. }
  264. }
  265. //Update status bar
  266. status_bar_push_item(g_strdup_printf("Iteration..: %d -> %f s ",iteration,(difftime(end_time, start_time))));
  267. //Update progress bar
  268. gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(pbar),((double)iteration/NUM_ITERATIONS));
  269. gtk_progress_bar_set_text (GTK_PROGRESS_BAR(pbar),g_strdup_printf("%f %%",100*((double)iteration/NUM_ITERATIONS)));
  270. /* Run all pending events and high priority idle functions */
  271. while(g_main_context_iteration(NULL, FALSE));
  272. update_percentual_trained();
  273. }
  274. status_bar_push_item(g_strdup_printf(" finished !!! "));
  275. }
  276. /*
  277. * Train Kohonen's Self Organizing Map (SOM).
  278. * This training code is faster
  279. */
  280. void train3(struct input_pattern * inputs[], int input_len) {
  281. int lw = GRIDS_XSIZE;
  282. int lh = GRIDS_YSIZE;
  283. int xstart, ystart, xend, yend;
  284. double dist, influence;
  285. double grid_radius = max(lw, lh)/2;
  286. double time_constant = NUM_ITERATIONS / log(grid_radius);
  287. int iteration = 0;
  288. double nbh_radius;
  289. struct som_node * bmu = NULL;
  290. struct som_node * temp = NULL;
  291. double * new_input = NULL;
  292. double learning_rate = START_LEARNING_RATE;
  293. int i, x, y;
  294. time_t start_time = 0;
  295. time_t end_time = 0;
  296. /* Train NUM_ITERATIONS times */
  297. while (iteration < NUM_ITERATIONS) {
  298. time(&start_time);
  299. /* Get the neighborhood radius */
  300. nbh_radius = neighborhood_radius(grid_radius,
  301. iteration,
  302. time_constant);
  303. /* For each input pattern, determine the BMU and adjust */
  304. /* the weights for the BMU's neighborhood */
  305. for (i=0; i<input_len; i++) {
  306. new_input = inputs[i]->weights;
  307. /* Get the BMU */
  308. bmu = get_bmu(new_input, WEIGHTS_SIZE, grids);
  309. xstart = (int)(bmu->xp - nbh_radius - 1);
  310. ystart = (int)(bmu->yp - nbh_radius - 1);
  311. xend = (int)(bmu->xp + nbh_radius + 1);
  312. yend = (int)(bmu->yp + nbh_radius + 1);
  313. if (xend > lw)
  314. xend = lw;
  315. if (xstart < 0)
  316. xstart = 0;
  317. if (yend > lh)
  318. yend = lh;
  319. if (ystart < 0)
  320. ystart = 0;
  321. /* Optimization: Only go through the (x,y) values */
  322. /* that fall within the radius */
  323. for (x=xstart; x<xend; x++) {
  324. for (y=ystart; y<yend; y++) {
  325. temp = grids[x][y];
  326. dist = distance_to(bmu, temp);
  327. if (dist <= (nbh_radius * nbh_radius)) {
  328. influence = get_influence
  329. (dist, nbh_radius);
  330. adjust_weights
  331. (temp,
  332. inputs[i],
  333. WEIGHTS_SIZE,
  334. learning_rate,
  335. influence);
  336. }
  337. }
  338. }
  339. }
  340. iteration++;
  341. /* Calculate the learning rate */
  342. learning_rate = START_LEARNING_RATE *
  343. exp(-(double)iteration/NUM_ITERATIONS);
  344. time(&end_time);
  345. printf("Iteration..: %d -> %f s\n",
  346. iteration,
  347. (difftime(end_time, start_time)));
  348. }
  349. }
  350. /*
  351. * Train Kohonen's Self Organizing Map (SOM).
  352. * This training code is slower than the first one
  353. */
  354. void train2(struct input_pattern * inputs[], int input_len) {
  355. int lw = GRIDS_XSIZE;
  356. int lh = GRIDS_YSIZE;
  357. double dist, influence;
  358. double grid_radius = max(lw, lh)/2;
  359. double time_constant = NUM_ITERATIONS / log(grid_radius);
  360. int iteration = 0;
  361. double nbh_radius;
  362. struct som_node * bmu = NULL;
  363. struct som_node * temp = NULL;
  364. double * new_input = NULL;
  365. double learning_rate = START_LEARNING_RATE;
  366. int i, x, y;
  367. /* Train NUM_ITERATIONS times */
  368. while (iteration < NUM_ITERATIONS) {
  369. /* Get the neighborhood radius */
  370. nbh_radius = neighborhood_radius(grid_radius,
  371. iteration,
  372. time_constant);
  373. /* For each input pattern, determine the BMU and adjust */
  374. /* the weights for the BMU's neighborhood */
  375. for (i=0; i<input_len; i++) {
  376. new_input = inputs[i]->weights;
  377. /* Get the BMU */
  378. bmu = get_bmu(new_input, WEIGHTS_SIZE, grids);
  379. for (x=0; x<GRIDS_XSIZE; x++) {
  380. for (y=0; y<GRIDS_XSIZE; y++) {
  381. temp = grids[x][y];
  382. dist = distance_to(bmu, temp);
  383. if (dist <= (nbh_radius * nbh_radius)) {
  384. influence = get_influence
  385. (dist, nbh_radius);
  386. adjust_weights
  387. (temp,
  388. inputs[i],
  389. WEIGHTS_SIZE,
  390. learning_rate,
  391. influence);
  392. }
  393. }
  394. }
  395. }
  396. iteration++;
  397. /* Calculate the learning rate */
  398. learning_rate = START_LEARNING_RATE *
  399. exp(-(double)iteration/NUM_ITERATIONS);
  400. }
  401. }
  402. struct som_node * get_bmu_xy (struct som_node * grids[][GRIDS_YSIZE],
  403. unsigned int * new_rss,
  404. unsigned int * current_rss,
  405. int * veloc,
  406. int * accel) {
  407. int temp_veloc;
  408. struct input_pattern * neural_input = NULL;
  409. struct som_node * bmu = NULL;
  410. /* Update the current rss pages, velocity and acceleration */
  411. temp_veloc = *new_rss - *current_rss;
  412. *accel = temp_veloc - *veloc;
  413. *veloc = temp_veloc;
  414. *current_rss = *new_rss;
  415. neural_input = (struct input_pattern *)
  416. malloc(sizeof(struct input_pattern));
  417. neural_input->weights[0] = normalize((double)*current_rss,
  418. MEM_MAX,
  419. MEM_MIN);
  420. neural_input->weights[1] = normalize((double)*veloc,
  421. VELOC_MAX,
  422. VELOC_MIN);
  423. neural_input->weights[2] = normalize((double)*accel,
  424. ACEL_MAX,
  425. ACEL_MIN);
  426. /* Get the BMU */
  427. bmu = get_bmu(neural_input->weights, WEIGHTS_SIZE, grids);
  428. free(neural_input);
  429. return bmu;
  430. }
  431. /*
  432. int main (int argc, char * argv[]) {
  433. init_grid(grids);
  434. print_grid(grids);
  435. struct input_pattern * inputs[5];
  436. inputs[0] = (struct input_pattern *)
  437. malloc(sizeof(struct input_pattern));
  438. inputs[0]->weights[0] = 0.1;
  439. inputs[0]->weights[1] = 0.25;
  440. inputs[0]->weights[2] = 0.015;
  441. inputs[1] = (struct input_pattern *)
  442. malloc(sizeof(struct input_pattern));
  443. inputs[1]->weights[0] = 0.5;
  444. inputs[1]->weights[1] = 0.35;
  445. inputs[1]->weights[2] = 0.2;
  446. inputs[2] = (struct input_pattern *)
  447. malloc(sizeof(struct input_pattern));
  448. inputs[2]->weights[0] = 0.58;
  449. inputs[2]->weights[1] = 0.75;
  450. inputs[2]->weights[2] = 0.4;
  451. inputs[3] = (struct input_pattern *)
  452. malloc(sizeof(struct input_pattern));
  453. inputs[3]->weights[0] = 0.066;
  454. inputs[3]->weights[1] = 0.99;
  455. inputs[3]->weights[2] = 0.01;
  456. inputs[4] = (struct input_pattern *)
  457. malloc(sizeof(struct input_pattern));
  458. inputs[4]->weights[0] = 0.326;
  459. inputs[4]->weights[1] = 0.888;
  460. inputs[4]->weights[2] = 0.271;
  461. clock_t start, end;
  462. double elapsed;
  463. start = clock();
  464. train(inputs, 5);
  465. end = clock();
  466. elapsed = ((double) (end - start)) / CLOCKS_PER_SEC;
  467. printf("Time Elapsed: %f\n\n", elapsed);
  468. start = clock();
  469. //train2(inputs, 5);
  470. end = clock();
  471. elapsed = ((double) (end - start)) / CLOCKS_PER_SEC;
  472. printf("Time Elapsed: %f\n\n", elapsed);
  473. printf("\n\n***********\n\n");
  474. print_grid(grids);
  475. return 0;
  476. }
  477. */