OCR Project
Loading...
Searching...
No Matches
cnn.c File Reference

CNN implementation: initialisation, forward pass, backward pass, SGD-with-momentum update. More...

#include "cnn.h"
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
Include dependency graph for cnn.c:

Functions

static float randn (void)
 Box-Muller transform: sample one value from N(0, 1).
static void relu_inplace (float *x, size_t length)
 Apply ReLU element-wise: f(x) = max(0, x).
static void softmax_inplace (float *x, size_t length)
 Apply softmax in-place over an array of length n.
CNNcnn_create (void)
 Allocate and initialise a CNN with He-initialised weights.
void cnn_free (CNN *net)
 Free all memory associated with a CNN.
static void forward_conv (CNN *net)
 Convolution stage: compute net->act.conv_out.
static void forward_pool (CNN *net)
 Max-pooling stage: compute net->act.pool_out.
static void forward_flatten (CNN *net)
 Flatten stage: copy pool_out into act->flat, row-major.
static void forward_dense1 (CNN *net)
 Dense layer 1 (2704 → 128) followed by ReLU.
static void forward_dense2 (CNN *net)
 Dense layer 2 (128 → 26) followed by Softmax.
void cnn_forward (CNN *net, const float *image)
 Run a full forward pass and populate net->act.
float cnn_loss (const CNN *net, int label)
 Compute cross-entropy loss for the current forward-pass output.
void cnn_backward (CNN *net, int label)
 Compute gradients via backpropagation.
void cnn_zero_grads (CNN *net)
 Zero all gradient accumulators in net->grads.
static void sgd_update (float *w, float *v, const float *g, size_t n, float inv_batch)
 Apply SGD+momentum to one weight array.
void cnn_update (CNN *net)
 Apply one SGD-with-momentum update step to the weights.
int cnn_predict (CNN *net, const float *image)
 Predict the most likely class for a single image.

Detailed Description

CNN implementation: initialisation, forward pass, backward pass, SGD-with-momentum update.

Function Documentation

◆ cnn_backward()

void cnn_backward ( CNN * net,
int label )

Compute gradients via backpropagation.

Must be called after cnn_forward(). Accumulates gradients into net->grads.

Parameters
netCNN after a forward pass.
labelTrue class index in [0, CNN_N_CLASSES).
Note
This is a stub: the full implementation is deferred.
Here is the caller graph for this function:

◆ cnn_create()

CNN * cnn_create ( void )

Allocate and initialise a CNN with He-initialised weights.

All conv kernels and dense weights are drawn from a zero-mean normal distribution with variance 2/fan_in (He, 2015). Biases are zeroed.

Returns
Pointer to a heap-allocated CNN, or NULL on allocation failure.
Note
The caller must free the returned pointer with cnn_free().
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cnn_forward()

void cnn_forward ( CNN * net,
const float * image )

Run a full forward pass and populate net->act.

Stages: Conv2D → ReLU → MaxPool → Flatten → Dense → ReLU → Dense → Softmax.

Parameters
netInitialised CNN.
imageFlat array of CNN_IMG_H * CNN_IMG_W normalised float pixels, row-major order.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cnn_free()

void cnn_free ( CNN * net)

Free all memory associated with a CNN.

Parameters
netPointer returned by cnn_create(). No-op if NULL.
Here is the caller graph for this function:

◆ cnn_loss()

float cnn_loss ( const CNN * net,
int label )

Compute cross-entropy loss for the current forward-pass output.

loss = -log(output[label])

Parameters
netCNN after cnn_forward().
labelTrue class index.
Returns
Scalar cross-entropy loss (≥ 0).
Here is the caller graph for this function:

◆ cnn_predict()

int cnn_predict ( CNN * net,
const float * image )

Predict the most likely class for a single image.

Runs cnn_forward() internally.

Parameters
netInitialised CNN with trained weights.
imageFlat float array, same layout as cnn_forward().
Returns
Class index in [0, CNN_N_CLASSES), i.e. 0 = 'A', 25 = 'Z'.
Here is the call graph for this function:

◆ cnn_update()

void cnn_update ( CNN * net)

Apply one SGD-with-momentum update step to the weights.

w_new = w - lr * (β * v + g) where v is the momentum velocity and g is the gradient.

Parameters
netCNN with filled net->grads from cnn_backward().
Note
Resets net->grads to zero after the update.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cnn_zero_grads()

void cnn_zero_grads ( CNN * net)

Zero all gradient accumulators in net->grads.

Parameters
netCNN whose gradients should be cleared.
Here is the caller graph for this function:

◆ forward_conv()

void forward_conv ( CNN * net)
static

Convolution stage: compute net->act.conv_out.

For each filter f and output position (r, c): conv_out[f][r][c] = bias[f] + sum_{dr,dc} kernel[f][dr][dc] * input[r+dr][c+dc]

Parameters
netCNN with loaded weights and net->act.input filled.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ forward_dense1()

void forward_dense1 ( CNN * net)
static

Dense layer 1 (2704 → 128) followed by ReLU.

z1[h] = b1[h] + sum_f W1[h][f] * flat[f] h1[h] = ReLU(z1[h])

Parameters
netCNN after forward_flatten().
Here is the caller graph for this function:

◆ forward_dense2()

void forward_dense2 ( CNN * net)
static

Dense layer 2 (128 → 26) followed by Softmax.

z2[k] = b2[k] + sum_h W2[k][h] * h1[h] output = softmax(z2)

Parameters
netCNN after forward_dense1().
Here is the call graph for this function:
Here is the caller graph for this function:

◆ forward_flatten()

void forward_flatten ( CNN * net)
static

Flatten stage: copy pool_out into act->flat, row-major.

Index formula: flat[f * POOL_OUT_H * POOL_OUT_W + r * POOL_OUT_W + c]

Parameters
netCNN after forward_pool().
Here is the caller graph for this function:

◆ forward_pool()

void forward_pool ( CNN * net)
static

Max-pooling stage: compute net->act.pool_out.

2×2 window, stride 2. Stores the winning row/col within each window in pool_max_r / pool_max_c for use during backprop.

Parameters
netCNN after forward_conv().
Here is the caller graph for this function:

◆ randn()

float randn ( void )
static

Box-Muller transform: sample one value from N(0, 1).

Uses the standard two-uniform-samples formula. Not thread-safe due to static state; call from a single thread during initialisation.

Returns
One sample from the standard normal distribution.
Here is the caller graph for this function:

◆ relu_inplace()

void relu_inplace ( float * x,
size_t length )
static

Apply ReLU element-wise: f(x) = max(0, x).

Parameters
xInput/output array (modified in-place).
lengthNumber of elements.
Here is the caller graph for this function:

◆ sgd_update()

void sgd_update ( float * w,
float * v,
const float * g,
size_t n,
float inv_batch )
static

Apply SGD+momentum to one weight array.

For each weight w, velocity v, gradient g: v = β * v + g w -= lr * v

Parameters
wWeight array (modified in-place).
vVelocity array (modified in-place).
gGradient array (read-only).
nNumber of elements.
Here is the caller graph for this function:

◆ softmax_inplace()

void softmax_inplace ( float * x,
size_t length )
static

Apply softmax in-place over an array of length n.

Subtracts the maximum value before exponentiation for numerical stability.

Parameters
xInput/output array (modified in-place).
lengthNumber of elements.
Here is the caller graph for this function: