/** * @brief Set the inputs of the network from a patch within an image. * It is assumed that the image is mono (1 byte per pixel) * @param net Backprop neural net object * @param img Array storing the image * @param image_width Width of the image in pixels * @param image_height Height of the image in pixels * @param tx Top left x coordinate of the patch within the image * @param ty Top left y coordinate of the patch within the image */ void bp_inputs_from_image_patch(bp * net, unsigned char * img, int image_width, int image_height, int tx, int ty) { int px,py,i=0,idx; /* The patch size is calculated from the number of inputs of the neural net. It's assumed to be square. */ int patch_size = (int)sqrt(net->NoOfInputs); /* make sure that the patch fits within the number of inputs */ assert(patch_size*patch_size <= net->NoOfInputs); /* set the inputs from the patch */ for (py = ty; py < ty+patch_size; py++) { if (py >= image_height) break; for (px = tx; px < tx+patch_size; px++, i++) { if (px >= image_width) break; /* array index within the image */ idx = (py*image_width) + px; /* set the input value within the range 0.25 to 0.75 */ bp_set_input(net, i, 0.25f + (img[idx]*0.5f/255.0f)); } } }
static void test_backprop_update() { bp net; int no_of_inputs=10; int no_of_hiddens=4; int hidden_layers=2; int no_of_outputs=5; int i; unsigned int random_seed = 123; printf("test_backprop_update..."); bp_init(&net, no_of_inputs, no_of_hiddens, hidden_layers, no_of_outputs, &random_seed); assert((&net)->inputs!=0); assert((&net)->hiddens!=0); assert((&net)->outputs!=0); /* set some inputs */ for (i = 0; i < no_of_inputs; i++) { bp_set_input(&net, i, i/(float)no_of_inputs); } for (i = 0; i < 100; i++) { bp_update(&net,0); } bp_free(&net); printf("Ok\n"); }
static void test_backprop() { bp net; int no_of_inputs=10; int no_of_hiddens=4; int hidden_layers=2; int no_of_outputs=5; int i,l; unsigned int random_seed = 123; printf("test_backprop..."); bp_init(&net, no_of_inputs, no_of_hiddens, hidden_layers, no_of_outputs, &random_seed); assert((&net)->inputs!=0); assert((&net)->hiddens!=0); assert((&net)->outputs!=0); /* set some inputs */ for (i = 0; i < no_of_inputs; i++) { bp_set_input(&net, i, i/(float)no_of_inputs); (&net)->inputs[i]->BPerror = 999; } for (l = 0; l < hidden_layers; l++) { for (i = 0; i < bp_hiddens_in_layer(&net,l); i++) { (&net)->hiddens[l][i]->BPerror = 999; } } /* set some target outputs */ for (i = 0; i < no_of_outputs; i++) { (&net)->outputs[i]->BPerror = 999; bp_set_output(&net, i, i/(float)no_of_inputs); } /* feed forward */ bp_feed_forward(&net); bp_backprop(&net,0); /* check for non-zero backprop error values */ for (i = 0; i < no_of_inputs; i++) { assert((&net)->inputs[i]->BPerror != 999); } for (l = 0; l < hidden_layers; l++) { for (i = 0; i < bp_hiddens_in_layer(&net,l); i++) { assert((&net)->hiddens[l][i]->BPerror != 999); } } for (i = 0; i < no_of_outputs; i++) { assert((&net)->outputs[i]->BPerror != 999); } bp_free(&net); printf("Ok\n"); }
/** * @brief Convolve an array of floats to the input layer of a neural net * @param samples_across The number of units across in the layer of neurons * (sampling grid resolution) * @param samples_down The number of units down in the layer of neurons * (sampling grid resolution) * @param patch_radius The radius of the patch within the float array * @param floats_width Width of the image * @param floats_height Height of the image * @param floats_depth Depth of the image (mono=1, RGB=3) * @param layer0 Array of floats * @param net Neural net to set the inputs for * @param feature_autocoder An autocoder containing learned features * @param use_dropouts Non-zero if dropouts are to be used * @returns zero on success */ int features_conv_floats_to_neurons(int samples_across, int samples_down, int patch_radius, int floats_width, int floats_height, int floats_depth, float layer0[], bp * net, ac * feature_autocoder, unsigned char use_dropouts) { int no_of_learned_features = feature_autocoder->NoOfHiddens; if (samples_across * samples_down * no_of_learned_features != net->NoOfInputs) { /* across*down doesn't equal the second layer units */ return -1; } if (feature_autocoder->NoOfInputs != patch_radius*patch_radius*4*floats_depth) { /* the patch size doesn't match the feature learner inputs */ return -2; } for (int fy = 0; fy < samples_down; fy++) { for (int fx = 0; fx < samples_across; fx++) { int tx=0, ty=0, bx=0, by=0; if (features_patch_coords(fx, fy, samples_across, samples_down, patch_radius, floats_width, floats_height, &tx, &ty, &bx, &by) != 0) { continue; } if (scan_floats_patch(layer0, floats_width, floats_depth, tx, ty, bx, by, feature_autocoder) != 0) { return -4; } int index_net_inputs = (fy * samples_across + fx) * no_of_learned_features; autocoder_encode(feature_autocoder, feature_autocoder->hiddens, use_dropouts); for (int f = 0; f < no_of_learned_features; f++) { bp_set_input(net, index_net_inputs+f, autocoder_get_hidden(feature_autocoder, f)); } } } return 0; }
static void test_backprop_autocoder() { bp autocoder; int itt,i,j; int no_of_inputs=10; int no_of_hiddens=4; int no_of_outputs=10; unsigned int random_seed = 123; float tot; printf("test_backprop_autocoder..."); /* create the autocoder */ bp_init(&autocoder, no_of_inputs, no_of_hiddens,1, no_of_outputs, &random_seed); autocoder.learningRate = 0.5f; /* run the autocoder for some itterations */ for (itt = 0; itt < 100; itt++) { /* set the inputs */ for (i = 0; i < no_of_inputs; i++) { bp_set_input(&autocoder,i,0.25f + (i*0.5f/(float)no_of_inputs)); bp_set_output(&autocoder,i,0.75f - (i*0.5f/(float)no_of_inputs)); } /* update */ bp_update(&autocoder,0); } for (i = 0; i < no_of_hiddens; i++) { /* check that some errors have been back-propogated */ assert((&autocoder)->hiddens[0][i]->BPerror != 0); /* check that weights have changed */ tot = 0; for (j = 0; j < no_of_inputs; j++) { assert((&autocoder)->hiddens[0][i]->lastWeightChange[j]!=0); tot += fabs((&autocoder)->hiddens[0][i]->lastWeightChange[j]); } /* total weight change */ assert(tot > 0.00001f); } bp_free(&autocoder); printf("Ok\n"); }
/** * @brief Pre-trains a hidden layer using an autocoder * @param net Backprop neural net object * @param autocoder Autocoder neural net object * @param hidden_layer The layer within the neural net to be autocoded */ void bp_pretrain(bp * net, bp * autocoder, int hidden_layer) { int i; float hidden_value; /* feed forward to the given hidden layer */ bp_feed_forward_layers(net, hidden_layer); if (hidden_layer > 0) { /* check that the number of inputs is valid */ assert(net->NoOfHiddens == autocoder->NoOfInputs); /* copy the hidden unit values to the inputs of the autocoder */ for (i = 0; i < net->NoOfHiddens; i++) { hidden_value = bp_get_hidden(net, hidden_layer-1, i); bp_set_input(autocoder,i, hidden_value); } } else { /* check that the number of inputs is valid */ assert(autocoder->NoOfInputs == net->NoOfInputs); /* copy the input unit values to the inputs of the autocoder */ for (i = 0; i < net->NoOfInputs; i++) { bp_set_input(autocoder, i, bp_get_input(net, i)); } } /* run the autocoder */ bp_update_autocoder(autocoder); }
/** * @brief Set the inputs of the network from an image. * It is assumed that the image is mono (1 byte per pixel) * @param net Backprop neural net object * @param img Array storing the image * @param image_width Width of the image in pixels * @param image_height Height of the image in pixels */ void bp_inputs_from_image(bp * net, unsigned char * img, int image_width, int image_height) { int i=0; /* check that the number of inputs is the same as the number of pixels */ assert(net->NoOfInputs == image_width*image_height); /* set the inputs */ for (i = 0; i < image_width*image_height; i++) { /* set the input value within the range 0.25 to 0.75 */ bp_set_input(net, i, 0.25f + (img[i]*0.5f/255.0f)); } }
static void test_backprop_deep() { bp net; bp autocoder; int l,itt,i; int no_of_inputs=10; int no_of_hiddens=4; int hidden_layers=3; int no_of_outputs=2; unsigned int random_seed = 123; printf("test_backprop_deep..."); bp_init(&net, no_of_inputs, no_of_hiddens, hidden_layers, no_of_outputs, &random_seed); assert((&net)->inputs!=0); assert((&net)->hiddens!=0); assert((&net)->outputs!=0); for (l = 0; l < hidden_layers; l++) { /* create an autocoder for this layer */ bp_create_autocoder(&net,l,&autocoder); /* do some training */ for (itt = 0; itt < 100; itt++) { /* set the inputs */ for (i = 0; i < no_of_inputs; i++) { bp_set_input(&net,i,i/(float)no_of_inputs); } /* update */ bp_pretrain(&net,&autocoder,l); } /* move the autocoder hidden weights into the main network */ bp_update_from_autocoder(&net,&autocoder,l); /* delete the autocoder */ bp_free(&autocoder); } bp_free(&net); printf("Ok\n"); }
static void test_backprop_feed_forward() { bp net; int no_of_inputs=10; int no_of_hiddens=4; int hidden_layers=2; int no_of_outputs=5; int i; unsigned int random_seed = 123; printf("test_backprop_feed_forward..."); bp_init(&net, no_of_inputs, no_of_hiddens, hidden_layers, no_of_outputs, &random_seed); assert((&net)->inputs!=0); assert((&net)->hiddens!=0); assert((&net)->outputs!=0); /* set some inputs */ for (i = 0; i < no_of_inputs; i++) { bp_set_input(&net, i, i/(float)no_of_inputs); } /* clear the outputs */ for (i = 0; i < no_of_outputs; i++) { (&net)->outputs[i]->value = 999; } /* feed forward */ bp_feed_forward(&net); /* check for non-zero outputs */ for (i = 0; i < no_of_outputs; i++) { assert((&net)->outputs[i]->value != 999); } bp_free(&net); printf("Ok\n"); }
static void test_backprop_training() { bp * net; int no_of_inputs=2; int no_of_hiddens=2; int hidden_layers=1; int no_of_outputs=1; int itt,example; unsigned int random_seed = 123; float state_TRUE = 0.8f; float state_FALSE = 0.2f; printf("test_backprop_training..."); net = (bp*)malloc(sizeof(bp)); bp_init(net, no_of_inputs, no_of_hiddens, hidden_layers, no_of_outputs, &random_seed); assert(net->inputs!=0); assert(net->hiddens!=0); assert(net->outputs!=0); /* training */ example=0; for (itt = 0; itt < 500000; itt++, example++) { if (example>=4) example=0; /* select an example from the XOR truth table */ switch(example) { case 0: { bp_set_input(net, 0, state_FALSE); bp_set_input(net, 1, state_FALSE); bp_set_output(net, 0, state_FALSE); break; } case 1: { bp_set_input(net, 0, state_TRUE); bp_set_input(net, 1, state_FALSE); bp_set_output(net, 0, state_TRUE); break; } case 2: { bp_set_input(net, 0, state_FALSE); bp_set_input(net, 1, state_TRUE); bp_set_output(net, 0, state_TRUE); break; } case 3: { bp_set_input(net, 0, state_TRUE); bp_set_input(net, 1, state_TRUE); bp_set_output(net, 0, state_FALSE); break; } } /* train on the example */ bp_update(net,0); } bp_set_input(net, 0, state_FALSE); bp_set_input(net, 1, state_FALSE); bp_feed_forward(net); if (bp_get_output(net, 0) >= 0.5f) { printf("\n%.5f\n",bp_get_output(net, 0)); } assert(bp_get_output(net, 0) < 0.5f); bp_set_input(net, 0, state_FALSE); bp_set_input(net, 1, state_TRUE); bp_feed_forward(net); if (bp_get_output(net, 0) <= 0.5f) { printf("\n%.5f\n",bp_get_output(net, 0)); } assert(bp_get_output(net, 0) > 0.5f); bp_set_input(net, 0, state_TRUE); bp_set_input(net, 1, state_FALSE); bp_feed_forward(net); if (bp_get_output(net, 0) <= 0.5f) { printf("\n%.5f\n",bp_get_output(net, 0)); } assert(bp_get_output(net, 0) > 0.5f); bp_set_input(net, 0, state_FALSE); bp_set_input(net, 1, state_FALSE); bp_feed_forward(net); if (bp_get_output(net, 0) >= 0.5f) { printf("\n%.5f\n",bp_get_output(net, 0)); } assert(bp_get_output(net, 0) < 0.5f); bp_free(net); free(net); printf("Ok\n"); }