【.com快译】本文的第一部分和第二部分将介绍从头开始构建人工神经网络(ANN)仅使用numpyPython库。上一篇文章将介绍构建一个非常简单的ANN,只有1个输入层和1个输出层,没有隐藏层。下一篇文章将介绍构建具有1个输入层、1个隐藏层和1个输出层的ANN。为什么要从头开始?有许多深度学习库(Keras、TensorFlow、PyTorch等)只需几行代码就可以构建神经网络。但是,如果你真的想了解神经网络的底层工作原理,建议学习如何使用Python或任何其他编程语言从头开始对神经网络进行编程。让我们创建一些随机数据集:图1.为简单起见,具有二进制值的随机数据集上表有五列:Person、X1、X2、X3和Y。1表示真,0表示假。我们的任务是创建一个能够根据X1、X2和X3的值预测Y值的人工神经网络。我们将创建一个具有1个输入层、1个输出层且没有隐藏层的人工神经网络。在我们开始编程之前,让我们来看看我们的神经网络在理论上将如何执行:ANN理论人工神经网络是一种监督学习算法,这意味着我们将输入数据与自变量和因变量输入数据。输出数据。就像在这个例子中,自变量是X1、X2和X3,因变量是Y。首先,ANN进行一些随机预测,将这些预测与正确的输出进行比较,并计算误差(预测值与预测值之间的差值)。值和实际值)。找到实际值和传播值之间差异的函数称为成本函数。这里的成本指的是误差。我们的目标是最小化代价函数。训练神经网络基本上意味着最小化成本函数。下面介绍了如何执行此任务。神经网络分两个阶段执行:前馈阶段和反向传播阶段。下面将详细描述这两个步骤。Feedforward图2来源:单层神经网络,又称Perceptron在ANN的前馈阶段,根据输入节点中的值和权重进行预测。如果查看上图中的神经网络,您会发现数据集中有三个特征:X1、X2和X3,因此第一层(也称为输入层)中有三个节点。神经网络的权重基本上是我们想要调整的字符串,以便能够正确预测输出。请记住,每个输入特征只有一个权重。以下是在ANN的前馈阶段执行的步骤:步骤1:计算输入和权重之间的点积输入层中的节点通过三个权重参数连接到输出层。在输出层,将输入节点中的值与相应的权重相乘并相加。最后,将偏差项b添加到总和中。为什么需要偏置项?假设某人有一个输入值(0,0,0),输入节点与权重的乘积之和将为零。在这种情况下,无论我们如何训练算法,输出始终为零。因此,为了能够做出预测,即使我们没有关于此人的任何非零信息,我们也需要一个偏差项。偏差项对于构建稳健的神经网络至关重要。数学上,点积之和:X.W=x1.w1+x2.w2+x3.w3+b第二步:通过激活函数传递点积之和(X.W)点积XW可以生成任意一组值。然而,在我们的输出中,我们有1和0形式的值。我们希望输出具有相同的格式。为此,我们需要一个激活函数,它将输入值限制在0和1之间。因此我们当然会使用sigmoid激活函数。图3.当Sigmoid激活函数的输入为0时,Sigmoid函数返回0.5。如果输入是一个大的正数,则返回一个接近1的值。在负输入的情况下,sigmoid函数的输出值接近于零。因此,它特别适用于我们想要预测概率作为输出的模型。由于概念仅存在于0和1之间,因此Sigmoid函数是解决我们问题的合适选择。在上图中,z是点积X.W的总和。在数学上,Sigmoid激活函数是:图4.Sigmoid激活函数总结到目前为止所做的工作。首先,我们找到输入特征(自变量矩阵)与权重的点积。接下来,将点积之和传递给激活函数。激活函数的结果基本上是输入特征的预测输出。在反向传播开始时,在任何训练之前,神经网络会进行随机预测,这当然是不正确的。我们首先让网络进行随机输出预测。然后,我们将神经网络的预测输出与实际输出进行比较。接下来,我们更新权重和偏差并确保预测输出更接近实际输出。在这个阶段,我们训练算法。让我们看一下反向传播阶段涉及的步骤。第1步:计算成本此阶段的第一步是找出预测成本。可以通过找到预测输出值与实际输出值之间的差异来计算预测成本。如果差异很大,成本也会很大。我们将使用均方误差或MSE成本函数。成本函数是计算预测给定输出的成本的函数。图5.均方误差这里,Yi是实际输出值,?i是预测输出值,n是观测值的数量。第2步:最小化成本我们的最终目标是微调神经网络的权重并最小化成本。如果你仔细观察,你会发现我们只能控制权重和偏差,其他一切都无法控制。我们无法控制输入,我们无法控制点积,我们无法操纵sigmoid函数。为了最小化成本,我们需要找到确保成本函数返回最小值的权重和偏置值。代价越小,预测越正确。为了找到函数的最小值,我们可以使用梯度下降算法。梯度下降可以在数学上表示为:图6.使用梯度下降更新权重𝛛误差是成本函数。上面的等式告诉我们求成本函数对每个权重和偏差的偏导数,然后用现有的权重减去结果得到新的权重。函数的导数给出任何给定点的斜率。为了确定成本是增加还是减少,给定一个权重值,我们可以找到该特定权重值的函数的导数。如果成本随着权重的增加而增加,则导数将返回一个正值,然后从现有值中减去该值。另一方面,如果成本随着权重的增加而降低,则将返回负值,该负值将添加到现有权重值中,因为负值会产生正值。在上面的公式中,a被称为学习率,乘以导数。学习率决定了我们的算法学习的速度。我们需要对所有的权重和偏差重复梯度下降操作,直到成本最小化并且成本函数返回一个接近于零的值。现在是实施我们迄今为止研究的人工神经网络的时候了。我们将在Python中创建一个具有1个输入层和1个输出层的简单神经网络。使用numpy实现人工神经网络图7图片来源:hackernoon.com采取的步骤:1.定义自变量和因变量2.定义超参数3.定义激活函数及其导数4.训练模型5.进行预测步骤1:首先创建自变量或输入特征集以及相应的因变量或标签。#Independentvariablesinput_set=np.array([[0,1,0],[0,0,1],[1,0,0],[1,1,0],[1,1,1],[0,1,1],[0,1,0]])#Dependentvariablelabels=np.array([[1,0,0,1,1,0,1]])labels=labels.reshape(7,1)#toconvertlabelstovector我们的输入集包含七个记录。同样,我们还为输入集中的每条记录创建了一个带有标签的标签集。标签是我们希望ANN预测的值。第2步:定义超参数。我们将使用numpy的random.seed函数,以便我们在执行以下代码时可以获得相同的随机值。接下来,我们用正态分布的随机数初始化权重。由于输入中有三个特征,我们有三个权重向量。然后,我们用另一个随机数初始化偏差值。最后,我们将学习率设置为0.05。np.random.seed(42)weights=np.random.rand(3,1)bias=np.random.rand(1)lr=0.05#learningrate第三步:定义激活函数及其导数:我们的激活函数是乙状结肠功能。defsigmoid(x):return1/(1+np.exp(-x))现在定义计算Sigmoid函数导数的函数。defsigmoid_derivative(x):返回sigmoid(x)*(1-sigmoid(x))第4步:是时候训练ANN模型了。我们将从定义纪元数开始。epoch是我们要在数据集上训练算法的次数。我们将在数据上训练算法25000次,因此epoch为25000。可以尝试不同的数字以进一步降低成本。forepochinrange(25000):inputs=input_setXW=np.dot(inputs,weights)+biasz=sigmoid(XW)error=z-labelsprint(error.sum())dcost=errordpred=sigmoid_derivative(z)z_del=dcost*dpredinputs=input_set.Tweights=weights-lr*np.dot(inputs,z_del)fornuminz_del:bias=bias-lr*num不妨了解一下每一步,然后进入预测的最后一步。我们将input_set中的值存入input变量中,使得input_set的值在每次迭代中保持不变。inputs=input_set接下来,我们找到输入和权重的点积,并为其添加偏差。(前馈阶段的第一步)XW=np.dot(inputs,weights)+bias接下来,我们将点积通过Sigmoid激活函数。(前馈阶段的第2步)z=sigmoid(XW)这样就完成了算法的前馈部分,现在是开始反向传播的时候了。变量z包含预测输出。反向传播的第一步是找出错误。error=z-labelsprint(error.sum())我们知道成本函数是:图8我们需要根据每个权重对这个函数进行微分,这可以使用微分链式法则轻松完成。我将跳过推导部分,但如果有人感兴趣,请发表评论。所以对于任何权重,成本函数的最终导数是:slope=inputxdcostxdpred现在斜率可以简化为:dcost=errordpred=sigmoid_derivative(z)z_del=dcost*dpredinputs=input_set.Tweights=weight-lr*np.dot(inputs,z_del)我们有z_del变量,它包含dcost和dpred的乘积。我们不是迭代每个记录并将输入乘以相应的z_del,而是将输入特征矩阵的转置乘以z_del。最后,我们将学习率变量lr与导数相乘以加速学习。除了更新权重,我们还更新了偏置项。fornuminz_del:bias=bias-lr*num一旦循环开始,你会看到总误差开始减少;在训练结束时,错误将保持在一个很小的值。-0.001415035616137969-0.0014150128584959256-0.0014149901015685952-0.0014149673453557714-0.0014149445898578358-0.00141492183507419-0.0014148990810050437-0.0014148763276499686-0.0014148535750089977-0.0014148308230825385-0.0014148080718707524-0.0014147853213728624-0.0014147625715897338-0.0014147398225201734-0.0014147170741648386-0.001414694326523502-0.001414671579597255-0.0014146488333842064-0.0014146260878853782-0.0014146033431002465-0.001414580599029179-0.0014145578556723406-0.0014145351130293877-0.0014145123710998-0.0014144896298846701-0.0014144668893831067-0.001414444149595611-0.0014144214105213174-0.0014143986721605849-0.0014143759345140276-0.0014143531975805163-0.001414330461361444-0.0014143077258557749-0.0014142849910631708-0.00141426225698401-0.0014142395236186895-0.0014142167909661323-0.001414194059027955-0.001414171327803089-0.001414148597290995-0.0014141258674925626-0.0014141031384067547-0.0014140804100348098-0.0014140576823759854-0.0014140349554301636-0.0014140122291978665-0.001413989503678362-0.001413966778871751-0.001413944054778446-0.0014139213313983257-0.0014138986087308195-0.0014138758867765552-0.0014138531655347973-0.001413830445006264-0.0014138077251906606-0.001413785006087985-0.0014137622876977014-0.0014137395700206355-0.0014137168530558228-0.0014136941368045382-0.0014136714212651114-0.0014136487064390219-0.0014136259923249635-0.001413603278923519-0.0014135805662344007-0.0014135578542581566-0.0014135351429944293-0.0014135124324428719-0.0014134897226037203-0.0014134670134771238-0.0014134443050626295-0.0014134215973605428-0.0014133988903706311第5步:作出预测是时候作出一些预测了先用[1,0,0]试一下:single_pt=np.array([1,0,0])result=sigmoid(np.dot(single_pt,weights)+bias)print(result)output:[0.01031463]Asyoucansee,theoutputiscloserto0than1,sotheclassificationis0.Maywishtotryagainwith[0,1,0]:single_pt=np.array([0,1,0])result=sigmoid(np.dot(single_pt,weights)+bias)print(result)output:[0.99440207]Asyoucansee,theoutputiscloserto1thanto0,hencetheclassificationas1.结论在本文中,我们学习了如何使用numpyPython库从头开始创建一个非常简单的人工神经网络,只有1个输入层和1个输出层。该ANN能够对线性可分数据进行分类。如果我们有非线性可分的数据,我们的ANN就不能对这种类型的数据进行分类。下一篇文章将介绍如何构建这样的ANN。原标题:BuildinganArtificialNeuralNetworkFromScratch:Part1,作者:NageshSinghChauhan
