推广 热搜: csgo  vue  angelababy  2023  gps  新车  htc  落地  app  p2p 

什么是神经网络?用代码示例解析其工作原理

   2023-07-05 网络整理佚名930
核心提示:该神经网络示例中,包含一个输入层(2个节点),一个隐藏层(2个节点)和一个输出层(1个节点)。上述简单示例中,涉及到如下神经网络基本概念:在上面的代码示例中,我们计算了输出层的误差(),这个误差实际上就是损失函数的梯度。函数是一种常用的激活函数,用于神经网络中对节点输出进行非线性转换。偏置参数使神经网络能够在没有输入(或输入为零)时产生非零输出。函数为例,一个神经元的输出可以表示为:

神经网络是一种模仿人脑神经元工作的计算模型,用于实现机器学习和人工智能系统。 它由一系列组织成不同层的互连神经元(也称为节点或单元)组成。 神经网络通常由输入层、一个或多个隐藏层和输出层组成。 每个节点根据其输入数据和相应的权重计算输出值,并通过激活函数进行非线性变换。

神经网络可以通过学习和调整权重来实现自适应,从而在处理复杂问题(如图像识别、自然语言处理和游戏策略等)时具有较高的灵活性。 训练神经网络的过程通常涉及获取大量输入数据和期望的输出,计算损失函数(衡量网络的输出与期望输出的差异程度),以及使用优化算法(例如梯度下降)来调整权重以最小化损失。

神经网络是深度学习的核心组成部分,深度学习模型通常包含多个隐藏层,使其能够学习更复杂的数学表示和抽象概念。

我们以一个简单的神经网络(用于解决异或问题)为例来说明神经网络中的各种概念。

在此示例神经网络中,有一个输入层(2 个节点)、一个隐藏层(2 个节点)和一个输出层(1 个节点)。 输入层和输出层之间以及隐藏层和输出层之间的所有节点都相互连接。 激活函数是一个函数。

上述神经网络的实现如下:

import numpy as np
# Sigmoid 激活函数
def sigmoid(x):
    return 1 / (1 + np.exp(-x))
# 使用 sigmoid 导数进行非线性变换以及反向传播计算梯度
def sigmoid_derivative(x):
    return x * (1 - x)
def mse_loss(y_true, y_pred):
    return np.mean(np.square(y_true - y_pred))
class NeuralNetwork:
    def __init__(self, input_nodes, hidden_nodes, output_nodes):
        self.input_nodes = input_nodes
        self.hidden_nodes = hidden_nodes
        self.output_nodes = output_nodes
        self.weights_ih = np.random.rand(self.input_nodes, self.hidden_nodes) - 0.5
        self.weights_ho = np.random.rand(self.hidden_nodes, self.output_nodes) - 0.5
        self.bias_h = np.random.rand(1, self.hidden_nodes) - 0.5
        self.bias_o = np.random.rand(1, self.output_nodes) - 0.5
    def feedforward(self, input_data):
        hidden = sigmoid(np.dot(input_data, self.weights_ih) + self.bias_h)
        output = sigmoid(np.dot(hidden, self.weights_ho) + self.bias_o)
        return hidden, output
    def backward(self, input_data, hidden, output, target_data, learning_rate=0.1):
        # 计算损失函数的梯度
        output_error = target_data - output
        output_delta = output_error * sigmoid_derivative(output)
        hidden_error = np.dot(output_delta, self.weights_ho.T)
        hidden_delta = hidden_error * sigmoid_derivative(hidden)
        self.weights_ho += learning_rate * np.dot(hidden.T, output_delta)
        self.weights_ih += learning_rate * np.dot(input_data.T, hidden_delta)
        self.bias_o += learning_rate * np.sum(output_delta, axis=0)
        self.bias_h += learning_rate * np.sum(hidden_delta, axis=0)
    # 根据输入输出数据,训练多轮,更新神经网络的权重和偏置,最终得到正确的神经网络参数
    def train(self, input_data, target_data, epochs, learning_rate=0.5):
        for _ in range(epochs):
            hidden, output = self.feedforward(input_data)
            self.backward(input_data, hidden, output, target_data, learning_rate)
