A. 如何在R语言中进行神经网络模型的建立
不能发链接,所以我复制过来了。
#载入程序和数据
library(RSNNS)
data(iris)
#将数据顺序打乱
iris <- iris[sample(1:nrow(iris),length(1:nrow(iris))),1:ncol(iris)]
#定义网络输入
irisValues <- iris[,1:4]
#定义网络输出,并将数据进行格式转换
irisTargets <- decodeClassLabels(iris[,5])
#从中划分出训练样本和检验样本
iris <- splitForTrainingAndTest(irisValues, irisTargets, ratio=0.15)
#数据标准化
iris <- normTrainingAndTestSet(iris)
#利用mlp命令执行前馈反向传播神经网络算法
model <- mlp(iris$inputsTrain, iris$targetsTrain, size=5, learnFunc="Quickprop", learnFuncParams=c(0.1, 2.0, 0.0001, 0.1),maxit=100, inputsTest=iris$inputsTest, targetsTest=iris$targetsTest)
#利用上面建立的模型进行预测
predictions <- predict(model,iris$inputsTest)
#生成混淆矩阵,观察预测精度
confusionMatrix(iris$targetsTest,predictions)
#结果如下:
# predictions
#targets 1 2 3
# 1 8 0 0
# 2 0 4 0
# 3 0 1 10
B. 如何用python和scikit learn实现神经网络
1:神经网络算法简介
2:Backpropagation算法详细介绍
3:非线性转化方程举例
4:自己实现神经网络算法NeuralNetwork
5:基于NeuralNetwork的XOR实例
6:基于NeuralNetwork的手写数字识别实例
7:scikit-learn中BernoulliRBM使用实例
8:scikit-learn中的手写数字识别实例
一:神经网络算法简介
1:背景
以人脑神经网络为启发,历史上出现过很多版本,但最着名的是backpropagation
2:多层向前神经网络(Multilayer Feed-Forward Neural Network)
C. 如何训练神经网络
1、先别着急写代码
训练神经网络前,别管代码,先从预处理数据集开始。我们先花几个小时的时间,了解数据的分布并找出其中的规律。
Andrej有一次在整理数据时发现了重复的样本,还有一次发现了图像和标签中的错误。所以先看一眼数据能避免我们走很多弯路。
由于神经网络实际上是数据集的压缩版本,因此您将能够查看网络(错误)预测并了解它们的来源。如果你的网络给你的预测看起来与你在数据中看到的内容不一致,那么就会有所收获。
一旦从数据中发现规律,可以编写一些代码对他们进行搜索、过滤、排序。把数据可视化能帮助我们发现异常值,而异常值总能揭示数据的质量或预处理中的一些错误。
2、设置端到端的训练评估框架
处理完数据集,接下来就能开始训练模型了吗?并不能!下一步是建立一个完整的训练+评估框架。
在这个阶段,我们选择一个简单又不至于搞砸的模型,比如线性分类器、CNN,可视化损失。获得准确度等衡量模型的标准,用模型进行预测。
这个阶段的技巧有:
· 固定随机种子
使用固定的随机种子,来保证运行代码两次都获得相同的结果,消除差异因素。
· 简单化
在此阶段不要有任何幻想,不要扩增数据。扩增数据后面会用到,但是在这里不要使用,现在引入只会导致错误。
· 在评估中添加有效数字
在绘制测试集损失时,对整个测试集进行评估,不要只绘制批次测试损失图像,然后用Tensorboard对它们进行平滑处理。
· 在初始阶段验证损失函数
验证函数是否从正确的损失值开始。例如,如果正确初始化最后一层,则应在softmax初始化时测量-log(1/n_classes)。
· 初始化
正确初始化最后一层的权重。如果回归一些平均值为50的值,则将最终偏差初始化为50。如果有一个比例为1:10的不平衡数据集,请设置对数的偏差,使网络预测概率在初始化时为0.1。正确设置这些可以加速模型的收敛。
· 人类基线
监控除人为可解释和可检查的损失之外的指标。尽可能评估人的准确性并与之进行比较。或者对测试数据进行两次注释,并且对于每个示例,将一个注释视为预测,将第二个注释视为事实。
· 设置一个独立于输入的基线
最简单的方法是将所有输入设置为零,看看模型是否学会从输入中提取任何信息。
· 过拟合一个batch
增加了模型的容量并验证我们可以达到的最低损失。
· 验证减少训练损失
尝试稍微增加数据容量。
D. 使用python在GPU上构建和训练卷积神经网络
我将对代码进行补充演练,以构建在数据集上训练的任何类型的图像分类器。在这个例子中,我将使用花卉数据集,其中包括102种不同类型的花。需要数据集和代码都可以私信我。
Pytorch是机器学习和Python上的免费软件包,非常易于使用。语法模拟numpy,因此,如果你在python中有一些科学计算经验,那么会相当有用的。贺宽只需几行代码,就可以下载预先训练的数据集,使用定义的变换对图像进丛袭行标准化,然后运行训练。
创建和扩充数据集
为了增加数据集,我使用' google_images_download'API 从互联网上下载了相关图像。显然,您可以使用此API不仅可以扩充现有数据集,还可以从头开始创建自己的数据集。
确保从图像中挑选出异常值(损坏的文件或偶然出现的无关图像)。
图像标准化
为了使图像具有相同的大小和像素变化,可以使用pytorch的transfors模块:
转移学习
从头开始训练的模型可能不是最明智的选择,因为有许多网络可用于各种数据集。简单地说,像edge-和其他简单形状检测器等低级特征对于不同的模型是相似的,即使clasificators是针对不同目的进行训练的。在本项目中,我使用了一个预训练网络Resnet152,只有最后一个完全连接的层重新用于新任务,即使这样也会产生相当好的效果。
在这里,我将除最后一层之外的所有层都设置为具有固定权重(requires_grad = False),因此只有最后层中的参数将通过梯度下降进行更新。
训练模型
下面介绍一下进行训练的函数:
如何获得GPU?
当然,对CPU的训练太慢了。根据我自己的经验,在GPU仅需要一个小时就可以完成12次训练周期,但是在CPU上相同数量的训练周期可能需要花费大约15个小时。
如果您没有本地可用的GPU,则可以考虑使用云GPU。为了加速禅郑亮CNN的训练,我使用了floydhub(www.floydhub.com)上提供的云GPU 。
这项服务非常指的使用:总有很好的文档和大量的提示,所以你会很清楚的知道下一步需要如何去做。在floydhub上对于使用GPU的收费也是可以接受的。
首先,需要将数据集上传到服务器
然后,需要创建项目。需要在计算机上安装floydhub客户端,将数据集上载到其网站并在终端中运行以下命令:
其中'username'是您的登录名,'i'是数据集所在的文件夹。
这样子在训练网络时就会很轻松了
结果和改进想法
得到的模型在数据集上训练了1.5小时,并在验证数据集上达到了95%的准确度。
E. 2.搭建一个神经网络模型训练MNIST手写体数字数据集中遇到的问题及解决方法
批量输入后,如何使用numpy矩阵计算的方法计算各权值梯度,提高计算速度
def backprop(self, x, y): #x为多维矩阵。每列为一个x值。 y为多维矩阵。每列为一个y值。
batch_num=x.shape[1]
#print(x.shape)
#print(y.shape)
"""创建两个变量,用来存储所有b值和所有w值对应的梯度值。初始化为0.nabla_b为一个list,形状与biases的形状完全一致。nabla_w 为一个list,形状与weights的形状完全一致。
"""
nabla_b = [np.zeros(b.shape) for b in self.biases]
nabla_w = [np.zeros(w.shape) for w in self.weights]
# feedforward
"""activations,用来所有中间层和输出层在一次前向计算过程中的最终输出值,即a值。该值记录下来,以供后期使用BP算法求每个b和w的梯度。
"""
activation = x #x为本批多个x为列组成的矩阵。
activations = [x] # list to store all the activations, layer by layer
"""zs,用来所有中间层和输出层在一次前向计算过程中的线性输出值,即z值。该值记录下来,以供后期使用BP算法求每个b和w的梯度。
"""
zs = [] # list to store all the z vectors, layer by layer ,zs的每个元素为本batch的x对应的z为列构成的矩阵。
"""
通过一次正向计算,将中间层和输出层所有的z值和a值全部计算出来,并存储起来。供接下来求梯度使用。
"""
for b, w in zip(self.biases, self.weights):
#print(w.shape)
#print(np.dot(w, activation).shape)
#print(b.shape)
z = np.dot(w, activation)+b #z为本batch的x对应的z为列构成的矩阵。
zs.append(z)
activation = sigmoid(z)
activations.append(activation)
"""
以下部分是采用BP算法求解每个可训练参数的计算方法。是权重更新过程中的关键。
"""
# backward pass
# 求出输出层的delta值
delta = ((activations[-1]-y) * sigmoid_prime(zs[-1]))
nabla_b[-1] = delta.mean(axis=1).reshape(-1, 1)
nabla_w[-1] =np.dot(delta,activations[-2].transpose())/batch_num
# Note that the variable l in the loop below is used a little
# differently to the notation in Chapter 2 of the book. Here,
# l = 1 means the last layer of neurons, l = 2 is the
# second-last layer, and so on. It's a renumbering of the
# scheme in the book, used here to take advantage of the fact
# that Python can use negative indices in lists.
for l in range(2, self.num_layers):
z = zs[-l]
sp = sigmoid_prime(z)
delta = (np.dot(self.weights[-l+1].transpose(), delta) * sp)
nabla_b[-l] = delta.mean(axis=1).reshape(-1, 1)
nabla_w[-l] =np.dot(delta,activations[-l-1].transpose())/batch_num
return (nabla_b, nabla_w)
##梯度计算后,如何更新各权值
def update_mini_batch(self, mini_batch, eta):
"""Update the network's weights and biases by applying
gradient descent using backpropagation to a single mini batch.
The ``mini_batch`` is a list of tuples ``(x, y)``, and ``eta``
is the learning rate."""
""" 初始化变量,去存储各训练参数的微分和。
"""
nabla_b = [np.zeros(b.shape) for b in self.biases]
nabla_w = [np.zeros(w.shape) for w in self.weights]
""" 循环获取batch中的每个数据,获取各训练参数的微分,相加后获得各训练参数的微分和。
"""
x_batch=None
y_batch=None
for x, y in mini_batch:
if( x_batch is None):
x_batch=x
else:
x_batch=np.append(x_batch,x,axis=1)
if( y_batch is None):
y_batch=y
else:
y_batch=np.append(y_batch,y,axis=1)
delta_nabla_b, delta_nabla_w = self.backprop(x_batch, y_batch)
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-eta*nw
for w, nw in zip(self.weights, nabla_w)]
self.biases = [b-eta*nb
for b, nb in zip(self.biases, nabla_b)]
F. 小白对于神经网络的数据集的问题
标准数据集是神经网络的训练基础。训练就相当于条件反射中的条件,是已知的条件。来源是“经验”,是已知的映射组,当在神经网络中载入标准数州磨据集后,神经网络随山盯机生成一组矩阵,用矩阵处理标准集中的输入集后,用所得结果与标准输出集比较,将误差提出后根据误差,向减少误差的方向修改矩阵组,然后重复多次以后,误差减逗迹和小到一定程度,标准输入集输入网络后能得到标准输出集,训练完成。这个矩阵组就是神经网络模型。神经网络就是用电脑在标准数据集上总结经验,来对新的输入进行映射
G. 构建ResNet卷积神经网络
2015年,微软亚洲研究院的何凯明团队发布了一种特殊的卷积神经网络——残差神经网络(ResNet)。在残差神经网络出现之前,最深的深度神经网络只有二三十层左右,这该神经网络却可以在实验中轻松达到上百层甚至上千层,另外不会占用过多训练时间,也正因如此,图像识别准确率有了显着增强。此模型更是在同年的ImageNet大赛中,获得图像分类、定位、检测三个项目的冠军。在国际大赛上取得如此优异的成绩,证明了残差神经网络是个实用性强且优异的模型。在本研究中的猫狗二分类的实验中,也是基于残差神经网络来构建分类模型的。
在本文中我们将把kaggle猫狗数据集应用于ResNet-18和ResNet-50网络模型。使用Resnet来探究当前使用卷积神经网络的准确率。如图4-1为ResNet的经典网络结构图——ResNet-18。
ResNet-18都是由BasicBlock组成,从图4-2也可得知50层及以上的ResNet网络模型由BottleBlock组成。在我们就需要将我们预处理过的数据集放入现有的Resnet-18和ResNet-50模型中去训练,首先我们通过前面提到的图像预处理把训练图像裁剪成一个96x96的正方形尺寸,然后输入到我们的模型中,这里就介绍一下ResNet-18的网络模型的结构,因为ResNet50与第五章的ResNet-34模型结构相仿。
ResNet-18的模型结构为:首先第一层是一个7×7的卷积核,输入特征矩阵为[112,112,64],经过卷积核64,stride为2得到出入特征矩阵[56,56,64]。第二层一开始是由一个3×3的池化层组成的,接着是2个残差结构,一开始的输入的特征矩阵为[56,56,64],需要输出的特征矩阵shape为[28,28,128], 然而主分支与shortcut的输出特征矩阵shape必须相同,所以[56,56,64]这个特征矩阵的高和宽从56通过主分支的stride为2来缩减为原来的一半即为28,再通过128个卷积核来改变特征矩阵的深度。然而这里的shortcut加上了一个1x1的卷积核,stride也为2,通过这个stride,输入的特征矩阵的宽和高也缩减为原有的一半,同时通过128个卷积核将输入的特征矩阵的深度也变为了128。第三层,有2个残差结构,输入的特征矩阵shape是[28,28,128],输出特征矩阵shape是[14,14,256], 然而主分支与shortcut的输出特征矩阵shape必须相同,所以[14,14,256]这个特征矩阵的高和宽从14通过主分支的stride为2来缩减为原来的一半即为7,再通过128个卷积核来改变特征矩阵的深度。然而这里的shortcut加上了一个1×1的卷积核,stride也为2,通过这个stride,输入的特征矩阵的宽和高也缩减为原有的一半,同时通过256个卷积核将输入的特征矩阵的深度也变为了256。第四层,有2个残差结构,经过上述的相同的变化过程得到输出的特征矩阵为[7,7,512]。第五层,有2个残差结构, 经过上述的相同的变化过程得到输出的特征矩阵为[1,1,512]。接着是平均池化和全连接层。
H. 从零开始用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:https://youtu.be/tIeHLnjs5U8
整合并完成一个实例
既然我们已经有了包括前向传播和反向传播的完整 Python 代码,那么就将其应用到一个例子上看看它是如何工作的吧。
神经网络可以通过学习得到函数的权重。而我们仅靠观察是不太可能得到函数的权重的。
让我们训练神经网络进行 1500 次迭代,看看会发生什么。 注意观察下面每次迭代的损失函数,我们可以清楚地看到损失函数单调递减到最小值。这与我们之前介绍的梯度下降法一致。
让我们看看经过 1500 次迭代后的神经网络的最终预测结果:
经过 1500 次迭代训练后的预测结果
我们成功了!我们应用前向和方向传播算法成功的训练了神经网络并且预测结果收敛于真实值。
注意预测值和真实值之间存在细微的误差是允许的。这样可以防止模型过拟合并且使得神经网络对于未知数据有着更强的泛化能力。
下一步是什么?
幸运的是我们的学习之旅还没有结束,仍然有很多关于神经网络和深度学习的内容需要学习。例如:
? 除了 Sigmoid 以外,还可以用哪些激活函数
? 在训练网络的时候应用学习率
? 在面对图像分类任务的时候使用卷积神经网络
我很快会写更多关于这个主题的内容,敬请期待!
最后的想法
我自己也从零开始写了很多神经网络的代码
虽然可以使用诸如 Tensorflow 和 Keras 这样的深度学习框架方便的搭建深层网络而不需要完全理解其内部工作原理。但是我觉得对于有追求的数据科学家来说,理解内部原理是非常有益的。
这种练习对我自己来说已成成为重要的时间投入,希望也能对你有所帮助