找回密码
 立即注册
搜索

Python机器学习-知识点汇总

1,什么样的材料集不合适用深度学习?
    数据集太小,数据样本不足时,深度学习相对其它机器学习算法,没有分明优势。数据集没有部分相关特性,目前深度学习表现比较好的范畴次要是图像/语音/自然言语处理等范畴,这些范畴的一个共性是部分相关性。图像中像素组成物体,语音信号中音位组合成单词,文本数据中单词组合成句子,这些特征元素的组合一旦被打乱,表示的含义同时也被改变。对于没有这样的部分相关性的数据集,不适于运用深度学习算法停止处理。举个例子:预测一个人的健康状况,相关的参数会有年龄、职业、支出、家庭状况等各种元素,将这些元素打乱,并不会影响相关的结果。
2,softmax函数的数学推导及Python完成


  softmax用于多分类过程中最后一层,将多个神经元的输入,映射到(0, 1)区间内,可以看成概率来了解,从而来停止多分类!

  softmax函数如下:

  更笼统的如下图表示:

  softmax 直白来说就是讲原来输入是 3, 1, -3 经过 softmax 函数一作用,就映射成为(0, 1)的值,而这些值的累和为1,那么我们就可以将其了解成概率,在最后选取输入节点的时分,我们可以选取概率最大的节点,作为我们的预测目的!

  Python代码完成:

# _*_coding:utf-8_*_

import tensorflow as tf

import numpy as np

import math

# softmax函数,或称归一化指数函数

def softmax(x, axis=1):

# 为了避免求 exp(x) 出现溢出的状况,普通需求减去最大值

# 计算每行的最大值

row_max = x.max(axis=axis)

# 每行元素都需求减去对应的最大值,否则求exp(x)会溢出,导致INF状况

row_max = row_max.reshpae(-1, 1)

x = x - row_max

x_exp = np.exp(x)

# 假如是列向量,则axis=0

x_sum = np.sum(x_exp, axis=1, keepdims=True)

s = x_exp / x_sum

return s

# 简单一些

def softmax(x):

"""Compute softmax values for each sets of scores in x."""

e_x = np.exp(x - np.max(x))

return e_x / e_x.sum()

# 运用 tf的softmax函数

with tf.Session() as sess:

tf_s2 = tf.nn.softmax(x, axis=axis)

s2 = sess.run(tf_s2)

  下面我们分析一下,减去最大值和不减去最大值能否有必要吗?首先看代码:

import numpy as np

def softmax(x):

"""Compute softmax values for each sets of scores in x."""

e_x = np.exp(x - np.max(x))

return e_x / e_x.sum()

def softmax1(x):

"""Compute softmax values for each sets of scores in x."""

return np.exp(x) / np.sum(np.exp(x), axis=0)

scores = [3.0, 1.0, 0.2]

print(softmax(scores))

print(softmax1(scores))

'''

结果输入如下:

[0.8360188 0.11314284 0.05083836]

[0.8360188 0.11314284 0.05083836]

'''

  其实两个结果输入是一样的,即便第一个完成了每列和最大值的差异,然后除以总和,但是成绩来了,实如今代码和工夫复杂度方面能否相似?哪一个更有效率?

  当然,他们都是正确的,但是从数值波动性的角度来看,第一个是正确的,由于我们避免了求 exp(x) 出现溢出的状况,这里减去了最大值。我们推导一下:

# 转化公式: a ^(b – c)=(a ^ b)/(a ^ c)

