使用C语言实现神经网络进行数字识别

本文介绍了一个使用C语言实现的基础机器学习模型,涉及前向传播和反向传播算法,通过训练数据进行权重更新,最后通过测试数据评估模型性能。

要求:

1、对C语言基本语法已经完全掌握

2、对机器学习的底层原理认识清晰

训练数据

// 训练数据
    double inputs[5][ROWS * COLS] = {
        {0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0},
        {1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1},
        {1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0},
        {0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0},
        {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0},
    };
    int labels[5] = { 1,2,3,4,5 };
    
// 测试数据
    double test_inputs[5][ROWS * COLS] = {
        {0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0},
        {1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1},
        {1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0},
        {0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0},
        {0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0},
    };
    int test_labels[5] = { 4, 2, 3, 5, 5 };

完整代码

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define ROWS 5
#define COLS 5
#define NUM_CLASSES 5
#define LEARNING_RATE 0.01
#define EPOCHS 6000

// sigmoid激活函数
double sigmoid(double x) {
    return 1.0 / (1.0 + exp(-x));
}

// softmax分类函数
void softmax(double* output, int n) {
    double sum = 0.0;
    for (int i = 0; i < n; i++) {
        sum += exp(output[i]);
    }
    for (int i = 0; i < n; i++) {
        output[i] = exp(output[i]) / sum;
    }
}

// 前向传播函数
void forward(double* input, double* weights, double* output) {
    for (int i = 0; i < NUM_CLASSES; i++) {
        double sum = 0.0;
        for (int j = 0; j < ROWS * COLS; j++) {
            sum += input[j] * weights[i * ROWS * COLS + j];
        }
        output[i] = sigmoid(sum);
    }
    softmax(output, NUM_CLASSES);
}

// 反向传播函数
void backward(double* input, double* weights, double* output, int label) {
    double delta[NUM_CLASSES];
    for (int i = 0; i < NUM_CLASSES; i++) {
        delta[i] = (i == label ? 1.0 : 0.0) - output[i];
    }
    for (int i = 0; i < NUM_CLASSES; i++) {
        for (int j = 0; j < ROWS * COLS; j++) {
            weights[i * ROWS * COLS + j] += LEARNING_RATE * delta[i] * input[j];
        }
    }
}

// 训练函数
void train(double* inputs, int* labels, double* weights, int num_examples) {
    for (int epoch = 0; epoch < EPOCHS; epoch++) {
        double loss = 0.0;
        for (int i = 0; i < num_examples; i++) {
            double output[NUM_CLASSES];
            forward(&inputs[i * ROWS * COLS], weights, output);
            backward(&inputs[i * ROWS * COLS], weights, output, labels[i]);
            loss -= log(output[labels[i]]);
        }
        loss /= num_examples;
        printf("Epoch %d\n", epoch + 1, loss);
    }
}

// 测试函数
void test(double* inputs, int* labels, double* weights, int num_examples) {
    int num_correct = 0;
    for (int i = 0; i < num_examples; i++) {
        double output[NUM_CLASSES];
        forward(&inputs[i * ROWS * COLS], weights, output);
        int prediction = 0;
        for (int j = 1; j < NUM_CLASSES; j++) {
            if (output[j] > output[prediction]) {
                prediction = j;
            }
        }
        if (prediction == labels[i]) {
            num_correct++;
        }
        printf("Prediction = %d\n", prediction);
    }
    double accuracy = (double)num_correct / num_examples;

    printf("Test Accuracy = %f\n", accuracy);
}

int main() {
    // 训练数据
    double inputs[5][ROWS * COLS] = {
        {0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0},
        {1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1},
        {1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0},
        {0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0},
        {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0},
    };
    int labels[5] = { 1,2,3,4,5 };

    // 初始化权重
    double weights[NUM_CLASSES * ROWS * COLS];
    for (int i = 0; i < NUM_CLASSES * ROWS * COLS; i++) {
        weights[i] = (double)rand() / RAND_MAX - 0.5;
    }

    // 训练模型
    train((double*)inputs, labels, weights, 5);

    // 测试模型
    double test_inputs[5][ROWS * COLS] = {
        {0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0},
        {1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1},
        {1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0},
        {0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0},
        {0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0},
    };
    int test_labels[5] = { 4, 2, 3, 5, 5 };
    test((double*)test_inputs, test_labels, weights, 5);

    return 0;
    
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值