if __name__ == "__main__":
    # 示例
    X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
    Y = np.array([[0], [1], [1], [0]])
    nn = NeuralNetwork(input_nodes=2, hidden_nodes=2, output_nodes=1)
    print("Before training:")
    _, output = nn.feedforward(X)
    print(output)
    nn.train(X, Y, epochs=2000, learning_rate=0.8)
    print("After training:")
    _, output = nn.feedforward(X)
    print(output)
    # 计算损失
    loss = mse_loss(Y, output)
    print("Loss:", loss)

在上面的简单例子中,涉及到以下神经网络的基本概念:

在上面的代码示例中,我们计算了输出层的误差( ),它实际上是损失函数的梯度。 这里的损失函数是均方误差(MSE),计算梯度的公式为:

output_error = target_data - output

在反向传播期间,我们通过该梯度更新权重和偏差以最小化损失。 因此,损失值在训练过程中起着关键作用。

其中,该函数是常用的激活函数,在神经网络中用于对节点输出进行非线性变换。 该函数的数学表达式如下:

sigmoid(x) = 1 / (1 + e^(-x))

其中 x 是输入值,e 是自然常数(约等于 2.71828)。

函数的输出值范围在0到1之间,并且具有平滑的S形曲线。 当输入值x趋于正无穷大时,函数值接近1; 当输入值x趋于负无穷大时,函数值接近0。因此,该函数可以将任何实际输入映射到(0, 1)区间,使得网络输出更好地可解释。 另外,函数的导数也可以方便地用其函数值来表示,方便梯度下降优化算法。

但该函数也存在一些问题,比如梯度消失问题。 当输入值太大或太小时,函数的梯度(导数)接近于0,导致权重更新非常慢,影响训练速度和效果。 因此,在深度学习中,有时会选择其他激活函数,例如ReLU(线性整流单元)等。

另外,引入偏差(bias)是为了增加模型的表达能力。 具体来说,在激活函数中,偏置的作用如下:

调整激活函数的输出:在神经网络中,激活函数(例如函数)用于对节点的线性加权和应用非线性变换。 偏差相当于一个常数值,可以整体上移或下移激活函数的输出。 这样激活函数就可以保持对不同区域输入的敏感性,提高模型的拟合能力。

提高模型的灵活性:添加偏置后,神经网络可以学习更复杂的表示。 偏差参数使神经网络在没有输入(或输入为零)时产生非零输出。 如果没有偏差,当输入为零时,即使权重参数不同,神经元的输出也将是相同的。 因此,引入偏差为神经网络提供了额外的自由度,使其能够更好地拟合复杂数据。

以函数为例,神经元的输出可以表示为:

= (w1 * x1 + w2 * x2 + ... + wn * xn + b)

这里,w1,w2,...,wn 是对应于输入数据(x1,x2,...,xn)的权重,b 是偏差。 通过调整偏置b的值,可以整体增大或减小函数的输出,从而改变神经元的激活阈值。 这使得神经网络能够更好地适应不同的数据分布,提高模型的泛化能力。

常见问题解答

梯度与函数导数的关系?

梯度与导数密切相关,但也有一些区别。 对于单变量函数(即只有一个自变量的函数),梯度就是导数。 导数表示函数在某一点的切线的斜率。 对于多元函数(即具有多个自变量的函数),梯度是一个向量,其中包含函数在沿每个轴的某一点处的偏导数。

换句话说,梯度是组合多个偏导数的向量,描述多元函数如何在各个方向上变化。 梯度的方向是函数在该点变化最快的方向,梯度的大小代表函数在该点的变化率。

综上所述:

 
反对 0举报 0 收藏 0 打赏 0评论 0
 
更多>同类资讯
推荐图文
推荐资讯
点击排行
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报
Powered By DESTOON