从零开始实现神经网络(一)_NN神经网络

参考文章:神经网络介绍

一、神经元

        这一神经网络的基本单元,神经元接受输入,对它们进行一些数学运算,并产生一个输出。

这里有三步。

        首先,将每个输入(X1)乘以一个权重

        x_1 * w_1

        x_2 * w_2

        接下来,将所有加权输入与偏置相加:

        ( x_1 * w _1 ) + ( x_2 * w_2 ) + b

        最后,总和通过激活函数传递:

        y = f(w_1*x_1 + w_2 * x_2 + b)

激活函数

激活函数用于将无界输入转换为具有良好、可预测形式的输出。常用的激活函数是sigmoid功能:

你可以把它想象成,压缩零到负无穷的数字到[-1,0],压缩0到正无穷的数字到[0,1]

举个例子:

        这里写成向量形式,假设权重W = {w1,w2} = {0,1},输入X = {x1,x2} = {2,3},偏置b为1。

        那么有一下计算:

        (X\cdot W ) + b = ( x_1 * w _1 ) + ( x_2 * w_2 ) + b

                                = 0 * 2 +1*3 +4

                                =7

        y = f(w_1*x_1 + w_2 * x_2 + b) = f(7) = 0.9999

下面来实现下代码:

import numpy as npdef 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 = weightsself.bias = biasdef feedforward(self, inputs):# Weight inputs, add bias, then use the activation functiontotal = np.dot(self.weights, inputs) + self.biasreturn 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

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

        神经网络只不过是一堆连接在一起的神经元。下面是一个简单的神经网络的样子:

该网络有 2 个输入(x1和x2),一个带有 2 个神经元的隐藏层 (ℎ1​和ℎ2​),以及具有 1 个神经元 (o1​).请注意,输入o1​是来自ℎ1​和h2​- 这就是使它成为一个网络的原因。

隐藏层是输入(第一层)和输出(最后一层)之间的任何。可以有多个隐藏层!

示例:前馈

让我们使用上图的网络,并假设所有神经元具有相同的权重w=[0,1],相同的偏差b=0,以及相同的 S 形激活函数。让h1​,h2​,o1​表示它们所代表的神经元的输出

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

用于输入的神经网络的输出x=[2,3]是0.7216很简单,对吧?

神经网络可以有任意数量的,这些层中可以有任意数量的神经元。基本思想保持不变:通过网络中的神经元向前馈送输入,以在最后获得输出。为简单起见,在本文的其余部分,我们将继续使用上图的网络。

神经网络的代码实现:

import numpy as np# ... code from previous section hereclass 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 sectionself.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 h2out_o1 = self.o1.feedforward(np.array([out_h1, out_h2]))return out_o1network = OurNeuralNetwork()
x = np.array([2, 3])
print(network.feedforward(x)) # 0.7216325609518421

三. 训练神经网络,第 1 部分

假设我们有以下测量值:

名字重量(磅)高度(英寸)
爱丽丝13365F
鲍勃16072M
查理15270M
黛安娜12060F

让我们训练我们的网络,根据某人的体重和身高预测他们的性别:

我们将用0代表男性1代表女性,我们还将处理数据以使其更易于使用:

名字重量(减去 135)高度(减去 66)
爱丽丝-2-11
鲍勃2560
查理1740
黛安娜-15-61

我随意选择了减去的数值(135和66) 以使数值看起来更好。通常,会按平均值移动。

损失

在我们训练网络之前,我们首先需要一种方法来量化它做得有多“好”,以便它可以尝试做得“更好”。这就是损失所在。

        我们将使用均方误差 (MSE) 损失:

        MSE = \frac{1}{n}\sum^n_{i=1} (yTrue - yPred)^2

让我们分解一下:

  • n是样本数,即4(爱丽丝,鲍勃,查理,戴安娜)。
  • y表示要预测的变量,即性别。
  • yTrue​是变量的真实值(“正确答案”)。例如yTRue​因为爱丽丝的性别为1(女)。
  • yPred​是变量的预测值。这是我们的网络输出的任何内容。

(yTrue - yPred)^2称为平方误差。我们的损失函数只是取所有平方误差的平均值(因此得名方误差)。我们的预测越好,我们的损失就越低!

更好的预测=更低的损失。

训练网络=试图将其损失降至最低。

损失计算示例

假设我们的网络总是输出0换句话说,它相信所有人类都是男性🤔。我们的损失会是什么?

名字yTRueyPRED(yTrue - yPred)^2
爱丽丝101
鲍勃000
查理000
黛安娜101

        MSE=\frac{1}{4}(1+0+0+1) = 0.5

均方误差的代码实现:

import numpy as npdef mse_loss(y_true, y_pred):# y_true and y_pred are numpy arrays of the same length.return ((y_true - y_pred) ** 2).mean()y_true = np.array([1, 0, 0, 1])
y_pred = np.array([0, 0, 0, 0])print(mse_loss(y_true, y_pred)) # 0.5

四. 训练神经网络,第 2 部分

反向传播

我们现在有一个明确的目标:尽量减少神经网络的损失。我们知道我们可以改变网络的权重和偏差来影响其预测,但是我们如何以减少损失的方式做到这一点呢?

为简单起见,让我们假设我们的数据集中只有 爱丽丝:

名字重量(减去 135)高度(减去66)
爱丽丝-2-11

        那么只是爱丽丝的均方误差损失(最后会带入yTrue的值进去):

        MSE = \frac{1}{1}\sum^1_{i=1} (yTrue - yPred)^2

        =(yTrue - yPred)^2

        =(1 - yPred)^2

另一种考虑损失的方法是作为权重和偏差的函数。让我们标记网络中的每个权重和偏差:

 

然后,我们可以将损失写为多变量函数:

        L(w1​,w2​,w3​,w4​,w5​,w6​,b1​,b2​,b3​)

想象一下,我们想调整w1​.损失将如何L如果我们改变了,就改变w1​?

这是一个偏导数的问题 \frac{\partial L}{\partial w_1}可以回答。我们如何计算它?

首先,让我们根据以下方法(链式法则)重写偏导数:

        \frac{\partial L}{\partial w_1} =\frac{\partial L}{\partial yPred} * \frac{\partial yPred}{\partial w_1}

这里\frac{\partial L}{\partial yPred}我们可以求得,由于前面的MSE均方误差计算的就是神经网络的误差,MSE作为损失函数,所以有等式:

        L(w1,w2,w3,w4,w5,w6,b1,b2,b3) = (1 - yPred)^2

所以可以得出:

         \frac{\partial L}{\partial yPred} = \frac{\partial (1 - yPred)^2}{\partial yPred}

这里使用符合函数求导法则(对于f(g(x))函数的x进行求导,将得到= f(g(x))^{'}*g(x)^{'}):

        = 2*(1-yPred)*(1-yPred)^{'}

        =2*(1-yPred)*(-1)

        =-2*(1-yPred)

然后我们再搞清楚\frac{\partial yPred}{\partial w_1},由于yPred是预测值,而预测值由激活函数输出,所以能够得到等式:

        yPred = o_1 = f(w_5*h_1 + w_6 * h_2 + b_3)

由于改变w1只对h1有影响,所以可以写成: 

我们再对h1做同样的步骤(h1是上一层的激活函数),\frac{\partial h_1}{\partial w_1},同样是复合函数求导法则:

对于激活函数sigmoid的倒数:

最终整合起来:

这种通过逆向计算偏导数的系统称为反向传播。

推导当前神经网络反向传播所用到的所有偏导公式:

\frac{\partial L}{\partial w_1} = \frac{\partial L}{\partial yPred} * \frac{\partial yPred}{\partial h_1} * \frac{\partial h_1}{\partial w_1}

\frac{\partial L}{\partial w_2} = \frac{\partial L}{\partial yPred} * \frac{\partial yPred}{\partial h_1} * \frac{\partial h_1}{\partial w_2}

\frac{\partial L}{\partial w_3} = \frac{\partial L}{\partial yPred} * \frac{\partial yPred}{\partial h_2} * \frac{\partial h_2}{\partial w_3}

\frac{\partial L}{\partial w_4} = \frac{\partial L}{\partial yPred} * \frac{\partial yPred}{\partial h_2} * \frac{\partial h_2}{\partial w_4}

\frac{\partial L}{\partial w_5} = \frac{\partial L}{\partial yPred} * \frac{\partial yPred}{\partial w_5}

\frac{\partial L}{\partial w_6} = \frac{\partial L}{\partial yPred} * \frac{\partial yPred}{\partial w_6}

\frac{\partial L}{\partial b_1} = \frac{\partial L}{\partial yPred} * \frac{\partial yPred}{\partial h_1} * \frac{\partial h_1}{\partial b_1}

\frac{\partial L}{\partial b_2} = \frac{\partial L}{\partial yPred} * \frac{\partial yPred}{\partial h_2} * \frac{\partial h_2}{\partial b_2}

\frac{\partial L}{\partial b_3} = \frac{\partial L}{\partial yPred} * \frac{\partial yPred}{\partial b_3}

例子:

我们将继续假设数据集中只有 爱丽丝:

名字重量(减去 135)高度(减去 66)
爱丽丝-2-11

让我们将所有权重初始化为1以及所有偏置为0.如果我们通过网络进行前馈传递,我们会得到:

网络输出yPred​=0.524,这并不强烈支持男性 或女性 .让我们计算一下\frac{\partial L}{\partial w_1}

这里用到了上面所求得的sigmoid的倒数。

我们成功了!这告诉我们,由于\frac{\partial L}{\partial w_1}所求的偏导结果为0.0214,是个正数,函数单调递增,所以

如果我们要增加w1(权重)​,L(损失)结果会增大一点点。

训练:随机梯度下降

我们现在拥有训练神经网络所需的所有工具!我们将使用一种称为随机梯度下降 (SGD) 的优化算法,该算法告诉我们如何改变权重和偏差以最小化损失。

就是这个方程式:

η是一个称为学习率的常数,它控制着我们训练的速度。我们所做的只是用旧权重减去学习率*偏导值​:

  • 如果\frac{\partial L}{\partial w_1}的值为正数,w1​的减少,会使得L减少。
  • 如果\frac{\partial L}{\partial w_1}的值为负数,w1​的增加,会使得L减少。

如果我们对网络中的每个权重和偏差都这样做,损失将慢慢减少,我们的网络将得到改善。

我们的训练过程将如下所示:

  1. 从我们的数据集中选择一个样本。这就是它随机梯度下降的原因——我们一次只对一个样本进行操作。
  2. 计算所有损失相对于权重或偏差的偏导数(例如​\frac{\partial L}{\partial w_1}​,\frac{\partial L}{\partial w_2}​等)。
  3. 使用更新公式更新每个权重和偏差。
  4. 返回步骤 1。

让我们看看它的实际效果吧!

代码:一个完整的神经网络

终于到了实现一个完整的神经网络的时候了:

名字重量(减去 135)高度(减去 66)
爱丽丝-2-11
鲍勃2560
查理1740
黛安娜-15-61
import numpy as npdef sigmoid(x):# Sigmoid activation function: f(x) = 1 / (1 + e^(-x))return 1 / (1 + np.exp(-x))def deriv_sigmoid(x):# Derivative of sigmoid: f'(x) = f(x) * (1 - f(x))fx = sigmoid(x)return fx * (1 - fx)def mse_loss(y_true, y_pred):# y_true and y_pred are numpy arrays of the same length.return ((y_true - y_pred) ** 2).mean()class OurNeuralNetwork:'''A neural network with:- 2 inputs- a hidden layer with 2 neurons (h1, h2)- an output layer with 1 neuron (o1)*** DISCLAIMER ***:The code below is intended to be simple and educational, NOT optimal.Real neural net code looks nothing like this. DO NOT use this code.Instead, read/run it to understand how this specific network works.'''def __init__(self):# Weightsself.w1 = np.random.normal()self.w2 = np.random.normal()self.w3 = np.random.normal()self.w4 = np.random.normal()self.w5 = np.random.normal()self.w6 = np.random.normal()# Biasesself.b1 = np.random.normal()self.b2 = np.random.normal()self.b3 = np.random.normal()def feedforward(self, x):# x is a numpy array with 2 elements.h1 = sigmoid(self.w1 * x[0] + self.w2 * x[1] + self.b1)h2 = sigmoid(self.w3 * x[0] + self.w4 * x[1] + self.b2)o1 = sigmoid(self.w5 * h1 + self.w6 * h2 + self.b3)return o1def train(self, data, all_y_trues):'''- data is a (n x 2) numpy array, n = # of samples in the dataset.- all_y_trues is a numpy array with n elements.Elements in all_y_trues correspond to those in data.'''learn_rate = 0.1epochs = 1000 # number of times to loop through the entire datasetfor epoch in range(epochs):for x, y_true in zip(data, all_y_trues):# --- Do a feedforward (we'll need these values later)sum_h1 = self.w1 * x[0] + self.w2 * x[1] + self.b1h1 = sigmoid(sum_h1)sum_h2 = self.w3 * x[0] + self.w4 * x[1] + self.b2h2 = sigmoid(sum_h2)sum_o1 = self.w5 * h1 + self.w6 * h2 + self.b3o1 = sigmoid(sum_o1)y_pred = o1# --- Calculate partial derivatives.# --- Naming: d_L_d_w1 represents "partial L / partial w1"d_L_d_ypred = -2 * (y_true - y_pred)# Neuron o1d_ypred_d_w5 = h1 * deriv_sigmoid(sum_o1)d_ypred_d_w6 = h2 * deriv_sigmoid(sum_o1)d_ypred_d_b3 = deriv_sigmoid(sum_o1)d_ypred_d_h1 = self.w5 * deriv_sigmoid(sum_o1)d_ypred_d_h2 = self.w6 * deriv_sigmoid(sum_o1)# Neuron h1d_h1_d_w1 = x[0] * deriv_sigmoid(sum_h1)d_h1_d_w2 = x[1] * deriv_sigmoid(sum_h1)d_h1_d_b1 = deriv_sigmoid(sum_h1)# Neuron h2d_h2_d_w3 = x[0] * deriv_sigmoid(sum_h2)d_h2_d_w4 = x[1] * deriv_sigmoid(sum_h2)d_h2_d_b2 = deriv_sigmoid(sum_h2)# --- Update weights and biases# Neuron h1self.w1 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w1self.w2 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w2self.b1 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_b1# Neuron h2self.w3 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h2_d_w3self.w4 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h2_d_w4self.b2 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h2_d_b2# Neuron o1self.w5 -= learn_rate * d_L_d_ypred * d_ypred_d_w5self.w6 -= learn_rate * d_L_d_ypred * d_ypred_d_w6self.b3 -= learn_rate * d_L_d_ypred * d_ypred_d_b3# --- Calculate total loss at the end of each epochif epoch % 10 == 0:y_preds = np.apply_along_axis(self.feedforward, 1, data)loss = mse_loss(all_y_trues, y_preds)print("Epoch %d loss: %.3f" % (epoch, loss))# Define dataset
data = np.array([[-2, -1],  # Alice[25, 6],   # Bob[17, 4],   # Charlie[-15, -6], # Diana
])
all_y_trues = np.array([1, # Alice0, # Bob0, # Charlie1, # Diana
])# Train our neural network!
network = OurNeuralNetwork()
network.train(data, all_y_trues)

随着网络学习,我们的损失稳步减少:

我们现在可以使用网络来预测性别:

# Make some predictions
emily = np.array([-7, -3]) # 128 pounds, 63 inches
frank = np.array([20, 2])  # 155 pounds, 68 inches
print("Emily: %.3f" % network.feedforward(emily)) # 0.951 - F
print("Frank: %.3f" % network.feedforward(frank)) # 0.039 - M

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/177682.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flume 快速入门【概述、安装、拦截器】

文章目录 什么是 Flume?Flume 组成Flume 安装Flume 配置任务文件应用示例启动 Flume 采集任务 Flume 拦截器编写 Flume 拦截器拦截器应用 什么是 Flume? Flume 是一个开源的数据采集工具,最初由 Apache 软件基金会开发和维护。它的主要目的是…

项目知识点总结-住房图片信息添加-Excel导出

(1)住房信息添加 Controller: RequestMapping("/add")public String add(Home home, Model model) throws IOException{String sqlPath null;//定义文件保存的本地路径String localPath"D:\\AnZhuang\\Java项目\\选题\\Xin-…

SQLServer数据库透明加密 安当加密

安当TDE透明加密组件是一种用于数据保护的解决方案,它对数据进行加密,以防止未经授权的访问和数据泄露。 以下是安当TDE透明加密组件的主要功能介绍: 数据保护:安当TDE透明加密组件可以对数据库中的敏感数据进行加密,…

HNU-计算机网络-实验1-应用协议与数据包分析实验(Wireshark)

计算机网络 课程基础实验一 应用协议与数据包分析实验(Wireshark) 计科210X 甘晴void 202108010XXX 一、实验目的: 通过本实验,熟练掌握Wireshark的操作和使用,学习对HTTP协议进行分析。 二、实验内容 2.1 HTTP 协议简介 HTTP 是超文本…

每日自动化提交git

目前这个功能,有个前提: 这个git代码仓库,是一个人负责,所以不存在冲突问题 我这个仓库地址下载后的本地路径是:D:\Projects\Tasks 然后我在另外一个地方新建了一个bat文件: bat文件所在目录为&#xff1a…

【PyTorch 卷积】实战自定义的图片归类

前言 卷积神经网络是一类包含卷积计算且具有深度结构的前馈神经网络,是深度学习的代表算法之一,它通过卷积层、池化层、全连接层等结构,可以有效地处理如时间序列和图片数据等。关于卷积的概念网络上也比较多,这里就不一一描述了。…

c++之类和对象

首先我们要理解cin,cout只能自动识别内置类型,原因就是因为cin,cout里面的函数重载。 那么如果我想输入非内置类型,就要进行运算符重载。 但是会发生如下的情况。 友元函数可以访问对象的私有。 运算符重载的总结 成员初始化既可以用函数体内初始化也可…

docker部署minio并使用springboot连接

需求:工作中,在微信小程序播放时,返回文件流并不能有效的使用,前端需要一个可以访问的地址,springboot默认是有资源拦截器的,但是不适合生产环境的使用 可以提供使用的有例如fastdfs或者minio,这…

【Linux】安装配置解决CentosMobaXterm的使用及Linux常用命令以及命令模式

目录 Centos的介绍 centos安装配置&MobaXterm 创建 安装 ​编辑 配置 ​编辑 MobaXterm使用 Linux常用命令&模式 常用命令 vi或vim编辑器 三种模式 命令模式 编辑模式 末行模式 拍照备份 Centos的介绍 CentOS(Community Enterprise Op…

软件测试面试,一定要准备的7个高频面试题(附答案,建议收藏)

问题1:请自我介绍下? 核⼼要素:个⼈技能优势⼯作背景经验亮点参考回答: 第一种:基本信息离职理由 ⾯试官您好,我叫张三,来⾃番茄市,在软件测试⾏业有 3 年的⼯作经验。做过 Web/APP…

无需编程技术,快速搭建个人网站

如果你想拥有一个属于自己的个人网站,但又没有任何编程经验,别担心,我们今天将为你介绍一个简单的方法,让你轻松搭建网站,无需任何编程知识。让我们一起来看看吧! 在乔拓云建站工具中,自带了许多…

图纸管理制度《八》设计图纸管理制度

第一章 总则 第1条 目的。为做好设计图纸的管理工作,使其收发及时、手续齐全、废图绝迹、不遗失、无差错,特制定本办法。 第2条 适用范围。本办法适用于企业所有工程项目的图纸管理工作。 第3条 相关部门及人员职责 (1) 工程技术部负责图纸管理的监督…

0基础学习PyFlink——个数滑动窗口(Sliding Count Windows)

大纲 滑动(Sliding)和滚动(Tumbling)的区别样例窗口为2,滑动距离为1窗口为3,滑动距离为1窗口为3,滑动距离为2窗口为3,滑动距离为3 完整代码参考资料 在 《0基础学习PyFlink——个数…

Explaining and harnessing adversarial examples

Explaining and harnessing adversarial examples----《解释和利用对抗样本》 背景: 早期的研究工作认为神经网络容易受到对抗样本误导是由于其非线性特征和过拟合。 创新点: 该论文作者认为神经网络易受对抗性扰动影响的主要原因是它的线性本质&#xf…

stm32 模拟I2C

目录 简介 I2C 物理层 协议层 ①②:起始信号和结束信号 ③ 应答和非应答信号 ④数据有效性 ⑤数据传输 ⑥空闲状态 简介 I2C 物理层 一个 I2C 总线两条线组成,一个双向串行数据线SDA用来表示数据,一个串行时钟线SCL用于数据收发同步…

5个最流行的文本生成纹理AI工具

在线工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 3D场景编辑器 拥抱文本生成纹理AI模型改变游戏规则的力量,人工智能驱动的创新彻底改变了游戏开发中的资产创建。 这些出色的工具可将书面描述转换…

《Generic Dynamic Graph Convolutional Network for traffic flow forecasting》阅读笔记

论文标题 《Generic Dynamic Graph Convolutional Network for traffic flow forecasting》 干什么活:交通流预测(traffic flow forecasting )方法:动态图卷积网络(Dynamic Graph Convolutional Network)…

Ubuntu 使用 nginx 搭建 https 文件服务器

Ubuntu 使用 nginx 搭建 https 文件服务器 搭建步骤安装 nginx生成证书修改 config重启 nginx 搭建步骤 安装 nginx生成证书修改 config重启 nginx 安装 nginx apt 安装: sudo apt-get install nginx生成证书 使用 openssl 生成证书: 到对应的路径…

【Mybatis-Plus】常见的@table类注解

目录 引入Mybatis-Plus依赖 TableName 当实体类的类名在转成小写后和数据库表名相同时 当实体类的类名在转成小写后和数据库表名不相同时 Tableld TableField 当数据库字段名与实体类成员不一致 成员变量名以is开头,且是布尔值 ​编辑 成员变量名与数据库关…