[译] 面向初学者: 神经网络概述(一)

SlimBear

最近网上看到一篇质量很不错的翻译文《小白都能看懂的神经网络教程:从原理到优化如此简单》,如获至宝。细读后发现里面有些翻译不到位。然后翻到原文读了一遍,又感觉原文有些虎头蛇尾,前半部分讲解深入浅出,后半部分讲解不够细致,匆匆收尾,作者似乎着急忙慌要睡觉似的。于是决定对原文再翻译一遍,以飨读者。

译文如下:

一篇简单介绍神经网络如何工作,以及如何用Python从头实现的文章

如果说“神经网络”其实不复杂,这可能会让你感到惊讶。事实上“神经网络”往往比你想象的要简单。

这篇文章是面向初学者的,并假定你机器学习基础为0。 我们将从头了解如何用 Python 实现神经网络。

1. 基本构建模块:神经元(Neurons)

首先,我们必须讨论下神经元,这是神经网络的基本单位。一个神经元接受多个输入,并对它们进行一些数学运算,然后产生一个输出。下图展示的是一个接收2个输入的神经元:
2 input svg
这里发生了三件事:
首先,每个 输入 (input) 都乘以一个权重 $w$ (weight):

$$ \begin{array}{l} x_{1} \rightarrow x_{1} * w_{1} \\ x_{2} \rightarrow x_{2} * w_{2} \end{array} $$

然后,所有的加权输入求和后又加上一个 偏移 $b$ (bias):

$$ \left(x_{1} * w_{1}\right)+\left(x_{2} * w_{2}\right)+b $$

最后,加他们的 传递给一个 激活函数 (activation function):

$$ y=f\left(x_{1} * w_{1}+x_{2} * w_{2}+b\right) $$

这里的激活函数作用是将无限制的输入转换为可预测的输出。一种常见的激活函数是 sigmoid函数

$$ \begin{aligned} \frac{1}{1+e^{-x}} \end{aligned} $$

激活函数
激活函数的输出数值只会落在 (0,1) 这个区间。你可以把它想象成将 $(−∞,+∞)$ 压缩成 $(0,1)$:

  • 把无限小的负数转化为无限接近于0
  • 把无限大的正数转化为无限接近于1

一个简单的例子

假设我们有一个使用$sigmoid$激活函数的神经元,它可以接收两个输入,下面是他的权重偏移

$$ w = [0,1] \\ b = 4 $$

$w = [0 ,1]$ 是 $w_{1} = 0$,$w_{2} = 1$ 的矢量表示法。

现在我们输入 $x = [2, 3]$。我们将用 点积 来简明的阐述:

$$ \begin{aligned} (w \cdot x)+b &=\left(\left(w_{1} * x_{1}\right)+\left(w_{2} * x_{2}\right)\right)+b \\ &=0 * 2+1 * 3+4 \\ &=7 \end{aligned} $$

$$ y=f(w \cdot x+b)=f(7)=\bm{0.999} $$

这个神经元给定输入$[2,3]$,给定输出 $0.999$。就是这样!这种向前传递输入以获得输出的过程成为前馈$(feedforward)$

编写一个神经元

是时候实现一个神经元了!我们将利用 Numpy (一个流行而强大的科学计数库) 来帮我们实现数学公式:

import numpy as np

def sigmoid(x):
  # Our activation function: f(x) = 1 / (1 + e^(-x))
  return 1 / (1 + np.exp(-x))

class Neuron:
  def __init__(self, weights, bias):
    self.weights = weights
    self.bias = bias

  def feedforward(self, inputs):
    # Weight inputs, add bias, then use the activation function
    total = np.dot(self.weights, inputs) + self.bias
    return sigmoid(total)

weights = np.array([0, 1]) # w1 = 0, w2 = 1
bias = 4                   # b = 4
n = Neuron(weights, bias)

x = np.array([2, 3])       # x1 = 2, x2 = 3
print(n.feedforward(x))    # 0.9990889488055994

认识这个数字吧?我们得到了相同的结果 0.999

2. 将神经元组合成神经网络

神经网络是什么?其实无非就是一束连接在一起的神经元。这是一个简单的神经网络的样子:
神经网络
该网络有2个输入,一个包含2个神经元的隐藏层($h_1$ 和 $h_2$​),以及一个带有1个神经元的输出层($o_1$​)。请注意,$o_1$​ 的输入来自 $h_1$ 和 $h_2$的输出 -这就是神经网络。

举个栗子:前馈

以上面图中的神经网络为例,并假定所有神经元都有相同的权重 $w=[0,1]$, 相同的偏移 $b=0$,以及相同的$sigmoid$激活函数。用$h_1,h_2,o_1$表示他们代表的神经元输出。

如果我们输入 $x = [2,3]$,会发生什么?

$$ \begin{aligned} h_{1}=h_{2} &=f(w \cdot x+b) \\ &=f((0 * 2)+(1 * 3)+0) \\ &=f(3) \\ &=0.9526 \end{aligned} $$

$$ \begin{aligned} o_{1} &=f\left(w \cdot\left[h_{1}, h_{2}\right]+b\right) \\ &=f\left(\left(0 * h_{1}\right)+\left(1 * h_{2}\right)+0\right) \\ &=f(0.9526) \\ &=\bm{0.7216} \end{aligned} $$

当输入为 $x = [2,3]$,这个神经网络输出为 $0.7216$, 是不是很简单?

一个神经网络可以有任意数量的层,每层可以有任意数据的神经元。基本思想一致:向前给神经元传递输入,并在后面得到结果。

方便起见,本文的其余部分将继续使用上图所示的神经网络

编写一个神经网络:前馈

让我们实现一个前馈神经网络。这是该网络的图片,仅供参考:
前馈神经网络

import numpy as np

# ... code from previous section here

class OurNeuralNetwork:
  '''
  A neural network with:
    - 2 inputs
    - a hidden layer with 2 neurons (h1, h2)
    - an output layer with 1 neuron (o1)
  Each neuron has the same weights and bias:
    - w = [0, 1]
    - b = 0
  '''
  def __init__(self):
    weights = np.array([0, 1])
    bias = 0

    # The Neuron class here is from the previous section
    self.h1 = Neuron(weights, bias)
    self.h2 = Neuron(weights, bias)
    self.o1 = Neuron(weights, bias)

  def feedforward(self, x):
    out_h1 = self.h1.feedforward(x)
    out_h2 = self.h2.feedforward(x)

    # The inputs for o1 are the outputs from h1 and h2
    out_o1 = self.o1.feedforward(np.array([out_h1, out_h2]))

    return out_o1

network = OurNeuralNetwork()
x = np.array([2, 3])
print(network.feedforward(x)) # 0.7216325609518421

我们又得出了$0.7216$,完美!

阅读 226

有点懒怎么办?

592 声望
116 粉丝
0 条评论
你知道吗?

有点懒怎么办?

592 声望
116 粉丝
宣传栏