经过很长的休息后,我回到了C语言,对自己说:“学习一些深度学习是什么?”。 因此,我具有以下结构:
以前,网络是一个层阵列,但是由于层数可能未知,所以我现在使用一个列表。
我希望按如下方式使用网络:创建,逐层添加,输出,删除。
// A neuron is an array of inputs, an array of weights, and the size of its arrays
typedef struct Neuron {
double * inputs;
double * weights;
size_t inputsCount;
} Neuron;
// Creates a Neuron and returns it
Neuron * Neuron_create (size_t inputsCount) {
Neuron * neuron;
size_t weightsIndex;
neuron = Structure_create (sizeof (Neuron));
neuron->inputsCount = inputsCount;
neuron->inputs = (double *) Structure_create (neuron->inputsCount * sizeof (double));
neuron->weights = (double *) Structure_create (neuron->inputsCount * sizeof (double));
for (weightsIndex = 0; weightsIndex < inputsCount; weightsIndex++)
neuron->weights [weightsIndex] = rand () / (RAND_MAX / 1.0); // On creation, random weights are used
return neuron;
}
// Deletes the neuron and sets its pointer to NULL
void Neuron_delete (Neuron ** target) {
if ((NULL == target) || (NULL == * target))
return;
printf (" Deleting neuron: %p\n", * target);
Structure_delete (& (* target)->inputs);
Structure_delete (& (* target)->weights);
Structure_delete (target);
printf (" Neuron deleted\n");
}
// A layer is an array of Neurons and its size
typedef struct NeuralLayer {
size_t neuronsCount;
Neuron ** neurons;
} NeuralLayer;
// Creates a Layer and returns it
NeuralLayer * NeuralLayer_create (size_t neuronsCount, size_t inputsCount) {
NeuralLayer * layer;
size_t neuronsIndex;
layer = Structure_create (sizeof (NeuralLayer));
layer->neuronsCount = neuronsCount;
layer->neurons = Structure_create (layer->neuronsCount * sizeof (NeuralLayer *));
for (neuronsIndex = 0; neuronsIndex < neuronsCount; neuronsIndex++)
layer->neurons [neuronsIndex] = Neuron_create (inputsCount);
return layer;
}
// Deletes the layer and sets its pointer to NULL
void NeuralLayer_delete (NeuralLayer ** target) {
if ((NULL == target) || (NULL == * target))
return;
printf (" Deleting layer: %p\n", * target);
for (size_t neuronIndex = 0; neuronIndex < (* target)->neuronsCount; neuronIndex++) {
Neuron * buffer = (* target)->neurons [neuronIndex];
Neuron_delete (& buffer);
}
Structure_delete ((* target)->neurons);
Structure_delete (target);
printf (" Layer deleted\n");
}
// The network is simply a List of layers
typedef struct NeuralNetwork {
List * layers;
} NeuralNetwork;
// Allocs the empty network and returns it
NeuralNetwork * NeuralNetwork_create (void) {
NeuralNetwork * network;
network = Structure_create (sizeof (NeuralNetwork));
network->layers = List_create ();
return network;
}
// Deletes the network and sets its pointer to NULL
void NeuralNetwork_delete (NeuralNetwork ** target) {
if ((NULL == target) || (NULL == * target))
return;
printf ("Deleting network: %p\n", * target);
// For each layer, delete layer
for (size_t layerIndex = 0; layerIndex < List_size ((* target)->layers); layerIndex++) {
NeuralLayer * buffer = List_get ((* target)->layers, layerIndex); // I'm using opaque structures
NeuralLayer_delete (& buffer);
}
List_delete (& (* target)->layers);
Structure_delete (target);
printf ("Network deleted\n");
}
// We only need to know how many neurons the new layer will contain, they will have as many inputs as the number of neurons in the previous layer
void NeuralNetwork_addLayer (NeuralNetwork * dest, size_t neuronsCount) {
if (NULL == dest->layers)
List_add (& dest->layers, NeuralLayer_create (neuronsCount, 1));
else {
NeuralLayer * previousLayer = List_get (dest->layers, List_size (dest->layers) - 1);
size_t inputsCount = NeuralLayer_getNeuronsCount (previousLayer);
NeuralLayer * newLayer = NeuralLayer_create (neuronsCount, inputsCount);
List_add (& dest->layers, newLayer);
}
}
我的主要对象:
int main (int argc, char * argv []) {
NeuralNetwork * network = NeuralNetwork_create ();
NeuralNetwork_addLayer (network, 4); // First layer are inputs, one for each pixel
NeuralNetwork_addLayer (network, 3); // Hidden layer of 15 neurons
NeuralNetwork_addLayer (network, 2); // Output layer,
NeuralNetwork_delete (& network);
return EXIT_SUCCESS;
}
在释放过程中程序崩溃,NeuralNetwork_delete()调用NeuralLayer_delete()并调用Neuron_delete(),这在分配/释放方面有问题。
哦,我忘记了基本存储功能:
// Allocates memory, checks it and returns it
// Have to change the name, i don't use it only to alloc structures
void * Structure_create (size_t size) {
void * structure;
structure = malloc (size);
if (NULL == structure) {
printf ("Memory allocation failed, aborting.\n");
system ("PAUSE");
exit (EXIT_FAILURE);
}
return structure;
}
// Free the memory and sets the pointer to NULL
void Structure_delete (void ** target) {
if ((NULL == target) || (NULL == * target))
return;
free (* target);
* target = NULL;
}
我做错了什么?
编辑:添加列表创建/删除
typedef struct List {
void * content;
List * next;
List * previous;
} List;
// Create a single item and inits it
static List * _List_createItem (void * content);
// Returns NULL to hide implementation
List * List_create (void) {
return (List* )NULL;
}
void List_delete (List ** target) {
if (NULL == target) {
printf ("Tried to delete NULL list\n");
return;
}
else if (NULL == * target)
return;
List_delete (& (* target)->next);
Structure_delete (target);
}
void * List_get (const List * const list, size_t index) {
if (NULL == list) {
printf ("Tried to get from List with index out of range\n");
return NULL;
}
else if (0 == index)
return list->content;
return List_get (list, index - 1);
}
// If the list was empty, it becomes a new list, so we need pointer to pointer
void List_add (List ** dest, void * content) {
if (NULL == dest) {
printf ("Tried to add item on NULL pointer\n");
return;
}
else if ((NULL != * dest) && (NULL == (* dest)->next)) {
(* dest)->next = _List_createItem (content);
(* dest)->next->previous = * dest;
}
else if (NULL == * dest)
* dest = _List_createItem (content);
else
List_add (& (* dest)->next, content);
}
static List * _List_createItem (void * content) {
List * item;
item = (List *)Structure_create (sizeof (List));
item->content = content;
item->next = NULL;
item->previous = NULL;
return item;
}
答案 0 :(得分:1)
您的List_get
函数似乎无法正确遍历列表:
return List_get (list, index - 1);
应为:
return List_get (list->next, index - 1);
此外,在NeuralLayer_delete
函数中:
Structure_delete ((* target)->neurons);
应为:
Structure_delete (&(* target)->neurons);
作为旁注:您已经发现这种“非常手动”的内存管理非常脆弱且容易出错。考虑在将来过渡到C ++。它具有RAII pattern和smart pointers用于更强大的资源管理。它还提供了dynamic array (vector)和linked list容器,因此您不必自己发明它们(也不会犯初学者的错误:)。它们也可能会提供更好的性能。