您的位置:

python神经网络dnn,Python神经网络库

本文目录一览:

python的机器学习是什么?

机器学习是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。它是人工智能核心,是使计算机具有智能的根本途径。

而数据分析与机器学习不同,机器学习比数据分析更深一个层次,就业前景、薪资待遇也更高。

深度学习 python怎么入门 知乎

自学深度学习是一个漫长而艰巨的过程。您需要有很强的线性代数和微积分背景,良好的Python编程技能,并扎实掌握数据科学、机器学习和数据工程。即便如此,在你开始将深度学习应用于现实世界的问题,并有可能找到一份深度学习工程师的工作之前,你可能需要一年多的学习和实践。然而,知道从哪里开始,对软化学习曲线有很大帮助。如果我必须重新学习Python的深度学习,我会从Andrew Trask写的Grokking deep learning开始。大多数关于深度学习的书籍都要求具备机器学习概念和算法的基本知识。除了基本的数学和编程技能之外,Trask的书不需要任何先决条件就能教你深度学习的基础知识。这本书不会让你成为一个深度学习的向导(它也没有做这样的声明),但它会让你走上一条道路,让你更容易从更高级的书和课程中学习。用Python构建人工神经元

大多数深度学习书籍都是基于一些流行的Python库,如TensorFlow、PyTorch或Keras。相比之下,《运用深度学习》(Grokking Deep Learning)通过从零开始、一行一行地构建内容来教你进行深度学习。

《运用深度学习》

你首先要开发一个人工神经元,这是深度学习的最基本元素。查斯克将带领您了解线性变换的基本知识,这是由人工神经元完成的主要计算。然后用普通的Python代码实现人工神经元,无需使用任何特殊的库。

这不是进行深度学习的最有效方式,因为Python有许多库,它们利用计算机的图形卡和CPU的并行处理能力来加速计算。但是用普通的Python编写一切对于学习深度学习的来龙去是非常好的。

在Grokking深度学习中,你的第一个人工神经元只接受一个输入,将其乘以一个随机权重,然后做出预测。然后测量预测误差,并应用梯度下降法在正确的方向上调整神经元的权重。有了单个神经元、单个输入和单个输出,理解和实现这个概念变得非常容易。您将逐渐增加模型的复杂性,使用多个输入维度、预测多个输出、应用批处理学习、调整学习速率等等。

您将通过逐步添加和修改前面章节中编写的Python代码来实现每个新概念,逐步创建用于进行预测、计算错误、应用纠正等的函数列表。当您从标量计算转移到向量计算时,您将从普通的Python操作转移到Numpy,这是一个特别擅长并行计算的库,在机器学习和深度学习社区中非常流行。

Python的深度神经网络

有了这些人造神经元的基本构造块,你就可以开始创建深层神经网络,这基本上就是你将几层人造神经元叠放在一起时得到的结果。

当您创建深度神经网络时,您将了解激活函数,并应用它们打破堆叠层的线性并创建分类输出。同样,您将在Numpy函数的帮助下自己实现所有功能。您还将学习计算梯度和传播错误通过层传播校正跨不同的神经元。

随着您越来越熟悉深度学习的基础知识,您将学习并实现更高级的概念。这本书的特点是一些流行的正规化技术,如早期停止和退出。您还将获得自己版本的卷积神经网络(CNN)和循环神经网络(RNN)。

在本书结束时,您将把所有内容打包到一个完整的Python深度学习库中,创建自己的层次结构类、激活函数和神经网络体系结构(在这一部分,您将需要面向对象的编程技能)。如果您已经使用过Keras和PyTorch等其他Python库,那么您会发现最终的体系结构非常熟悉。如果您没有,您将在将来更容易地适应这些库。

在整本书中,查斯克提醒你熟能生巧;他鼓励你用心编写自己的神经网络,而不是复制粘贴任何东西。

代码库有点麻烦

并不是所有关于Grokking深度学习的东西都是完美的。在之前的一篇文章中,我说过定义一本好书的主要内容之一就是代码库。在这方面,查斯克本可以做得更好。

在GitHub的Grokking深度学习库中,每一章都有丰富的jupiter Notebook文件。jupiter Notebook是一个学习Python机器学习和深度学习的优秀工具。然而,jupiter的优势在于将代码分解为几个可以独立执行和测试的小单元。Grokking深度学习的一些笔记本是由非常大的单元格组成的,其中包含大量未注释的代码。

