当前位置:首页 > 行业动态 > 正文

c 神经网络 入门实例

神经网络入门实例通常从简单感知机开始,构建含输入、隐藏及输出层的网络,用小数据集训练,如手写数字识别,助理解原理。

在C语言中实现神经网络,尤其是对于初学者来说,是一个复杂但极具教育意义的过程,下面将通过一个简单的入门实例来展示如何使用C语言构建一个基本的前馈神经网络,用于解决异或(XOR)问题,这个例子将涵盖神经网络的基本概念、结构定义、前向传播以及训练过程的简化版本。

神经网络基础

神经网络由多个层次的神经元组成,包括输入层、隐藏层和输出层,每个神经元接收输入,通过加权求和并应用激活函数后产生输出,在这个例子中,我们将构建一个包含一个输入层、一个隐藏层和一个输出层的简单神经网络。

网络结构定义

我们需要定义网络的结构,包括每层的神经元数量、权重矩阵和偏置向量,为了简化,我们假设输入层有2个神经元(对应于XOR问题的两个输入),隐藏层有2个神经元,输出层有1个神经元(输出0或1表示XOR的结果)。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define INPUT_SIZE 2
#define HIDDEN_SIZE 2
#define OUTPUT_SIZE 1
// 激活函数:Sigmoid
double sigmoid(double x) {
    return 1.0 / (1.0 + exp(-x));
}
// 网络参数初始化
double hidden_weights[INPUT_SIZE][HIDDEN_SIZE] = {{0.5, -0.5}, {0.5, -0.5}};
double output_weights[HIDDEN_SIZE][OUTPUT_SIZE] = {{0.5}, {-0.5}};
double hidden_biases[HIDDEN_SIZE] = {0.1, 0.1};
double output_bias[OUTPUT_SIZE] = {0.1};

前向传播

前向传播是计算输入通过神经网络层层传递直到输出的过程,对于每个神经元,我们计算其加权输入之和,加上偏置,然后应用激活函数。

c 神经网络 入门实例

void forward_propagation(double inputs[INPUT_SIZE], double hidden[HIDDEN_SIZE], double output[OUTPUT_SIZE]) {
    // 计算隐藏层输出
    for (int j = 0; j < HIDDEN_SIZE; j++) {
        hidden[j] = 0.0;
        for (int k = 0; k < INPUT_SIZE; k++) {
            hidden[j] += inputs[k] * hidden_weights[k][j];
        }
        hidden[j] += hidden_biases[j];
        hidden[j] = sigmoid(hidden[j]);
    }
    // 计算输出层输出
    for (int j = 0; j < OUTPUT_SIZE; j++) {
        output[j] = 0.0;
        for (int k = 0; k < HIDDEN_SIZE; k++) {
            output[j] += hidden[k] * output_weights[k][j];
        }
        output[j] += output_bias[j];
        output[j] = sigmoid(output[j]);
    }
}

训练网络

训练网络通常涉及反向传播算法,但在这个简化的例子中,我们将使用一种非常基础的方法来调整权重和偏置,以使网络能够学习XOR功能,这里,我们简单地通过多次迭代随机调整权重,直到网络输出接近期望结果,注意,这不是实际的训练方法,只是为了演示目的。

void train_network() {
    double inputs[4][INPUT_SIZE] = {{0, 0}, {0, 1}, {1, 0}, {1, 1}};
    double expected_outputs[4][OUTPUT_SIZE] = {{0}, {1}, {1}, {0}};
    double hidden[HIDDEN_SIZE], output[OUTPUT_SIZE];
    int iterations = 10000; // 迭代次数
    for (int iter = 0; iter < iterations; iter++) {
        for (int i = 0; i < 4; i++) {
            forward_propagation(inputs[i], hidden, output);
            double error = expected_outputs[i][0] output[0];
            // 简单的权重更新规则(不是反向传播)
            for (int j = 0; j < HIDDEN_SIZE; j++) {
                hidden_weights[0][j] += 0.01 * error * inputs[i][0];
                hidden_weights[1][j] += 0.01 * error * inputs[i][1];
            }
            for (int j = 0; j < OUTPUT_SIZE; j++) {
                output_weights[0][j] += 0.01 * error * hidden[0];
                output_weights[1][j] += 0.01 * error * hidden[1];
            }
        }
    }
}

测试网络

我们测试训练好的网络是否能正确解决XOR问题。

int main() {
    train_network(); // 训练网络
    double test_inputs[INPUT_SIZE] = {1, 1}; // XOR输入
    double hidden[HIDDEN_SIZE], output[OUTPUT_SIZE];
    forward_propagation(test_inputs, hidden, output);
    printf("Output: %f
", output[0]); // 应接近0或1
    return 0;
}

FAQs

Q1: 这个网络为什么能解决XOR问题?

c 神经网络 入门实例

A1: XOR问题是线性不可分的,需要非线性激活函数(如Sigmoid)来引入非线性因素,使得网络能够学习到输入之间的复杂关系,通过调整权重和偏置,网络逐渐逼近正确的输出。

Q2: 为什么选择Sigmoid作为激活函数?

A2: Sigmoid函数能够将神经元的输出压缩到0到1之间,这有助于处理概率问题,并且在历史上是神经网络中常用的激活函数之一,现代神经网络中也广泛使用ReLU等其他激活函数,因为它们在某些情况下表现更好,比如减少梯度消失问题。

c 神经网络 入门实例

小编有话说

虽然这个例子极大地简化了神经网络的训练过程,但它展示了用C语言实现神经网络的基本框架和原理,实际应用中,神经网络的训练要复杂得多,涉及到更高级的训练算法(如随机梯度下降、Adam优化器等)、正则化化技术(如Dropout、L2正则化等)以及更复杂的网络架构(如卷积神经网络CNN、循环神经网络RNN等),还有许多高效的深度学习库(如TensorFlow、PyTorch等)提供了更高级的API和优化,使得神经网络的实现和应用变得更加便捷和高效。