e ^ (x - max(x)) / sum(e^(x - max(x))

= e ^ x / (e ^ max(x) * sum(e ^ x / e ^ max(x)))

= e ^ x / sum(e ^ x)

  
3,欧氏间隔和曼哈顿间隔


  欧氏间隔(也称为欧几里得度量),是运用勾股定理计算两个点之间的直线间隔,也就是指m维空间两个点之间的真实间隔,或者向量的自然长度(即该点到原点的间隔)。

  下面是欧式间隔的公式(分别是二维空间,三维空间,n维空间):



  曼哈顿间隔表示的是两个点在标准坐标系上相对轴距之和,是种运用在几何度量空间的几何学用语。

  例如在平面上,坐标(x1, y1)的i点与坐标(x2, y2)的j点的曼哈顿间隔为:

d(i,j)=|X1-X2|+|Y1-Y2|

  如图所示,很直接明了的了解欧氏间隔和曼哈顿间隔:

  图中红线代表曼哈顿间隔,绿色代表欧氏间隔,也就是直线间隔,而蓝色和黄色代表等价的曼哈顿间隔。

  欧氏间隔和曼哈顿间隔的Python完成:

import numpy as np

def manhattan_distance(vec1, vec2):

"""

This method implements the manhattan distance metric

:param p_vec: vector one

:param q_vec: vector two

:return: the manhattan distance between vector one and two

"""

return np.sum(np.fabs(vec1 - vec2))

def edclidean_distance(vec1, vec2):

"""

This method implements the edclidean distance metric

:param vec1: vector one

:param vec2: vector two

:return: the edclidean distance between vector one and two

"""

# 方法一

distance = np.sqrt(np.sum(np.square(vec1 - vec2)))

# method 2

dist = np.linalg.norm(vec1 - vec2)

return distance

  
4,什么是数据埋点


  数据埋点我们可以分为两类,其一是页面统计,其二是行为统计。

  页面统计可以帮我们知晓某个页面被多少人访问了多少次,行为统计是指用户在界面上的操作行为,运用最多的是按钮的点击次数。
5,请简要说说一个残缺的机器学习项目流程

5.1:笼统成数学成绩


  明白成绩是停止机器学习的第一步。机器学习的训练过程通常都是一件非常耗时的事情,胡乱尝试工夫成本是非常高的。  这里的笼统成数学成绩,指的我们明白我们可以获得什么样的数据,目的是一个分类还是回归或者是聚类的成绩,假如都不是的话,假如划归为其中的某类成绩。
5.2:获取数据


  数据决议了机器学习结果的下限,而算法只是尽能够逼近这个下限。数据要有代表性,否则必然会过拟合。而且对于分类成绩,数据偏斜不能过于严重,不同类别的数据数量不要有数个数量级的差距。

  而且还要对数据的量级有一个评价,多少个样本,多少个特征,可以估算出其对内存的耗费程度,判别训练过程中内存能否可以放得下。假如放不下就得思索改进算法或者运用一些降维的技巧了。假如数据量真实太大,那就要思索分布式了。
5.3 特征预处理与特征选择


  良好的数据要可以提取出良好的特征才能真正发挥效能。

  特征预处理、数据清洗是很关键的步骤,往往可以使得算法的效果和功能得到分明提高。归一化、团圆化、因子化、缺失值处理、去除共线性等,数据发掘过程中很多工夫就花在它们下面。这些工作简单可复制,收益波动可预期,是机器学习的基础必备步骤。  挑选出分明特征、摒弃非分明特征,需求机器学习工程师反复了解业务。这对很多结果有决议性的影响。特征选择好了,非常简单的算法也能得出良好、波动的结果。这需求运用特征有效性分析的相关技术,如相关系数、卡方检验、平均互信息、条件熵、后验概率、逻辑回归权重等方法。
5.4:训练模型与调优


  直到这一步才用到我们下面说的算法停止训练。如今很多算法都可以封装成黑盒供人运用。但是真正考验程度的是调整这些算法的(超)参数,使得结果变得愈加优秀。这需求我们对算法的原理有深化的了解。了解越深化,就越能发现成绩的症结,提出良好的调优方案。
5.5:模型诊断


  如何确定模型调优的方向与思绪呢?这就需求对模型停止诊断的技术。  过拟合、欠拟合判别是模型诊断中至关重要的一步。常见的方法如交叉验证,绘制学习曲线等。过拟合的基本调优思绪是添加数据量,降低模型复杂度。欠拟合的基本调优思绪是提高特征数量和质量,添加模型复杂度。  误差分析 也是机器学习至关重要的步骤。经过观察误差样本,片面分析误差产生误差的缘由:是参数的成绩还是算法选择的成绩,是特征的成绩还是数据本身的成绩……  诊断后的模型需求停止调优,调优后的新模型需求重新停止诊断,这是一个反复迭代不断逼近的过程,需求不断地尝试, 进而达到最优形状。
5.6:模型交融


  普通来说,模型交融后都能使得效果有一定提升。而且效果很好。  工程上,次要提升算法准确度的方法是分别在模型的前端(特征清洗和预处理,不同的采样形式)与后端(模型交融)上下功夫。由于他们比较标准可复制,效果比较波动。而直接调参的工作不会很多,毕竟大量数据训练起来太慢了,而且效果难以保证。
5.7:上线运转


  这一部分内容次要跟工程完成的相关性比较大。工程上是结果导向,模型在线上运转的效果直接决议模型的成败。 不单纯包括其准确程度、误差等状况,还包括其运转的速度(工夫复杂度)、资源耗费程度(空间复杂度)、波动功能否可接受。  这些工作流程次要是工程实际上总结出的一些阅历。并不是每个项目都包含残缺的一个流程。这里的部分只是一个指点性的阐明,只要大家本人多实际,多积累项目阅历,才会有本人更深入的看法。
6,全衔接神经网络网络结构


  (此题参考:https://blog.csdn.net/cuiyuan605/article/details/84307323)

  神经网络算法,是运用计算机模拟生物神经系统,来模拟人类思想方式的算法。它的基本单位就是人工神经元。经过互相衔接构成一张神经网络。对于神经网络有些了解的盆友能够都知道,神经网络其实就是一个输入 X(向量) 到输入 Y(向量)的映射函数:f(x) = Y,函数的系数就是我们所要训练的网络参数 W,只需函数系数确定上去,对于任何输入xi,我们就能得到一个与之对应的输入 yi,至于 yi 能否符合我们的预期,这就是输入如何提高模型功能方面的成绩。

  生物神经网络中,每个神经元与其他神经元衔接,当它“激活”时,会传递化学物质到相连的神经元,改变其他神经元的电位,当电位达到一定“阈值”,那么这个神经元也会被激活。

  单个人工神经元的计算公式如下:

  其中:

  

为输入参数向量,表示其他神经元输入的信号。

  

为每个输入参数的权重值,表示对应神经元信号的权重。

  theta 为阈值或者偏向值,是指该激活神经元的难易程度。

  y 为神经元的输入值,表示该神经元能否被激活。

  Act() 为激活函数,理想的激活函数如下图(a)中的跃阶函数,“1” 为神经元兴奋,“0”为神经元抑制,但由于跃阶函数具有不是延续可导等不好的性质,因此普通采用下面(b) 图的 Sigmoid 函数作为激活函数:

  下面定义一个全衔接神经网络:

  全衔接神经网络,就是指每一层的每个神经元都和下一层的每个神经元项衔接。

  Layer:0 为输入层

  Layer:L 为输入层

  其他L-1 个Layer 为隐层

  输入 x :

,我们称一个输入值 x 为一个样本

  输入 y :

,变量的上标(L)表示该变量出于神经网络的那一层。

  

表示第 L 层编号为 i 的神经元

  

表示第 L 层的神经元数量

7,全衔接神经网络的前向传播


  前向传播比较简单,就是向量点乘,也就是加权求和,然后经过一个激活函数。也就是网络如何根据输入 X 得到输入 Y的。

  记

为第 l-1 层第 k个神经元到第 l 层第 j 个神经元的权重,

为第 l 层 第 j 个神经元的偏置,

为第 l 层第 j 个神经元的激活值(激活函数的输入)。不好看出

的值取决于上一层神经元的激活:

  将下面重写为矩阵方式:

  为了方便表示,记

为每一层权重输入,矩阵方式则变为

  应用矩阵方式可以一层层计算网络的激活值,最终能根据输入X 得到相应的输入


8,随机梯度下降法


(此题参考:https://blog.csdn.net/qq_38150441/article/details/80533891 和 https://blog.csdn.net/qq_39037383/article/details/89156894)

  梯度下降算法的思想就是根据人类在渐进学习中,不断从错误中纠副本人的认知的过程中感触到的。
8.1 梯度下降


  简单来说,梯度下降就是从山顶找一条最短的路走到山底最低的地方。但是由于选择方向的缘由,我们找到的最低点能够不是真正的最低点。如图所示,黑色标注的道路所指的方向并不是真正的地方。(由于梯度下降是一种思想,没有严厉的定义,所以用一个比喻来解释什么是梯度下降)

  既然是选择一个方向下山,那么这个方向该如何选?每次该怎样走?

  先说选的方向,在算法中是以随机方式给出的,这也是形成有时分走不到真正最低点的缘由。假如选定了方向,当前每走一步,都选择的时最陡的方向,直到最低点。总结起来就是:随机选择一个方向,然后每次都选择最陡的方向,直到这个方向上能达到的最低点。

  在机器学习算法中,有时分需求对原始的模型构建损失函数,然后经过优化算法对损失函数停止优化,以便寻觅到最优的参数,使得损失函数的值最小。而求解机器学习参数的优化算法中,运用最多的就是基于梯度下降的优化算法(Gradient Descent GD)。

  梯度下降的优缺陷
    优点:效率。在梯度下降法的求解过程中,只需求解损失函数的一阶导数,计算的代价比较小,可以在很多大规模数据集上运用。缺陷:求解的时部分最优值,即由于方向选择的成绩,得到的结果不一定是全局最优步长选择,过小使得函数收敛速度慢,过大又容易找不到最优解。
8.2 随机梯度下降


  随机梯度下降(SGD)是一种简单但非常有效地方法,多用于支持向量机,逻辑回归等凸损失函数下的线性分类器的学习。并且SGD曾经成功运用于文本分类和自然言语处理中常常遇到的大规模和稀疏机器学习成绩。SGD 既可以用于分类计算,也可以用于回归计算。

  随机梯度下降法不是对每个样本集停止求梯度更新参数,而是对一个或者多个样本停止求梯度,更新参数,采集多个样本为样本集再停止如下操作:

1.初始化参数为恣意值(可以取到面上恣意一点)

2.对样本集里每个样本停止遍历如下操作

1.求解梯度值

2.更新参数

3.若达到指定迭代次数或者收敛条件,则训练结束

  随机梯度下降法不同于批量梯度下降,随机梯度下降是每次迭代运用一个样本来对参数停止更新。使得训练速度加快。

  对于一个样本的目的函数为:

  对目的函数求偏导:

  参数更新:

  随机梯度下降的优缺陷:
    优点:由于不是在全部训练数据上的损失函数,而是在每轮迭代中,随机优化某一条训练数据上损失函数,这样每一轮参数的更新速度大大加快。缺陷:准确度下降,由于即便在目的函数为强凸函数的状况下,SGD依旧无法做到线性收敛。能够会收敛到部分最优,而单个样本并不能代表全体样本的趋向,而且不易于并行完成。
9,LR的原理和Loss的推导


  首先,LR是一个分类模型,讨论二分类状况下,在这个基础上我们假设样本服从伯努利分布(0~1)分布。做了假设分布后下一步就是求分布参数,这个过程普通采用极大似然估计MLE(Maximum Likelihood Estimation),详细的方法就是求该假设分布在训练样本上的结合概率(样本带入连乘),然后求其关于 theta 的最大值,为了方便计算所以普通取 -log,单调性保持不变,一切就有了 logLoss: L(Y, P(Y|X)) = - logP(Y|X)。

10,机器学习中,为何要常常对数据做归一化


  (参考文献:https://blog.csdn.net/abc_138/article/details/82798674)

  普通做机器学习运用的时分大部分工夫是花费在特征处理上,其中很关键的一步就是对特征数据停止归一化。

  首先要明白归一化的目的是什么,其目的是为了避免数值较大的特征A变化掩盖了数值较小的特征B变化,最终希望让特征AB都能对结果有影响。

  那么为什么要做归一化呢?

  维基百科给出的解释:1,归一化后加快了梯度下降求最优解的速度。2,归一化有能够提高精度。
解释:归一化为什么能提高梯度下降法求解最优解的速度?


  如下图所示(来自:斯坦福机器学习视频)

  蓝色的圈圈图代表的是两个特征的等高线。其中左图两个特征 X1和 X2的区间差别非常大,X1区间为[0, 2000] ,x2区间是 [1, 5],像这种有的数据那么大,有的数据那么小,两类之间的幅度相差这么大,其所构成的等高线非常尖。当运用梯度下降法寻求最优解时,很有能够走“之字型”道路(垂直等高线走),从而导致需求迭代很多次才能收敛。而右图对两个原始特征停止了归一化,其对应的等高线显得很圆,在梯度下降停止求解时能较快的收敛,因此假如机器学习模型运用梯度下降法求最优解时,归一化往往非常有必要,否则很难收敛,甚至不能收敛。
解释:归一化有能够提高精度


  一些分类器需求计算样本之间的间隔(如欧式间隔),例如KNN。假如一个特征值域范围非常大,那么间隔计算就次要取决于这个特征,从而与实践状况相悖(比如这时实践状况是值域范围小的特征更重要)。
归一化的类型


1,线性归一化

  这种归一化方法比较适用于在数值比较集中的状况。这种方法有个缺陷,假如max和min 不波动,很容易使得归一化结果不波动,使得后续运用效果也不波动。实践运用中可以用阅历常量值来替代 max和 min。

2,标准差标准化

  经过处理的数据符合标准正态分布,即均值为0,标准差为1。

3,非线性归一化

  常常用在数据分化比较大的场景,有些数值很大,有些很小。经过一些数学函数,将原始值停止映射。该方法包括 log、指数,正切等。需求根据数据分布的状况,决议非线性函数的曲线,比如log(V, 2)还是log(V, 10)等。
11,batch


  深度学习中频繁出现batch这个词语,所以我们有必要了解一下。

  深度学习中 的优化算法,说白了就是梯度下降。每次的参数更新有两种方式。

  第一种,遍历全部数据集算一次损失函数,然后算函数对各个参数的梯度,更新梯度。这张方式每更新一次参数都要把数据集里的一切样本都看一遍,计算量开支大,计算速度慢,不支持在线学习,这称为 Batch gradient descent,批梯度下降。

  另一种,每看一个数据就算一下损失函数,然后求梯度更新参数,这个称为随机梯度下降, stochastic gradient descent。这个方法速度比较快,但是收敛功能不太好,能够在最优点附近晃来晃去, hit 不到最优点。两次参数的更新也有能够互相抵消掉,形成目的函数震荡的比较猛烈。

  为了克制两种方法的缺陷,如今普通采用的时一种折中手腕,mini-batch gradient decent,小批的梯度下降,这种方法把数据分为若干个批,按批来更新参数。这样一个批中的一组数据共同决议了本次梯度的方向,下降起来就不容易跑偏,减少了随机性。另外一方面由于批次的样本数与整个数据集相比少了很多,计算量也不是很大。

  基本上如今的梯度下降都是基于 mini-batch的,所以Keras的模块中常常会出现 batch_size,就是指这个。
12,关于机器学习拟合成绩

12.1 什么是机器学习过拟合?


  所谓过拟合,就是指模型在训练集上的效果很好,在测试集上的预测效果很差。
12.2 如何避免过拟合成绩?


  1,重采样Bootstrap

  2,L1,L2 正则化

  3,决策树的剪枝操作

  4,交叉验证
12.3 什么是机器学习的欠拟合?


  所谓欠拟合就是模型复杂度低或者数据集太小,对模型数据的拟合程度不高,因此模型在训练集上的效果就不好。
12.3 如何避免欠拟合成绩?


  1,添加样本数量

  2,添加样本特征的数量

  3,可以停止特征维度扩展
12.4 算法的误差普通是由那几个方面惹起的?


  1,因模型无法表达基本数据的复杂度而形成的偏向(bias)——欠拟合

  2,因模型过度拟合训练集数据而形成的方差(variance)——过拟合
13,为什么朴素贝叶斯如此“朴素”?


  贝叶斯算法简单高效,在处理分类成绩上,是首先要思索的方法之一。

  贝叶斯分类是一类分类算法的总称,这类算法均以贝叶斯定理为基础,故统称为贝叶斯分类。公式如下:

  该公式最大的优点就是可以忽略AB 的结合概率直接求其条件概率分布。

  而朴素贝叶斯为什么如此朴素,由于他假定一切的特征在数据集中的作用是异样重要和独立的。正如我们所知,这个假设在理想世界中是很不真实的,因此说朴素贝叶斯真的很“朴素”。

  朴素贝叶斯分类是一种非常简单的分类算法,其思想是朴素的。即:对于给出的待分类项,求解在此项出现的条件下各个类别出现的概率,那个最大,就以为此待分类项属于那个类别。

  实际上,朴素贝叶斯模型与其他分类方法相比具有最小的误差率。但是实践上并非总是如此,这是由于朴素贝叶斯模型给定输入类别的状况下,假设属性之间互相独立,这个假设在实践运用中往往是不成立的,在属性个数比较多或者属性之间相关性较大时,分类效果不好。而在属性相关性较小的时,朴素贝叶斯功能最为良好。对于这一点,有半朴素贝叶斯之类的算法经过思索部分关联性过度改进。

14,反向传播算法(BP算法)的推导及其Python完成


  下面学习如何调整一个神经网络的参数,也就是误差反向传播算法(BP算法)。以得到一个可以根据输入,预测正确输入的模型。
14.1,首先我们要了解优化的目的


  根据人工神经元的定义,有以下三个公式:

  其中,Act() 是激活函数,之前学习过。

  根据下面两个公式,可以得出各个神经元之间的通用公式,如下:

  其中上式是人工神经网络正向传播的核心公式。

  那么,我们根据什么来调整神经网络的参数,以得到一个可以正确预测结果的模型呢?请看下面的公式:

  上式用来计算我们希冀的输入和实践输入的“差别”,其中cost() 叫做损失函数。我们的希冀是损失函数值达到最小。

  但是只根据一次输入的损失值,对参数停止调整,无法使模型顺应一切输入样本。我们需求的是,调整参数,使得一切输入样本,得到输入的总损失值最小,而不是只让妻子一个样本的损失值最小,导致其他样本损失值增大。因此有下面公式:

  上式表示一个 batch 的一切样本输入的总损失值的平均值。其中,bn 表示一个 batch中样本的数量。

  为什么不用一切的样本计算损失值,而将一切样本分成一个个的 batch呢?由于一切的训练样本数量太大了,能够有数以百万计,将一切的样本损失值都一同停止运算,计算量过于庞大,大大降低了模型计算的速度。

  而计算总的损失值 C,其中是一个以一切的衔接权重 W 和 一切的阈值 theta 未为变量的多元函数。我们想要的模型就是求得 C 最小时,一切 W 和 theta 的值。直接计算显然是不能够的,由于对于一个大的深度神经网络,一切的参数变量,能够数以万计。

  在这里我们运用梯度下降算法来逐渐逼近 C的最小值,也即是先随机得到一组参数变量的值,然后计算参数变量当前的梯度,向梯度的反方向,也就是C变小最快的方向,逐渐调整参数值,最终得到 C 的最小值,或者近似最小值。

  而将一切样本,随机分成一个个固定长度的 batch,以得到近似的梯度方向,叫做随机梯度下降算法。
14.2 末尾求梯度


  那么根据梯度的定义,接上去的义务,就是求取各个参数变量相对于 C 的偏导数。我们将运用误差反向传播算法来求取各个参数变量的偏导数。

  求取偏导数的方法和神经网络正向传播(根据样本计算输入值)的方式相似,也是逐层求解,只是方向正好相反,从最后一层末尾,逐层向前。

  首先,我们先求神经网络最后一层,也即是输入层的相关参数的偏导数。为了降低推导的复杂性,我们只计算相对一个样本的损失值函数 Cbi 的偏导数,由于相对于总损失值函数 C 的偏导数值,也不过是把某个参数的一切相对于 Cbi 偏导数值加起来而已。

  根据下面公式,以及 复合函数求导法则,可以得到输入层(L层)某个神经元的权值参数 W 的偏导数,计算公式如下:

  根据后面三个公式求导如下:



  将这三个公式代入下面公式,可以得到:

  我们令:

  则:

  将上式代入损失函数求导的公式中可以得到:

  这样我们就得到了输入层 L 相关的权重参数 W 的偏导数计算公式!

  接上去,同理可以求得输入层 L 相关的阈值 theta 的偏导数计算公式为:

  而根据第二个公式可以得到:

  将上式代入到上上式可以得到:

  这就是 输入层 L 相关的阈值 theta 的偏导数计算公式!
14.3 根据 L 层,求前一层参数的偏导函数


  从下面公式,可知,一个权重参数 W 只影响一个 L-1 层的神经元:

  因此可以得到有下面公式:



  将上式代入到上上式可以得到:

  根据假设:

  我们可以得到:

  将上式代入到上上式,可以得到:

  同理,我们可以得到:

  根据14.3 第一个公式可以得到:

  将上式代入到上上式,可以得到:

  这样我们就得到了 L-1 层神经元相关参数的计算公式。

  下面我们还需求推导一下

之间的关系,根据下面公式:

  我们可以得到:

  同理可得:

  将上式代入到上上式,可以得:

  我们知道,一个权重参数 W 只影响一个 L-1 层的神经元,但这个 L-1 层神经元影响了一切 L层的神经元。因此,根据多元复合函数求导法则。有:

  根据我们之前的假设,可以得到:

  将上式代入到上上式,可以得到:

  我们可以知道:

  将上式代入到上上式,可以得到:

  最后将上式代入之前的公式,可以得到:

  这样我们就得到了反向传播,逐层推导的通用公式:




  这里, W 和 Z 都是整箱传播过程中曾经算好的常数,而

可以从 L层末尾逐层向前推导,直到第1层,第0层是输入层,不需求调整参数,而第L层的参数可以参考下面公式:

  下面是全衔接神经网络的Python实古代码:

#coding=utf-8

import numpy as np

import matplotlib.pylab as plt

import random

class NeuralNetwork(object):

def __init__(self, sizes, act, act_derivative, cost_derivative):

#sizes表示神经网络各层的神经元个数,第一层为输入层,最后一层为输入层

#act为神经元的激活函数

#act_derivative为激活函数的导数

#cost_derivative为损失函数的导数

self.num_layers = len(sizes)

self.sizes = sizes

self.biases = [np.random.randn(nueron_num, 1) for nueron_num in sizes[1:]]

self.weights = [np.random.randn(next_layer_nueron_num, nueron_num)

for nueron_num, next_layer_nueron_num in zip(sizes[:-1], sizes[1:])]

self.act=act

self.act_derivative=act_derivative

self.cost_derivative=cost_derivative

#前向反馈(正向传播)

def feedforward(self, a):

#逐层计算神经元的激活值,公式(4)

for b, w in zip(self.biases, self.weights):

a = self.act(np.dot(w, a)+b)

return a

#随机梯度下降算法

def SGD(self, training_data, epochs, batch_size, learning_rate):

#将训练样本training_data随机分为若干个长度为batch_size的batch

#运用各个batch的数据不断调整参数,学习率为learning_rate

#迭代epochs次

n = len(training_data)

for j in range(epochs):

random.shuffle(training_data)

batches = [training_data[k:k+batch_size] for k in range(0, n, batch_size)]

for batch in batches:

self.update_batch(batch, learning_rate)

print("Epoch {0} complete".format(j))

def update_batch(self, batch, learning_rate):

#根据一个batch中的训练样本,调整各个参数值

nabla_b = [np.zeros(b.shape) for b in self.biases]

nabla_w = [np.zeros(w.shape) for w in self.weights]

for x, y in batch:

delta_nabla_b, delta_nabla_w = self.backprop(x, y)

nabla_b = [nb+dnb for nb, dnb in zip(nabla_b, delta_nabla_b)]

nabla_w = [nw+dnw for nw, dnw in zip(nabla_w, delta_nabla_w)]

#计算梯度,并调整各个参数值

self.weights = [w-(learning_rate/len(batch))*nw for w, nw in zip(self.weights, nabla_w)]

self.biases = [b-(learning_rate/len(batch))*nb for b, nb in zip(self.biases, nabla_b)]

#反向传播

def backprop(self, x, y):

#保存b和w的偏导数值

nabla_b = [np.zeros(b.shape) for b in self.biases]

nabla_w = [np.zeros(w.shape) for w in self.weights]

#正向传播

activation = x

#保存每一层神经元的激活值

activations = [x]

#保存每一层神经元的z值

zs = []

for b, w in zip(self.biases, self.weights):

z = np.dot(w, activation)+b

zs.append(z)

activation = self.act(z)

activations.append(activation)

#反向传播得到各个参数的偏导数值

#公式(13)

d = self.cost_derivative(activations[-1], y) * self.act_derivative(zs[-1])

#公式(17)

nabla_b[-1] = d

#公式(14)

nabla_w[-1] = np.dot(d, activations[-2].transpose())

#反向逐层计算

for l in range(2, self.num_layers):

z = zs[-l]

sp = self.act_derivative(z)

#公式(36),反向逐层求参数偏导

d = np.dot(self.weights[-l+1].transpose(), d) * sp

#公式(38)

nabla_b[-l] = d

#公式(37)

nabla_w[-l] = np.dot(d, activations[-l-1].transpose())

return (nabla_b, nabla_w)

#间隔函数的偏导数

def distance_derivative(output_activations, y):

#损失函数的偏导数

return 2*(output_activations-y)

# sigmoid函数

def sigmoid(z):

return 1.0/(1.0+np.exp(-z))

# sigmoid函数的导数

def sigmoid_derivative(z):

return sigmoid(z)*(1-sigmoid(z))

if __name__ == "__main__":

#创建一个5层的全衔接神经网络,每层的神经元个数为1,8,5,3,1

#其中第一层为输入层,最后一层为输入层

network=NeuralNetwork([1,8,5,3,1],sigmoid,sigmoid_derivative,distance_derivative)

#训练集样本

x = np.array([np.linspace(-7, 7, 200)]).T

#训练集结果,由于运用了sigmoid作为激活函数,需保证其结果落在(0,1)区间内

y = (np.cos(x)+1)/2

#运用随机梯度下降算法(SGD)对模型停止训练

#迭代5000次;每次随机抽取40个样本作为一个batch;学习率设为0.1

training_data=[(np.array([x_value]),np.array([y_value])) for x_value,y_value in zip(x,y)]

network.SGD(training_data,5000,40,0.1)

#测试集样本

x_test = np.array([np.linspace(-9, 9, 120)])

#测试集结果

y_predict = network.feedforward(x_test)

#图示对比训练集和测试集数据

plt.plot(x,y,'r',x_test.T,y_predict.T,'*')

plt.show()

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

大神点评3

罗东泰 2020-4-4 22:21:30 来自手机 显示全部楼层
OMG!介是啥东东!!!
回复

使用道具 举报

za59 2020-4-5 22:13:01 显示全部楼层
围观 围观 沙发在哪里!!!
回复

使用道具 举报

cyokkk 2020-4-6 18:11:11 显示全部楼层
珍爱生命,果断回帖。
回复

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies