1.神经网络基础

1.感知机

就是一个很简单的模型,给定输入,输出0或1


2.多层感知机(MLP)


网络是密集的(dense),意味着一个层中的每一个神经元都会与前一层的每个神经元相连接,并且连接到下一层中的所有神经元。

3.训练感知机的问题以及应对之道

我们希望我们的学习是一点一点进步的,而不是跳跃的,对于下面函数来说,它的输出有一个很大的跳跃,不能够逐步学习。


所以我们需要一个函数,从0逐步变化到1,没有间断。从数学上讲,这意味着我们需要一个连续的函数,它允许我们计算导数

激活函数1 --sigmoid


如下图所示,当输入变化时,它在(0,1)中的输出变化很小。从数学上讲,该函数是连续的。下面的图表示一个典型的Sigmoid函数


sigmoid的表现与感知机是很相似的,但是却能逐步变化。

激活函数2 ---ReLU

f(x)=max(0,x)

ReLU非常好,因为其常常能产生很好的实验结果



4.激活函数

它是深度学习算法的基本构件,可以逐渐减少我们网络的错误。


5.实例入门---手写数字识别

mnist数据集,大家都很清楚了,训练集有60000个例子,测试集有10000个例子。每个mnist都是灰度图片,大小为28*28.

5.1独热编码(One-hot encoding (OHE))

将类别特征转换为数字特征,将数字0-9转化为一个10维向量。


5.2用keras定义一个简单的神经网络

先从简单入手。说明一下:我们将数据转化到0,1之间,格式为float32

from keras.models import Sequential
import numpy as np
from keras.datasets import mnist
from keras.layers import Dense,Activation
from keras.optimizers import SGD
from keras.utils import np_utils
np.random.seed(1671)#为了可复现

#参数定义
NB_EPOCH=200
BATCH_SIZE=128
VERBOSE=1
NB_CLASS=10
OPTIMIZER=SGD()
VALIDATION_SPLIT=0.2

#数据
(X_train,y_train),(X_test,y_test)=mnist.load_data()
RESHAPE=784
#将数据展开
X_train=X_train.reshape(60000,  RESHAPE)
X_test=X_test.reshape(10000,RESHAPE) 
#标准化
X_train/=255
X_test/=255
y_train=np_utils.to_categorical(y_train,NB_CLASS)
y_test=np_utils.to_categorical(y_test,NB_CLASS)

#定义模型
model=Sequential()
model.add(Dense(NB_CLASS,input_shape=(RESHAPE,)))
model.add(Activation('softmax'))

模型定义完成之后,必须要compile它才能被keras的backend(tensorflow或theano)执行。compile有以下选择:

  1. 需要优化器optimizer在训练模型的时候更新权重
  2. 需要loss function去指引方向
  3. 需要评估训练模型

loss function的选择有:

1.MSE:mean squared error,通过平方可以使错误更加明显


2.Binary cross-entropy:适用于二元预测


3.Categorical cross-entropy: 


metrics如下:

Accuracy:这是相对于目标的正确预测的比例。

Precision:This denotes how many selected items are relevant for a multilabel classification

Recall:This denotes how many selected items are relevant for a multilabel classification

model.compile(loss='categorical_crossentropy',optimizer=OPTIMIZER,metrics=['accuracy'])当模型

一旦模型compile完毕, 我们就可以用fit函数去训练了,它有以下几个参数:

  • epochs:这是模型暴露于训练集的次数。在每次迭代中,优化器试图调整权重,从而使目标函数最小化。
  • batch_size: 这是在优化器执行权重更新之前观察到的训练实例数。

keras的模型训练很是简单:

history=model.fit(X_train,y_train,batch_size=BATCH_SIZE,epochs=NB_EPOCH,verbose=VERBOSE,
                  validation_split=VALIDATION_SPLIT)
我们保留了一部分的培训集用于验证。关键的思想是,我们保留一部分培训数据,以便在训练过程中测量验证的性能。这是任何机器学习任务的良好做法,我们将在所有示例中采用这一做法


一旦对模型进行了训练,我们就可以在包含新的看不见的例子的测试集上对其进行评估,这样我们就可以得到目标函数所达到的最小值和评价度量所达到的最佳值。

请注意,训练集和测试集当然是严格分开的。在一个已经用于培训的例子上评估模型是没有意义的。学习本质上是一个旨在概括未见观察到的观察,而不是记住已经知道的东西的过程。

score=model.evaluate(X_test,y_test,verbose=VERBOSE)
print('Test score:',score[0])
print('Test accuracy:',score[1])


我们可以看到,最后的准确率大概是在92.77


5.3添加隐藏层改进网络

from keras.models import Sequential
import numpy as np
from keras.datasets import mnist
from keras.layers import Dense,Activation
from keras.optimizers import SGD
from keras.utils import np_utils
np.random.seed(1671)#为了可复现

#参数定义
NB_EPOCH=200
BATCH_SIZE=128
VERBOSE=1
NB_CLASS=10
OPTIMIZER=SGD()
N_HIDDEN=128
VALIDATION_SPLIT=0.2

#数据
(X_train,y_train),(X_test,y_test)=mnist.load_data()
RESHAPE=784
#将数据展开
X_train=X_train.reshape(60000,  RESHAPE)
X_test=X_test.reshape(10000,RESHAPE) 
X_train=X_train.astype('float32')
X_test=X_test.astype('float32')

#标准化
X_train=X_train/255
X_test=X_test/255
y_train=np_utils.to_categorical(y_train,NB_CLASS)
y_test=np_utils.to_categorical(y_test,NB_CLASS)

#定义模型
model=Sequential()
model.add(Dense(N_HIDDEN,input_shape=(RESHAPE,)))
model.add(Activation('relu'))
model.add(Dense(N_HIDDEN))
model.add(Activation('relu'))
model.add(Dense(NB_CLASS))
model.add(Activation('softmax'))
model.summary()#输出信息


model.compile(loss='categorical_crossentropy',optimizer=OPTIMIZER,metrics=['accuracy'])

history=model.fit(X_train,y_train,batch_size=BATCH_SIZE,epochs=NB_EPOCH,verbose=VERBOSE,
                  validation_split=VALIDATION_SPLIT)

score=model.evaluate(X_test,y_test,verbose=VERBOSE)
print('Test score:',score[0])
print('Test accuracy:',score[1])

可以发现,正确率提高到了:97.65


5.4进一步提高with dropout层

我们的正确率已经提高到97.65%。这才的改进很简单,我们决定随机删除一些在我们内部隐藏层密集网络中传播的值。这是一种众所周知的正则化方法,令人惊讶的是,随机删除一些值可以提高我们的性能。

from keras.models import Sequential
import numpy as np
from keras.datasets import mnist
from keras.layers import Dense,Activation,Dropout
from keras.optimizers import SGD
from keras.utils import np_utils
np.random.seed(1671)#为了可复现

#参数定义
NB_EPOCH=250
BATCH_SIZE=128
VERBOSE=1
NB_CLASS=10
OPTIMIZER=SGD()
N_HIDDEN=128
VALIDATION_SPLIT=0.2
DROPOYT=0.3

#数据
(X_train,y_train),(X_test,y_test)=mnist.load_data()
RESHAPE=784
#将数据展开
X_train=X_train.reshape(60000,  RESHAPE)
X_test=X_test.reshape(10000,RESHAPE) 
X_train=X_train.astype('float32')
X_test=X_test.astype('float32')

#标准化
X_train=X_train/255
X_test=X_test/255
y_train=np_utils.to_categorical(y_train,NB_CLASS)
y_test=np_utils.to_categorical(y_test,NB_CLASS)

#定义模型
model=Sequential()
model.add(Dense(N_HIDDEN,input_shape=(RESHAPE,)))
model.add(Activation('relu'))
model.add(Dropout(DROPOYT))
model.add(Dense(N_HIDDEN))
model.add(Activation('relu'))
model.add(Dropout(DROPOYT))
model.add(Dense(NB_CLASS))
model.add(Activation('softmax'))
model.summary()#输出信息


model.compile(loss='categorical_crossentropy',optimizer=OPTIMIZER,metrics=['accuracy'])

history=model.fit(X_train,y_train,batch_size=BATCH_SIZE,epochs=NB_EPOCH,verbose=VERBOSE,
                  validation_split=VALIDATION_SPLIT)

score=model.evaluate(X_test,y_test,verbose=VERBOSE)
print('Test score:',score[0])
print('Test accuracy:',score[1])

5.5测试不同的优化器

Kears应用了更快的梯度下降的变体---SGD随机梯度下降,还有两个更高级的优化技术--Adam和RMSprop。除了SGD的加速组件之外,Adam和RMSprop还包含了动量的概念,这会增加计算代价,但会增加收敛速度。,现在我们是试试另外两个:

from keras.optimizers import SGD,Adam,RMSprop

正确率什么就不粘贴在这了。


当然,为了更好得到调参,你还可以更改dropout的数值。


5.6增加epochs

让我们再做一次尝试,把训练时间从20点增加到200点。不幸的是,这种选择使我们的计算时间增加了10,但却没有结果。实验不成功,但我们知道如果我们花更多的时间学习,我们就不一定会提高。学习更多的是采用智能技术,而不一定是花费在计算上的时间。

所以有时候增加epochs并没有用。

5.7控制优化器的学习率

我们还可以做另一次尝试,即更改优化器的学习参数。如下图所示,最优值接近0.001,这是优化者的默认学习速率


5.8增加隐藏神经元数目

我们可以再做一次尝试,即改变内部隐藏神经元的数量。我们用越来越多的隐藏神经元报告实验结果。从下图我们可以看到,随着模型复杂性的增加,运行时间显著增加,因为有越来越多的参数需要优化。




所示,隐藏层的神经元数目又不是越多越好,也要适度增加。

5.9增加batch_size的大小

梯度下降试图最小化训练集中提供的所有示例的成本函数,同时,对于输入中提供的所有特性。随机梯度下降是一个成本较低的变量,它只考虑批大小示例。因此,让我们通过更改这个参数来查看行为。


5.10总结一下:

因此,让我们总结一下:使用五种不同的变量,我们能够将性能从92.36%提高到97.93%。首先,我们在keras中定义了一个简单的层网络。然后,我们通过添加一些隐藏层来改进性能。然后,通过在我们的网络中添加几个随机丢包,并通过试验不同类型的优化器来提高测试集的性能。下面的表总结了当前的结果:


自己以后分析的时候也可以这样做

然而,接下来的两个实验并没有提供显著的改进。增加内部神经元的数量会创建更复杂的模型,并且需要更昂贵的计算,但它只提供少量的收益。如果我们增加训练时间,我们就会得到同样的经验。最后一个实验是的批处理尺寸

5.11采用正则化以避免过拟合

从直觉上看,一个好的机器学习模型应该在训练数据上获得较低的误差。从数学上讲,这相当于给定机器学习模型所建立的训练数据上的损失函数最小化。这是由以下公式表示的:


然而,这可能还不够。一个模型可能会变得过于复杂,以便捕捉所有由训练数据固有的关系。这种复杂性的增加可能会产生两个负面后果。首先,复杂模型可能需要大量时间才能执行。第二,复杂模型可以在训练数据上获得非常好的性能--因为所有经过训练的数据中的内在关系都被记忆了,但是在验证数据上的性能不太好--由于模型无法对新的未见数据进行泛化。同样,学习更多地是关于泛化而不是记忆。


据经验,如果在训练中,如果在最初的loss下降后,loss开始增加,那就说明过拟合了。

为了解决过拟合问题,我们需要一种方法来捕捉一个模型的复杂性,即一个模型可以有多复杂。有什么可以解决的呢?一个模型只不过是一个权重向量。因此,模型的复杂性可以方便地表示为非零权重的个数。换句话说,如果我们有两个模型,m1和m2,就可以实现。在损失函数方面,我们应该选择最简单的模型,它具有最小的非零权重。我们可以使用一个超参数>=0来控制拥有一个简单模型的重要性,如下面的公式


为了解决过拟合问题,我们需要一种方法来捕捉一个模型的复杂性,即一个模型可以有多复杂。有什么可以解决的呢?一个模型只不过是一个权重向量。因此,模型的复杂性可以方便地表示为非零权重的个数。换句话说,如果我们有两个模型,m1和m2,就可以实现。在损失函数方面,我们应该选择最简单的模型,它具有最小的非零权重。我们可以使用一个超参数>=0来控制拥有一个简单模型的重要性,如下面的公式


有三种不同的正则化:

  • L1 regularization (also known as lasso)
  • L2 regularization (also known as ridge)
  • Elastic net regularization

正则化是提高网络性能的好方法,特别是当存在明显的过拟合情况时。

keras支持三种正则化,添加也很简单:

from keras import regularizers 
model.add(Dense(64, input_dim=64, kernel_regularizer=regularizers.l2(0.01)))


5.12超参数调参

前面的实验给出了对网络进行微调的机会。然而,这个例子中的工作并不一定适用于其他例子。对于给定的网络,确实有多个参数可以优化(例如隐藏神经元的数量、batch_szie、epochs,以及根据网络本身的复杂性而进行的更多)


超参数调参是寻找这些参数的最优组合,使损失函数最小化的过程。关键思想是,如果我们有n个参数,那么我们可以想象它们定义了一个n维的空间,目标是在这个空间中找到与成本函数的最优值相对应的点。实现这个目标的一种方法是在这个空间中创建网格,系统地检查每个网格顶点的成本函数所假定的值,换句话说,参数被划分成批次,并通过蛮力法检查不同的值组合。


给定输入,有以下几种方法计算输出:

  • model.evaluate(): This is used to compute the loss values
  • model.predict_classes(): This is used to compute category outputs
  • model.predict_proba(): This is used to compute class probabilities

6.对于反向传播的实用综述

多层感知器通过一个叫做反向传播的过程从训练数据中学习。这个过程可以被描述为一发现错误就逐步纠正错误的方法。让我们看看这个过程是如何工作的。

请记住,每个神经网络层都有一组相关的权重,这些权重决定了给定一组输入的输出值。此外,请记住,一个神经网络可以有多个隐藏层

在开始时,所有的权重都有一些随机分配。然后对训练集中的每一个输入激活网络:值从输入阶段向前传播到进行预测的输出阶段(请注意,我们只使用几个带绿色虚线的值来保持以下图表的简单性,但实际上,所有的值都是向前传播的


由于我们知道训练集中的真实观测值,所以可以计算在预测中产生的误差。回溯的关键直觉是将误差传播回来,并使用适当的优化器算法(例如梯度下降)来调整神经网络的权重,目的是减少误差(同样为了简单起见,只表示几个错误值):


从输入到输出的前向传播和误差的后向传播过程被重复多次,直到误差达到预定的阈值。整个过程如下图所示:


特征表示输入,标签用于驱动学习过程。模型被更新,使损失函数逐渐最小化。在神经网络中,真正重要的不是单个神经元的输出,而是每一层调整的集体权重。因此,网络以预测增加的方式逐步调整其内部权重,正确地预测标签的数量也在增加。当然,使用正确的集合特征和具有质量标签的数据是最小化学习过程中的偏差的根本。






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值