这在后面的章节中会变得尤其困难,因为代码会变得更长更复杂,在笔记本中寻找自己的方法会变得非常乏味。作为一个原则问题,教育材料的代码应该被分解成小单元格,并在关键区域包含注释。

此外,Trask在Python 2.7中编写了这些代码。虽然他已经确保了代码在Python 3中也能顺畅地工作,但它包含了已经被Python开发人员弃用的旧编码技术(例如使用“for i in range(len(array))”范式在数组上迭代)。

更广阔的人工智能图景

Trask已经完成了一项伟大的工作,它汇集了一本书,既可以为初学者,也可以为有经验的Python深度学习开发人员填补他们的知识空白。

但正如泰温·兰尼斯特(Tywin Lannister)所说(每个工程师都会同意),“每个任务都有一个工具,每个工具都有一个任务。”深度学习并不是一根可以解决所有人工智能问题的魔杖。事实上,对于许多问题,更简单的机器学习算法,如线性回归和决策树,将表现得和深度学习一样好,而对于其他问题,基于规则的技术,如正则表达式和几个if-else子句,将优于两者。

关键是,你需要一整套工具和技术来解决AI问题。希望Grokking深度学习能够帮助你开始获取这些工具。

你要去哪里?我当然建议选择一本关于Python深度学习的深度书籍,比如PyTorch的深度学习或Python的深度学习。你还应该加深你对其他机器学习算法和技术的了解。我最喜欢的两本书是《动手机器学习》和《Python机器学习》。

你也可以通过浏览机器学习和深度学习论坛,如r/MachineLearning和r/deeplearning subreddits,人工智能和深度学习Facebook组,或通过在Twitter上关注人工智能研究人员来获取大量知识。

AI的世界是巨大的,并且在快速扩张,还有很多东西需要学习。如果这是你关于深度学习的第一本书,那么这是一个神奇旅程的开始。

从零开始用Python构建神经网络

从零开始用Python构建神经网络

动机:为了更加深入的理解深度学习,我们将使用 python 语言从头搭建一个神经网络,而不是使用像 Tensorflow 那样的封装好的框架。我认为理解神经网络的内部工作原理,对数据科学家来说至关重要。

这篇文章的内容是我的所学,希望也能对你有所帮助。

神经网络是什么?

介绍神经网络的文章大多数都会将它和大脑进行类比。如果你没有深入研究过大脑与神经网络的类比,那么将神经网络解释为一种将给定输入映射为期望输出的数学关系会更容易理解。

神经网络包括以下组成部分

? 一个输入层,x

? 任意数量的隐藏层

? 一个输出层,?

? 每层之间有一组权值和偏置,W and b

? 为隐藏层选择一种激活函数,σ。在教程中我们使用 Sigmoid 激活函数

下图展示了 2 层神经网络的结构(注意:我们在计算网络层数时通常排除输入层)

2 层神经网络的结构

用 Python 可以很容易的构建神经网络类

训练神经网络

这个网络的输出 ? 为:

你可能会注意到,在上面的等式中,输出 ? 是 W 和 b 函数。

因此 W 和 b 的值影响预测的准确率. 所以根据输入数据对 W 和 b 调优的过程就被成为训练神经网络。

每步训练迭代包含以下两个部分:

? 计算预测结果 ?,这一步称为前向传播

? 更新 W 和 b,,这一步成为反向传播

下面的顺序图展示了这个过程:

前向传播

正如我们在上图中看到的,前向传播只是简单的计算。对于一个基本的 2 层网络来说,它的输出是这样的:

我们在 NeuralNetwork 类中增加一个计算前向传播的函数。为了简单起见我们假设偏置 b 为0:

但是我们还需要一个方法来评估预测结果的好坏(即预测值和真实值的误差)。这就要用到损失函数。

损失函数

常用的损失函数有很多种,根据模型的需求来选择。在本教程中,我们使用误差平方和作为损失函数。

误差平方和是求每个预测值和真实值之间的误差再求和,这个误差是他们的差值求平方以便我们观察误差的绝对值。

训练的目标是找到一组 W 和 b,使得损失函数最好小,也即预测值和真实值之间的距离最小。

反向传播

我们已经度量出了预测的误差(损失),现在需要找到一种方法来传播误差,并以此更新权值和偏置。

为了知道如何适当的调整权值和偏置,我们需要知道损失函数对权值 W 和偏置 b 的导数。

回想微积分中的概念,函数的导数就是函数的斜率。

梯度下降法

如果我们已经求出了导数,我们就可以通过增加或减少导数值来更新权值 W 和偏置 b(参考上图)。这种方式被称为梯度下降法。

但是我们不能直接计算损失函数对权值和偏置的导数,因为在损失函数的等式中并没有显式的包含他们。因此,我们需要运用链式求导发在来帮助计算导数。

链式法则用于计算损失函数对 W 和 b 的导数。注意,为了简单起见。我们只展示了假设网络只有 1 层的偏导数。

这虽然很简陋,但是我们依然能得到想要的结果—损失函数对权值 W 的导数(斜率),因此我们可以相应的调整权值。

现在我们将反向传播算法的函数添加到 Python 代码中

为了更深入的理解微积分原理和反向传播中的链式求导法则,我强烈推荐 3Blue1Brown 的如下教程:

Youtube:

整合并完成一个实例

既然我们已经有了包括前向传播和反向传播的完整 Python 代码,那么就将其应用到一个例子上看看它是如何工作的吧。

神经网络可以通过学习得到函数的权重。而我们仅靠观察是不太可能得到函数的权重的。

让我们训练神经网络进行 1500 次迭代,看看会发生什么。 注意观察下面每次迭代的损失函数,我们可以清楚地看到损失函数单调递减到最小值。这与我们之前介绍的梯度下降法一致。

让我们看看经过 1500 次迭代后的神经网络的最终预测结果:

经过 1500 次迭代训练后的预测结果

我们成功了!我们应用前向和方向传播算法成功的训练了神经网络并且预测结果收敛于真实值。

注意预测值和真实值之间存在细微的误差是允许的。这样可以防止模型过拟合并且使得神经网络对于未知数据有着更强的泛化能力。

下一步是什么?

幸运的是我们的学习之旅还没有结束,仍然有很多关于神经网络和深度学习的内容需要学习。例如:

? 除了 Sigmoid 以外,还可以用哪些激活函数

? 在训练网络的时候应用学习率

? 在面对图像分类任务的时候使用卷积神经网络

我很快会写更多关于这个主题的内容,敬请期待!

最后的想法

我自己也从零开始写了很多神经网络的代码

虽然可以使用诸如 Tensorflow 和 Keras 这样的深度学习框架方便的搭建深层网络而不需要完全理解其内部工作原理。但是我觉得对于有追求的数据科学家来说,理解内部原理是非常有益的。

这种练习对我自己来说已成成为重要的时间投入,希望也能对你有所帮助

深度神经网络dnn怎么调节参数

深度神经网络(DNN)目前是许多现代AI应用的基础。

自从DNN在语音识别和图像识别任务中展现出突破性的成果,使用DNN的应用数量呈爆炸式增加。这些DNN方法被大量应用在无人驾驶汽车,癌症检测,游戏AI等方面。

在许多领域中,DNN目前的准确性已经超过人类。与早期的专家手动提取特征或制定规则不同,DNN的优越性能来自于在大量数据上使用统计学习方法,从原始数据中提取高级特征的能力,从而对输入空间进行有效的表示。

然而,DNN超高的准确性是以超高的计算复杂度为代价的。

通常意义下的计算引擎,尤其是GPU,是DNN的基础。因此,能够在不牺牲准确性和增加硬件成本的前提下,提高深度神经网络的能量效率和吞吐量的方法,对于DNN在AI系统中更广泛的应用是至关重要的。研究人员目前已经更多的将关注点放在针对DNN计算开发专用的加速方法。

鉴于篇幅,本文主要针对论文中的如下几部分详细介绍:

DNN的背景,历史和应用

DNN的组成部分,以及常见的DNN模型

简介如何使用硬件加速DNN运算

DNN的背景

人工智能与深度神经网络

深度神经网络,也被称为深度学习,是人工智能领域的重要分支,根据麦卡锡(人工智能之父)的定义,人工智能是创造像人一样的智能机械的科学工程。深度学习与人工智能的关系如图1所示:

图1:深度神经网络与人工智能的关系

人工智能领域内,一个大的子领域是机器学习,由Arthur Samuel在1959年定义为:让计算机拥有不需要明确编程即可学习的能力。

这意味着创建一个程序,这个程序可以被训练去学习如何去做一些智能的行为,然后这个程序就可以自己完成任务。而传统的人工启发式方法,需要对每个新问题重新设计程序。

高效的机器学习算法的优点是显而易见的。一个机器学习算法,只需通过训练,就可以解决某一领域中每一个新问题,而不是对每个新问题特定地进行编程。

在机器学习领域,有一个部分被称作brain-inspired computation。因为人类大脑是目前学习和解决问题最好的“机器”,很自然的,人们会从中寻找机器学习的方法。

尽管科学家们仍在探索大脑工作的细节,但是有一点被公认的是:神经元是大脑的主要计算单元。

人类大脑平均有860亿个神经元。神经元相互连接,通过树突接受其他神经元的信号,对这些信号进行计算之后,通过轴突将信号传递给下一个神经元。一个神经元的轴突分支出来并连接到许多其他神经元的树突上,轴突分支和树突之间的连接被称为突触。据估计,人类大脑平均有1014-1015个突触。

突触的一个关键特性是它可以缩放通过它的信号大小。这个比例因子可以被称为权重(weight),普遍认为,大脑学习的方式是通过改变突触的权重实现的。因此,不同的权重导致对输入产生不同的响应。注意,学习过程是学习刺激导致的权重调整,而大脑组织(可以被认为是程序)并不改变。

大脑的这个特征对机器学习算法有很好的启示。

神经网络与深度神经网络

神经元的计算是输入值的加权和这个概念启发了神经网络的研究。这些加权和对应于突触的缩放值以及神经元所接收的值的组合。此外,神经元并不仅仅是输入信号的加权和,如果是这样的话,级联的神经元的计算将是一种简单的线性代数运算。

相反的是,神经元组合输入的操作似乎是一种非线性函数,只有输入达到某个阈值的时候,神经元才会生成输出。因此,通过类比,我们可以知道神经网络在输入值的加权和的基础上应用了非线性函数。

图2(a)展示了计算神经网络的示意图,图的最左边是接受数值的“输入层”。这些值被传播到中间层神经元,通常也叫做网络的“隐藏层”。通过一个或更多隐藏层的加权和最终被传播到“输出层”,将神经网络的最终结果输出给用户。

图2:神经网络示意图

在神经网络领域,一个子领域被称为深度学习。最初的神经网络通常只有几层的网络。而深度网络通常有更多的层数,今天的网络一般在五层以上,甚至达到一千多层。

目前在视觉应用中使用深度神经网络的解释是:将图像所有像素输入到网络的第一层之后,该层的加权和可以被解释为表示图像不同的低阶特征。随着层数的加深,这些特征被组合,从而代表更高阶的图像特征。

例如,线可以被组合成形状,再进一步,可以被组合成一系列形状的集合。最后,再训练好这些信息之后,针对各个图像类别,网络给出由这些高阶特征组成各个对象的概率,即分类结果。

推理(Inference)与训练(Training)

既然DNN是机器学习算法中的一员,那么它的基本编程思想仍然是学习。DNN的学习即确定网络的权重值。通常,学习过程被称为训练网络(training)。一旦训练完成,程序可以使用由训练确定的权值进行计算,这个使用网络完成任务的操作被被称为推断(inference)。

接下来,如图3所示,我们用图像分类作为例子来展示如何训练一个深度神经网络。当我们使用一个DNN的时候,我们输入一幅图片,DNN输出一个得分向量,每一个分数对应一个物体分类;得到最高分数的分类意味着这幅图片最有可能属于这个分类。

训练DNN的首要目标就是确定如何设置权重,使得正确分类的得分最高(图片所对应的正确分类在训练数据集中标出),而使其他不正确分类的得分尽可能低。理想的正确分类得分与目前的权重所计算出的得分之间的差距被称为损失函数(loss)。

因此训练DNN的目标即找到一组权重,使得对一个较大规模数据集的loss最小。

图3:图像分类

权重(weight)的优化过程类似爬山的过程,这种方法被称为梯度下降(gradient decent)。损失函数对每个权值的梯度,即损失函数对每个权值求偏导数,被用来更新权值(例:第t到t+1次迭代:,其中α被称为学习率(Learning rate)。梯度值表明权值应该如何变化以减小loss。这个减小loss值的过程是重复迭代进行的。

梯度可以通过反向传播(Back-Propagation)过程很高效地进行计算,loss的影响反向通过网络来计算loss是如何被每个权重影响的。

训练权重有很多种方法。前面提到的是最常见的方法,被称为监督学习,其中所有的训练样本是有标签的。

无监督学习是另一种方法,其中所有训练样本都没有标签,最终目标是在数据中查找结构或聚类。半监督学习结合了两种方法,只有训练数据的一小部分被标记(例如,使用未标记的数据来定义集群边界,并使用少量的标记数据来标记集群)。

最后,强化学习可以用来训练一个DNN作为一个策略网络,对策略网络给出一个输入,它可以做出一个决定,使得下一步的行动得到相应的奖励;训练这个网络的过程是使网络能够做出使奖励(即奖励函数)最大化的决策,并且训练过程必须平衡尝试新行为(Exploration)和使用已知能给予高回报的行为(Exploitation)两种方法。

用于确定权重的另一种常用方法是fine-tune,使用预先训练好的模型的权重用作初始化,然后针对新的数据集(例如,传递学习)或新的约束(例如,降低的精度)调整权重。与从随机初始化开始相比,能够更快的训练,并且有时会有更好的准确性。

如何用 Python 构建神经网络择时模型

import math

import random

random.seed(0)

def rand(a,b): #随机函数

return (b-a)*random.random()+a

def make_matrix(m,n,fill=0.0):#创建一个指定大小的矩阵

mat = []

for i in range(m):

mat.append([fill]*n)

return mat

#定义sigmoid函数和它的导数

def sigmoid(x):

return 1.0/(1.0+math.exp(-x))

def sigmoid_derivate(x):

return x*(1-x) #sigmoid函数的导数

class BPNeuralNetwork:

def __init__(self):#初始化变量

self.input_n = 0

self.hidden_n = 0

self.output_n = 0

self.input_cells = []

self.hidden_cells = []

self.output_cells = []

self.input_weights = []

self.output_weights = []

self.input_correction = []

self.output_correction = []

#三个列表维护:输入层,隐含层,输出层神经元

def setup(self,ni,nh,no):

self.input_n = ni+1 #输入层+偏置项

self.hidden_n = nh #隐含层

self.output_n = no #输出层

#初始化神经元

self.input_cells = [1.0]*self.input_n

self.hidden_cells= [1.0]*self.hidden_n

self.output_cells= [1.0]*self.output_n

#初始化连接边的边权

self.input_weights = make_matrix(self.input_n,self.hidden_n) #邻接矩阵存边权:输入层-隐藏层

self.output_weights = make_matrix(self.hidden_n,self.output_n) #邻接矩阵存边权:隐藏层-输出层

#随机初始化边权:为了反向传导做准备---随机初始化的目的是使对称失效

for i in range(self.input_n):

for h in range(self.hidden_n):

self.input_weights[i][h] = rand(-0.2 , 0.2) #由输入层第i个元素到隐藏层第j个元素的边权为随机值

for h in range(self.hidden_n):

for o in range(self.output_n):

self.output_weights[h][o] = rand(-2.0, 2.0) #由隐藏层第i个元素到输出层第j个元素的边权为随机值

#保存校正矩阵,为了以后误差做调整

self.input_correction = make_matrix(self.input_n , self.hidden_n)

self.output_correction = make_matrix(self.hidden_n,self.output_n)

#输出预测值

def predict(self,inputs):

#对输入层进行操作转化样本

for i in range(self.input_n-1):

self.input_cells[i] = inputs[i] #n个样本从0~n-1

#计算隐藏层的输出,每个节点最终的输出值就是权值*节点值的加权和

for j in range(self.hidden_n):

total = 0.0

for i in range(self.input_n):

total+=self.input_cells[i]*self.input_weights[i][j]

# 此处为何是先i再j,以隐含层节点做大循环,输入样本为小循环,是为了每一个隐藏节点计算一个输出值,传输到下一层

self.hidden_cells[j] = sigmoid(total) #此节点的输出是前一层所有输入点和到该点之间的权值加权和

for k in range(self.output_n):

total = 0.0

for j in range(self.hidden_n):

total+=self.hidden_cells[j]*self.output_weights[j][k]

self.output_cells[k] = sigmoid(total) #获取输出层每个元素的值

return self.output_cells[:] #最后输出层的结果返回

#反向传播算法:调用预测函数,根据反向传播获取权重后前向预测,将结果与实际结果返回比较误差

def back_propagate(self,case,label,learn,correct):

#对输入样本做预测

self.predict(case) #对实例进行预测

output_deltas = [0.0]*self.output_n #初始化矩阵

for o in range(self.output_n):

error = label[o] - self.output_cells[o] #正确结果和预测结果的误差:0,1,-1

output_deltas[o]= sigmoid_derivate(self.output_cells[o])*error#误差稳定在0~1内

#隐含层误差

hidden_deltas = [0.0]*self.hidden_n

for h in range(self.hidden_n):

error = 0.0

for o in range(self.output_n):

error+=output_deltas[o]*self.output_weights[h][o]

hidden_deltas[h] = sigmoid_derivate(self.hidden_cells[h])*error

#反向传播算法求W

#更新隐藏层-输出权重

for h in range(self.hidden_n):

for o in range(self.output_n):

change = output_deltas[o]*self.hidden_cells[h]

#调整权重:上一层每个节点的权重学习*变化+矫正率

self.output_weights[h][o] += learn*change + correct*self.output_correction[h][o]

#更新输入-隐藏层的权重

for i in range(self.input_n):

for h in range(self.hidden_n):

change = hidden_deltas[h]*self.input_cells[i]

self.input_weights[i][h] += learn*change + correct*self.input_correction[i][h]

self.input_correction[i][h] = change

#获取全局误差

error = 0.0

for o in range(len(label)):

error = 0.5*(label[o]-self.output_cells[o])**2 #平方误差函数

return error

def train(self,cases,labels,limit=10000,learn=0.05,correct=0.1):

for i in range(limit): #设置迭代次数

error = 0.0

for j in range(len(cases)):#对输入层进行访问

label = labels[j]

case = cases[j]

error+=self.back_propagate(case,label,learn,correct) #样例,标签,学习率,正确阈值

def test(self): #学习异或

cases = [

[0, 0],

[0, 1],

[1, 0],

[1, 1],

] #测试样例

labels = [[0], [1], [1], [0]] #标签

self.setup(2,5,1) #初始化神经网络:输入层,隐藏层,输出层元素个数

self.train(cases,labels,10000,0.05,0.1) #可以更改

for case in cases:

print(self.predict(case))

if __name__ == '__main__':

nn = BPNeuralNetwork()

nn.test()

利用Python实现卷积神经网络的可视化

在本文中,将探讨如何可视化卷积神经网络(CNN),该网络在计算机视觉中使用最为广泛。首先了解CNN模型可视化的重要性,其次介绍可视化的几种方法,同时以一个用例帮助读者更好地理解模型可视化这一概念。

正如上文中介绍的癌症肿瘤诊断案例所看到的,研究人员需要对所设计模型的工作原理及其功能掌握清楚,这点至关重要。一般而言,一名深度学习研究者应该记住以下几点:

1.1 理解模型是如何工作的

1.2 调整模型的参数

1.3 找出模型失败的原因

1.4 向消费者/终端用户或业务主管解释模型做出的决定

2.可视化CNN模型的方法

根据其内部的工作原理,大体上可以将CNN可视化方法分为以下三类:

初步方法:一种显示训练模型整体结构的简单方法

基于激活的方法:对单个或一组神经元的激活状态进行破译以了解其工作过程

基于梯度的方法:在训练过程中操作前向传播和后向传播形成的梯度

下面将具体介绍以上三种方法,所举例子是使用Keras深度学习库实现,另外本文使用的数据集是由“识别数字”竞赛提供。因此,读者想复现文中案例时,请确保安装好Kears以及执行了这些步骤。

研究者能做的最简单的事情就是绘制出模型结构图,此外还可以标注神经网络中每层的形状及参数。在keras中,可以使用如下命令完成模型结构图的绘制:

model.summary()_________________________________________________________________Layer (type)                 Output Shape              Param #  

=================================================================conv2d_1 (Conv2D)            (None, 26, 26, 32)        320_________________________________________________________________conv2d_2 (Conv2D)            (None, 24, 24, 64)        18496_________________________________________________________________max_pooling2d_1 (MaxPooling2 (None, 12, 12, 64)        0_________________________________________________________________dropout_1 (Dropout)          (None, 12, 12, 64)        0_________________________________________________________________flatten_1 (Flatten)          (None, 9216)              0_________________________________________________________________dense_1 (Dense)              (None, 128)               1179776_________________________________________________________________dropout_2 (Dropout)          (None, 128)               0_________________________________________________________________preds (Dense)                (None, 10)                1290      

=================================================================Total params: 1,199,882Trainable params: 1,199,882Non-trainable params: 0

还可以用一个更富有创造力和表现力的方式呈现模型结构框图,可以使用keras.utils.vis_utils函数完成模型体系结构图的绘制。

另一种方法是绘制训练模型的过滤器,这样就可以了解这些过滤器的表现形式。例如,第一层的第一个过滤器看起来像:

top_layer = model.layers[0]plt.imshow(top_layer.get_weights()[0][:, :, :, 0].squeeze(), cmap='gray')

一般来说,神经网络的底层主要是作为边缘检测器,当层数变深时,过滤器能够捕捉更加抽象的概念,比如人脸等。

为了理解神经网络的工作过程,可以在输入图像上应用过滤器,然后绘制其卷积后的输出,这使得我们能够理解一个过滤器其特定的激活模式是什么。比如,下图是一个人脸过滤器,当输入图像是人脸图像时候,它就会被激活。

from vis.visualization import visualize_activation

from vis.utils import utils

from keras import activations

from matplotlib import pyplot as plt

%matplotlib inline

plt.rcParams['figure.figsize'] = (18, 6)

# Utility to search for layer index by name.

# Alternatively we can specify this as -1 since it corresponds to the last layer.

layer_idx = utils.find_layer_idx(model, 'preds')

# Swap softmax with linear

model.layers[layer_idx].activation = activations.linear

model = utils.apply_modifications(model)

# This is the output node we want to maximize.filter_idx = 0

img = visualize_activation(model, layer_idx, filter_indices=filter_idx)

plt.imshow(img[..., 0])

同理,可以将这个想法应用于所有的类别,并检查它们的模式会是什么样子。

for output_idx in np.arange(10):

  # Lets turn off verbose output this time to avoid clutter and just see the output.

  img = visualize_activation(model, layer_idx, filter_indices=output_idx, input_range=(0., 1.))

  plt.figure()

  plt.title('Networks perception of {}'.format(output_idx))

  plt.imshow(img[..., 0])

在图像分类问题中,可能会遇到目标物体被遮挡,有时候只有物体的一小部分可见的情况。基于图像遮挡的方法是通过一个灰色正方形系统地输入图像的不同部分并监视分类器的输出。这些例子清楚地表明模型在场景中定位对象时,若对象被遮挡,其分类正确的概率显著降低。

为了理解这一概念,可以从数据集中随机抽取图像,并尝试绘制该图的热图(heatmap)。这使得我们直观地了解图像的哪些部分对于该模型而言的重要性,以便对实际类别进行明确的区分。

def iter_occlusion(image, size=8):

    # taken from

  occlusion = np.full((size * 5, size * 5, 1), [0.5], np.float32)

  occlusion_center = np.full((size, size, 1), [0.5], np.float32)

  occlusion_padding = size * 2

  # print('padding...')

  image_padded = np.pad(image, ( \  (occlusion_padding, occlusion_padding), (occlusion_padding, occlusion_padding), (0, 0) \  ), 'constant', constant_values = 0.0)

  for y in range(occlusion_padding, image.shape[0] + occlusion_padding, size):

      for x in range(occlusion_padding, image.shape[1] + occlusion_padding, size):

          tmp = image_padded.copy()

          tmp[y - occlusion_padding:y + occlusion_center.shape[0] + occlusion_padding, \

            x - occlusion_padding:x + occlusion_center.shape[1] + occlusion_padding] \            = occlusion

          tmp[y:y + occlusion_center.shape[0], x:x + occlusion_center.shape[1]] = occlusion_center          yield x - occlusion_padding, y - occlusion_padding, \

            tmp[occlusion_padding:tmp.shape[0] - occlusion_padding, occlusion_padding:tmp.shape[1] - occlusion_padding]i = 23 # for exampledata = val_x[i]correct_class = np.argmax(val_y[i])

# input tensor for model.predictinp = data.reshape(1, 28, 28, 1)# image data for matplotlib's imshowimg = data.reshape(28, 28)

# occlusionimg_size = img.shape[0]

occlusion_size = 4print('occluding...')heatmap = np.zeros((img_size, img_size), np.float32)class_pixels = np.zeros((img_size, img_size), np.int16)

from collections import defaultdict

counters = defaultdict(int)for n, (x, y, img_float) in enumerate(iter_occlusion(data, size=occlusion_size)):

    X = img_float.reshape(1, 28, 28, 1)

    out = model.predict(X)

    #print('#{}: {} @ {} (correct class: {})'.format(n, np.argmax(out), np.amax(out), out[0][correct_class]))

    #print('x {} - {} | y {} - {}'.format(x, x + occlusion_size, y, y + occlusion_size))

    heatmap[y:y + occlusion_size, x:x + occlusion_size] = out[0][correct_class]

    class_pixels[y:y + occlusion_size, x:x + occlusion_size] = np.argmax(out)

    counters[np.argmax(out)] += 1

正如之前的坦克案例中看到的那样,怎么才能知道模型侧重于哪部分的预测呢?为此,可以使用显著图解决这个问题。显著图首先在这篇文章中被介绍。

使用显著图的概念相当直接——计算输出类别相对于输入图像的梯度。这应该告诉我们输出类别值对于输入图像像素中的微小变化是怎样变化的。梯度中的所有正值告诉我们,像素的一个小变化会增加输出值。因此,将这些梯度可视化可以提供一些直观的信息,这种方法突出了对输出贡献最大的显著图像区域。

class_idx = 0indices = np.where(val_y[:, class_idx] == 1.)[0]

# pick some random input from here.idx = indices[0]

# Lets sanity check the picked image.from matplotlib import pyplot as plt%matplotlib inline

plt.rcParams['figure.figsize'] = (18, 6)plt.imshow(val_x[idx][..., 0])

from vis.visualization import visualize_saliency

from vis.utils import utilsfrom keras import activations# Utility to search for layer index by name.

# Alternatively we can specify this as -1 since it corresponds to the last layer.

layer_idx = utils.find_layer_idx(model, 'preds')

# Swap softmax with linearmodel.layers[layer_idx].activation = activations.linear

model = utils.apply_modifications(model)grads = visualize_saliency(model, layer_idx, filter_indices=class_idx, seed_input=val_x[idx])

# Plot with 'jet' colormap to visualize as a heatmap.plt.imshow(grads, cmap='jet')

# This corresponds to the Dense linear layer.for class_idx in np.arange(10):

    indices = np.where(val_y[:, class_idx] == 1.)[0]

    idx = indices[0]

    f, ax = plt.subplots(1, 4)

    ax[0].imshow(val_x[idx][..., 0])

    for i, modifier in enumerate([None, 'guided', 'relu']):

        grads = visualize_saliency(model, layer_idx, filter_indices=class_idx,

        seed_input=val_x[idx], backprop_modifier=modifier)

        if modifier is None:

            modifier = 'vanilla'

        ax[i+1].set_title(modifier)

        ax[i+1].imshow(grads, cmap='jet')

类别激活映射(CAM)或grad-CAM是另外一种可视化模型的方法,这种方法使用的不是梯度的输出值,而是使用倒数第二个卷积层的输出,这样做是为了利用存储在倒数第二层的空间信息。

from vis.visualization import visualize_cam

# This corresponds to the Dense linear layer.for class_idx in np.arange(10):

indices = np.where(val_y[:, class_idx] == 1.)[0]

idx = indices[0]f, ax = plt.subplots(1, 4)

ax[0].imshow(val_x[idx][..., 0])

for i, modifier in enumerate([None, 'guided', 'relu']):

    grads = visualize_cam(model, layer_idx, filter_indices=class_idx,

    seed_input=val_x[idx], backprop_modifier=modifier)

    if modifier is None:

        modifier = 'vanilla'

    ax[i+1].set_title(modifier)

    ax[i+1].imshow(grads, cmap='jet')

本文简单说明了CNN模型可视化的重要性,以及介绍了一些可视化CNN网络模型的方法,希望对读者有所帮助,使其能够在后续深度学习应用中构建更好的模型。 免费视频教程: