热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

神经网络基础学习笔记(三)神经网络的学习

前言:上一章讲了神经网络前向传播内容,这一章讲如何根据数据训练出相关权重参数的过程。我们在实战中直接得出了参数权重,接下爱我们要学习4.1从数据中学习介绍神经网络的学习,即利用数据

目录

前言:


4.1从数据中学习

4.1.1数据驱动

4.1.2训练数据和测试数据

4.2损失函数

4.2.1均方误差

4.2.2交叉熵误差

4.2.3mini-batch学习

4.2.5为什么要设定损失函数

4.3数值微分

4.3.1导数

4.3.2一个微分的例子

4.3.3偏导数

4.4梯度

4.4.1梯度法

4.4.2神经网络的梯度

4.5 学习算法的实现

4.5.1 2层神经网络的类

4.5.2 mini-batch的实现

4.5.3 基于测试数据的评价

小结:



前言:

上一章讲了神经网络前向传播内容,这一章讲如何根据数据训练出相关权重参数的过程。我们在实战中直接得出了参数权重,接下爱我们要学习

4.1从数据中学习

介绍神经网络的学习,即利用数据决定参数值的方法。我们将针对上一个实验的训练集进行学习

4.1.1数据驱动

图像的特征量通常表示为向量的形式。

前面学习过分类算法SVM以及KNN,我们手动提取特征向量。

深 度 学 习 有 时 也 称 为 端 到 端 机 器 学 习(end-to-end machine learning)。这里所说的端到端是指从一端到另一端的意思,也就是 从原始数据(输入)中获得目标结果(输出)的意思。

神经网络的优点是对所有的问题都可以用同样的流程来解决。

4.1.2训练数据和测试数据

1.训练数据和测试数据:训练数据用来训练模型的,而测试数据就是不包含在训练模型内的数据用来评判训练后模型好坏的数据

2.泛化能力:如果测试的成绩好那么他的泛化能力就好。

3.过拟合:适应训练数据强,但泛化能力弱。

4.2损失函数

神经网络的学习的目的就是以该损失函数为基准,找出能使它 的值达到最小的权重参数

种评判方法均方误差交叉熵误差

4.2.1均方误差

实现代码:

4.2.2交叉熵误差

交叉熵误差的值是由正确解标签所对应的输出结果决定的

实现代码:

4.2.3mini-batch学习

单个单个计算的话,数据处理时间过长,我们希望时间大部分花费咋计算上面。计算所有数据的(损失函数值的和/总数)的平均损失函数值

分析上一个实验的数据包

随机抽取10笔

为了找到使损失函数的值尽可能小的地方,需要计算参数的导数(确切地讲是梯度),然后以这个导数为指引,
逐步更新参数的值。

4.2.5为什么要设定损失函数

因为损失函数可导且连续,便于调试。

以一个例子,比如有100个训练数据进行测试,发现精度为32%,如果以识别精度为指标,那么稍微修改权重参数精度也只会是32%,稍微改动大一点点权重参数精度可能直接变为33%,这种是离散不连续的变化;而损失函数不一样,稍微改变权重关系时,损失函数值就会立刻改变(如0.9524变为0.9612),这种值是连续性的,因为离散型的变化其导数(斜率)一般都为0,而连续型的变化导数一般不为0,所以能很容易判别出权重参数变化时的模型好坏。

4.3数值微分


4.3.1导数

 

1.10e-50精度会有误差,比如python的float精度为小数点后4位,这里已经是50位了,所以要改成10e-4 舍入误差

2.f(x+h)-f(x)/h(向前差分)这个误差也很大,因为根据1的改变,h不是一个趋近于0的数,所以误差变大,应该用中心法改成f(x+h)-f(x-h)/2h(中心差分)

利用微小的差分求导数的过程称为数值微分(numerical  differentiation)

数值微分数值梯度

改进后代码

中值定理的感觉

注意:

这种利用微小差分的导数过程为数值微分,而用数学公式推导的如y=x²导数为y=2x这种交解析性求导,这种叫做真导数

4.3.2一个微分的例子

如y=0.01x²+0.1x的导数实现

可以发现改进后的微分代码误差非常小

数值微分代码:

4.3.3偏导数

比如实现的偏导数

先看这个函数的代码实现与图像:

偏导数实现:原理其实跟一元导数一样,就是带入一个真值消除一个变量而已

公式难在数值微分,肉眼偏导验算一下,第一条公式为2*X0

4.4梯度

在刚才的例子中,我们按变量分别计算了x0和x1的偏导数。现在,我 们希望一起计算x0和x1的偏导数。比如

比如我们求一个函数y=x0²+x1²变量有x0,x1,当我们对他全部变量(这里最多只有2个)进行偏导汇总而成的变量叫梯度。

梯度指向的图

从这个图可以看出,梯度指向的点的函数值越来越小,反之越来越大,这是梯度重要性质!

4.4.1梯度法

寻找最小值的梯度法称为梯度下降法(gradient descent method), 寻找最大值的梯度法称为梯度上升法(gradient ascent method)。

神经网络(深度学习)中,梯度法主要是指梯度下降法

从上面的梯度我们可以知道梯度其实就是寻找梯度为0的地方,但是梯度为0不一定是最小值(高数里的靶点),他可能是极小值或者是鞍点(某方向看是极小值,另一方向看是极大值,导数为0的点),所以我们可以计算一次梯度后再次计算一次梯度,这样最后就能找到真正的最小值点了,这就是梯度法。

学习率决定在一次学习中,应该学习多少,以及在多大程度上更新参数

注意:找最小其实跟找最大是一样的,就是取负的问题而已,不用太在意这个。

(梯度下降法)代码实现:

numerical_gradient(f,x)会求函数的梯度,用该梯度乘以学习率得到的值进行更新操作,由step_num指定重复的 次数。

这个例子中得到的最后的x值都是非常小的数,都几乎趋向于0,根据解析式方式(自己动笔试试)我们知道最小值为(0,0),跟上面的例子几乎一致(实际的例子中最小值不一定是0)。

每次求导后的过程:

实现代码:

# coding: utf-8
import numpy as np
import matplotlib.pylab as plt
from gradient_2d import numerical_gradient #求梯度,原理与数值微分相同
#梯度下降法
def gradient_descent(f, init_x, lr=0.01, step_num=100):
x = init_x
x_history = []
for i in range(step_num):
# 记录前一个x,用于绘图痕迹
x_history.append( x.copy() )
# 梯度下降法,为梯度乘以学习率
grad = numerical_gradient(f, x)
x -= lr * grad
return x, np.array(x_history)
# 求偏导,np.sum(x**2)
def function_2(x):
return x[0]**2 + x[1]**2
init_x = np.array([-3.0, 4.0])
# 学习率为0.1
lr = 0.1
# 梯度法的重复次数
step_num = 20
x, x_history = gradient_descent(function_2, init_x, lr=lr, step_num=step_num)
plt.plot( [-5, 5], [0,0], '--b')
plt.plot( [0,0], [-5, 5], '--b')
plt.plot(x_history[:,0], x_history[:,1], 'o')
plt.xlim(-3.5, 3.5)
plt.ylim(-4.5, 4.5)
plt.xlabel("X0")
plt.ylabel("X1")
plt.show()

 

这里有个学习率太大  太小的例子:

太大时结果会发散成很大的数,太小的话结果几乎没更新就结束了

所以学习率n太大太小都不好学习率被称为超参数,一般认为多次设定后取一个合理值

学习率这样的参数称为超参数。

相对于神经网络的权重参数是通过训练 数据和学习算法自动获得的,学习率这样的超参数则是人工设定的。

4.4.2神经网络的梯度

所说的梯度是指损失函数关于权重参数的梯度

如图,我们有2*3的W权重参数,L为损失函数,梯度用表示,如图:

为simpleNet的类(源代码在ch04/gradient_simplenet.py 中

代码实现:

# coding: utf-8
import sys, os
sys.path.append(os.pardir) # 为了导入父目录中的文件而进行的设定
import numpy as np
from common.functions import softmax, cross_entropy_error
from common.gradient import numerical_gradient
class simpleNet:
def __init__(self):
# 初始化2*3权重参数
self.W = np.random.randn(2,3)
def predict(self, x):
# 一层 权重乘以变量 == 一层感知机
return np.dot(x, self.W)
def loss(self, x, t):
# 计算交叉熵softmax()函数的损失值
z = self.predict(x)
y = softmax(z)
loss = cross_entropy_error(y, t)
return loss
x = np.array([0.6, 0.9])
t = np.array([0, 0, 1])
net = simpleNet()
f = lambda w: net.loss(x, t)
dW = numerical_gradient(f, net.W)
print(dW)




来自-优秀的方同学:
https://me.csdn.net/qq_37431224





来自-优秀的方同学:
https://me.csdn.net/qq_37431224


4.5 学习算法的实现


随机梯度下降法(stochastic gradient descent)。“随机”指的是“随机选择的” 的意思,因此,随机梯度下降法是“对随机选择的数据进行的梯度下降法”。简称SGD

实现代码:

4.5.1 2层神经网络的类

two_layer_net:

# coding: utf-8
import sys, os
sys.path.append(os.pardir) # 为了导入父目录的文件而进行的设定
from common.functions import *
from common.gradient import numerical_gradient
class TwoLayerNet:
"""
从第1个参数开始,依次表示:
输入层的神经元数、隐藏层的神经元数、输出层的神经元数
输入图像大小784 输出10个数字(0-9)
"""
def __init__(self, input_size, hidden_size, output_size, weight_init_std=0.01):
# 初始化权重,是有要求的但是后面在补上
self.params = {}
# params变量中保存了该神经网络所需的全部参数
self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size)
self.params['b1'] = np.zeros(hidden_size)
self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size)
self.params['b2'] = np.zeros(output_size)
def predict(self, x):
W1, W2 = self.params['W1'], self.params['W2']
b1, b2 = self.params['b1'], self.params['b2']

a1 = np.dot(x, W1) + b1
z1 = sigmoid(a1)
a2 = np.dot(z1, W2) + b2
y = softmax(a2)

return y

# x:输入数据, t:监督数据
def loss(self, x, t):
y = self.predict(x)
return cross_entropy_error(y, t)

def accuracy(self, x, t):
y = self.predict(x)
y = np.argmax(y, axis=1)
t = np.argmax(t, axis=1)

accuracy = np.sum(y == t) / float(x.shape[0])
return accuracy

# x:输入数据, t:监督数据
# numerical_gradient(self, x, t)
# 基于数值微分计算参数的梯度。
def numerical_gradient(self, x, t):
loss_W = lambda W: self.loss(x, t)

grads = {}
grads['W1'] = numerical_gradient(loss_W, self.params['W1'])
grads['b1'] = numerical_gradient(loss_W, self.params['b1'])
grads['W2'] = numerical_gradient(loss_W, self.params['W2'])
grads['b2'] = numerical_gradient(loss_W, self.params['b2'])

return grads
# 使用误差反向传播法计算梯度
def gradient(self, x, t):
W1, W2 = self.params['W1'], self.params['W2']
b1, b2 = self.params['b1'], self.params['b2']
grads = {}

batch_num = x.shape[0]

# forward
a1 = np.dot(x, W1) + b1
z1 = sigmoid(a1)
a2 = np.dot(z1, W2) + b2
y = softmax(a2)

# backward
dy = (y - t) / batch_num
grads['W2'] = np.dot(z1.T, dy)
grads['b2'] = np.sum(dy, axis=0)

da1 = np.dot(dy, W2.T)
dz1 = sigmoid_grad(a1) * da1
grads['W1'] = np.dot(x.T, dz1)
grads['b1'] = np.sum(dz1, axis=0)
return grads

 

 

4.5.2 mini-batch的实现

类:train_neuralnet:

# coding: utf-8
import sys, os
sys.path.append(os.pardir) # 为了导入父目录的文件而进行的设定
import numpy as np
import matplotlib.pyplot as plt
from dataset.mnist import load_mnist
from two_layer_net import TwoLayerNet
# 读入数据
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)
network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10)
# 超参数
iters_num = 10000 # 适当设定循环的次数
train_size = x_train.shape[0]
batch_size = 100
learning_rate = 0.1
train_loss_list = []
train_acc_list = []
test_acc_list = []
iter_per_epoch = max(train_size / batch_size, 1)
for i in range(iters_num):
# 获取mini-batch
batch_mask = np.random.choice(train_size, batch_size)
x_batch = x_train[batch_mask]
t_batch = t_train[batch_mask]

# 计算梯度
#grad = network.numerical_gradient(x_batch, t_batch)
# 高速版
grad = network.gradient(x_batch, t_batch)

# 更新参数
for key in ('W1', 'b1', 'W2', 'b2'):
network.params[key] -= learning_rate * grad[key]
# 记录学习过程
loss = network.loss(x_batch, t_batch)
train_loss_list.append(loss)

if i % iter_per_epoch == 0:
train_acc = network.accuracy(x_train, t_train)
test_acc = network.accuracy(x_test, t_test)
train_acc_list.append(train_acc)
test_acc_list.append(test_acc)
print("train acc, test acc | " + str(train_acc) + ", " + str(test_acc))
# 绘制图形
markers = {'train': 'o', 'test': 's'}
x = np.arange(len(train_acc_list))
plt.plot(x, train_acc_list, label='train acc')
plt.plot(x, test_acc_list, label='test acc', line)
plt.xlabel("epochs")
plt.ylabel("accuracy")
plt.ylim(0, 1.0)
plt.legend(loc='lower right')
plt.show()

可以发现随着学习的进行,损失函数的值在不断减小。这 是学习正常进行的信号,表示神经网络的权重参数在逐渐拟合数据。也就是 说,神经网络的确在学习!通过反复地向它浇灌(输入)数据,神经网络正 在逐渐向最优参数靠近。

实线表示训练数据的识别精度,虚线表示测试数据的识别精 度

4.5.3 基于测试数据的评价

光看这个结果还不能说明该神经网络在 其他数据集上也一定能有同等程度的表现。

神经网络的学习中,必须确认是否能够正确识别训练数据以外的其他数 据,即确认是否会发生过拟合。

要评价神经网络的泛 化能力,就必须使用不包含在训练数据中的数据

 epoch是一个单位。一个 epoch表示学习中所有训练数据均被使用过 一次时的更新次数。比如,对于 10000笔训练数据,用大小为 100 笔数据的mini-batch进行学习时,重复随机梯度下降法 100次,所 有的训练数据就都被“看过”了A。此时,100次就是一个 epoch。

代码在上面:

之所以要计算每一个epoch的识别精度,是因 为如果在for语句的循环中一直计算识别精度,会花费太多时间

没有必要那么频繁地记录识别精度(只要从大方向上大致把握识别精度的推 移就可以了

小结:

本章所学的内容


  • 机器学习中使用的数据集分为训练数据和测试数据

  • 神经网络用训练数据进行学习,并用测试数据评价学习到的模型的 泛化能力。 

  • 神经网络的学习以损失函数为指标,更新权重参数,以使损失函数的值减小。

  • 利用某个给定的微小值的差分求导数的过程,称为数值微分

  • 利用数值微分,可以计算权重参数的梯度

  • 数值微分虽然费时间,但是实现起来很简单。

需要注意的时候,你会觉得比较多内容这一章,建议书写一下
 






























名称 函数
数值微分 numerical_diff(x)
偏导数

function_2(x)

偏导数
梯度 numerical_gradient(f,x)
梯度下降法 gradient_descent(f, init_x, lr=0.01, step_num=100)

下一章中要实现的稍 微复杂一些的误差反向传播法可以高速地计算梯度。


推荐阅读
  • YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程
    本文介绍了关于人工智能、神经网络和深度学习的知识点,并提供了YOLOv7基于自己的数据集从零构建模型完整训练、推理计算的详细教程。文章还提到了郑州最低生活保障的话题。对于从事目标检测任务的人来说,YOLO是一个熟悉的模型。文章还提到了yolov4和yolov6的相关内容,以及选择模型的优化思路。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 也就是|小窗_卷积的特征提取与参数计算
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了卷积的特征提取与参数计算相关的知识,希望对你有一定的参考价值。Dense和Conv2D根本区别在于,Den ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
  • 本博文基于《Amalgamationofproteinsequence,structureandtextualinformationforimprovingprote ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 本文介绍了机器学习手册中关于日期和时区操作的重要性以及其在实际应用中的作用。文章以一个故事为背景,描述了学童们面对老先生的教导时的反应,以及上官如在这个过程中的表现。同时,文章也提到了顾慎为对上官如的恨意以及他们之间的矛盾源于早年的结局。最后,文章强调了日期和时区操作在机器学习中的重要性,并指出了其在实际应用中的作用和意义。 ... [详细]
  • 本文讨论了一个数列求和问题,该数列按照一定规律生成。通过观察数列的规律,我们可以得出求解该问题的算法。具体算法为计算前n项i*f[i]的和,其中f[i]表示数列中有i个数字。根据参考的思路,我们可以将算法的时间复杂度控制在O(n),即计算到5e5即可满足1e9的要求。 ... [详细]
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
  • 本文介绍了在Python张量流中使用make_merged_spec()方法合并设备规格对象的方法和语法,以及参数和返回值的说明,并提供了一个示例代码。 ... [详细]
  • Learning to Paint with Model-based Deep Reinforcement Learning
    本文介绍了一种基于模型的深度强化学习方法,通过结合神经渲染器,教机器像人类画家一样进行绘画。该方法能够生成笔画的坐标点、半径、透明度、颜色值等,以生成类似于给定目标图像的绘画。文章还讨论了该方法面临的挑战,包括绘制纹理丰富的图像等。通过对比实验的结果,作者证明了基于模型的深度强化学习方法相对于基于模型的DDPG和模型无关的DDPG方法的优势。该研究对于深度强化学习在绘画领域的应用具有重要意义。 ... [详细]
  • 本文介绍了使用Spark实现低配版高斯朴素贝叶斯模型的原因和原理。随着数据量的增大,单机上运行高斯朴素贝叶斯模型会变得很慢,因此考虑使用Spark来加速运行。然而,Spark的MLlib并没有实现高斯朴素贝叶斯模型,因此需要自己动手实现。文章还介绍了朴素贝叶斯的原理和公式,并对具有多个特征和类别的模型进行了讨论。最后,作者总结了实现低配版高斯朴素贝叶斯模型的步骤。 ... [详细]
  • [echarts] 同指标对比柱状图相关的知识介绍及应用示例
    本文由编程笔记小编为大家整理,主要介绍了echarts同指标对比柱状图相关的知识,包括对比课程通过率最高的8个课程和最低的8个课程以及全校的平均通过率。文章提供了一个应用示例,展示了如何使用echarts制作同指标对比柱状图,并对代码进行了详细解释和说明。该示例可以帮助读者更好地理解和应用echarts。 ... [详细]
  • 本文介绍了利用ARMA模型对平稳非白噪声序列进行建模的步骤及代码实现。首先对观察值序列进行样本自相关系数和样本偏自相关系数的计算,然后根据这些系数的性质选择适当的ARMA模型进行拟合,并估计模型中的位置参数。接着进行模型的有效性检验,如果不通过则重新选择模型再拟合,如果通过则进行模型优化。最后利用拟合模型预测序列的未来走势。文章还介绍了绘制时序图、平稳性检验、白噪声检验、确定ARMA阶数和预测未来走势的代码实现。 ... [详细]
  • 我用Tkinter制作了一个图形用户界面,有两个主按钮:“开始”和“停止”。请您就如何使用“停止”按钮终止“开始”按钮为以下代码调用的已运行功能提供建议 ... [详细]
author-avatar
feixiang1563122
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有