第一章:深度学习内容
主动学习
- 在某些情况下,没有类标签的数据相当丰富而有类标签的数据相当稀少,并且人工对数据进行标记的成本又相当高昂。在这种情况下,我们可以让学习算法主动地提出要对哪些数据进行标注,之后我们要将这些数据送到砖家那里让他们进行标注,再将这些数据加入到训练样本集中对算法进行训练。这一过程叫做主动学习。
半监督学习
- 部分有标签,用无标签数据加强有标签学习
增强学习
- 类似alphago
loss function的选择
当我们用sigmoid函数作为神经元的激活函数时,最好使用交叉熵代价函数来替代方差代价函数,以避免训练过程太慢。因为sigmoid会产生一个求导后代入激活值的项,这一项会比较小。然后交叉熵代价函数就不会有这个缺点。
收敛速度与激活函数,代价函数都有很大的关系。
通过添加一个权重衰减项来修改代价函数,使得代价函数是凸函数
validation data
- Validation set: a set of examples used to tune the parameters of a classifier In the MLP case, we would use the validation set to find the “optimal” number of hidden units or determine a stopping point for the back-propagation algorithm
SGD算法的比较
GD是最naive的
SGD
Momentum
就是当前下降的方向要与之前下降的方向加权平均。这里的\gamma一般取0.9就行了。直观上可以减少震荡,能更快的收敛
NAG
NAG(Nesterov accelerated gradient)核心思想就是利用Momentum预测下一步的梯度,而不是使用当前的\Vtheta。
Adagrad
通过算法让学习速率的选择更加容易
其学习率是单调递减的,训练后期学习率非常小
其需要手工设置一个全局的初始学习率
rmsprop,adadelta
是基于adagrad的,两者差不多
Adam
神器,首先Adam利用了AdaGrad和RMSProp在稀疏数据上的优点。对初始化的偏差的修正也让Adam表现的更好。
总结
虽然针对不同的任务,应该尝试不同的优化算法。我觉得实在不知道用什么就试试Adam。但是在训练过程中自己调整一下学习速率对于复杂优化目标是必要的(个人观点),比如一个epoch乘以0.5啥的。这就得靠经验了。别以为最普通的SGD不行,还是会被很多人使用,因为谁都不知道训练复杂模型的过程中会发生什么,而SGD是最能保证收敛的
正则化
OK,来个一句话总结:L1范数和L0范数可以实现稀疏,L1因具有比L0更好的优化求解特性而被广泛应用。
另一个青睐于稀疏的理由是,模型更容易解释。
大家对稀疏规则化趋之若鹜的一个关键原因在于它能实现特征的自动选择。
从学习理论的角度来说,L2范数可以防止过拟合,提升模型的泛化能力。
主要的CNN网络
Alexnet
RELU
Dropout
LRN:对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力。
数据增强,随机地从(256,256)的原始图像中截取(224,224)大小的区域
在CNN中使用重叠的最大池化。
VGGnet:牛津加deepmind
通过反复堆叠3´3的小型卷积核和2´2的最大池化层,VGGNet成功地构筑了16~19层深的卷积神经网络。
VGG有A到E多种结构,网络逐渐加深
3个串联的3´3的卷积层,拥有比1个7´7的卷积层更少的参数量,只有后者的。最重要的是,3个3´3的卷积层拥有比1个7´7的卷积层更多的非线性变换(前者可以使用三次ReLU激活函数,而后者只有一次),使得CNN对特征的学习能力更强。
1´1的卷积也是很有效的,但是没有3´3的卷积好,大一些的卷积核可以学习更大的空间特征。
VGGNet在训练时有一个小技巧,先训练级别A的简单网络,再复用A网络的权重来初始化后面的几个复杂模型,这样训练收敛的速度更快
Inception Net - Google
Inception V1有22层深,比AlexNet的8层或者VGGNet的19层还要更深。但其计算量只有15亿次浮点运算,同时只有500万的参数量,仅为AlexNet参数量(6000万)的1/12,却可以达到远胜于AlexNet的准确率,可以说是非常优秀并且非常实用的模型。
第一,参数越多模型越庞大,需要供模型学习的数据量就越大,而目前高质量的数据非常昂贵;第二,参数越多,耗费的计算资源也会更大。
去除了最后的全连接层,用全局平均池化层(即将图片尺寸变为1´1)来取代它。全连接层几乎占据了AlexNet或VGGNet中90%的参数量,而且会引起过拟合,去除全连接层后模型训练更快并且减轻了过拟合。
Inception V1中精心设计的Inception Module提高了参数的利用效率,其结构如图10所示。这一部分也借鉴了NIN的思想,形象的解释就是Inception Module本身如同大网络中的一个小网络,其结构可以反复堆叠在一起形成大网络。
因此一个“好”的稀疏结构,应该是符合Hebbian原理的,我们应该把相关性高的一簇神经元节点连接在一起。在普通的数据集中,这可能需要对神经元节点聚类,但是在图片数据中,天然的就是临近区域的数据相关性高,因此相邻的像素点被卷积操作连接在一起。而我们可能有多个卷积核,在同一空间位置但在不同通道的卷积核的输出结果相关性极高。因此,一个1´1的卷积就可以很自然地把这些相关性很高的、在同一个空间位置但是不同通道的特征连接在一起,这就是为什么1´1卷积这么频繁地被应用到Inception Net中的原因。
Inception V2学习了VGGNet,用两个3´3的卷积代替5´5的大卷积。还增加了batch normaliztion
而Inception V3网络则主要有两方面的改造:一是引入了Factorization into small convolutions的思想,将一个较大的二维卷积拆成两个较小的一维卷积,比如将7´7卷积拆成1´7卷积和7´1卷积,或者将3´3卷积拆成1´3卷积和3´1卷积,如图12所示。一方面节约了大量参数,加速运算并减轻了过拟合(比将7´7卷积拆成1´7卷积和7´1卷积,比拆成3个3´3卷积更节约参数),同时增加了一层非线性扩展模型表达能力。
RESnet - Microsoft
ResNet最初的灵感出自这个问题:在不断加神经网络的深度时,会出现一个Degradation的问题,即准确率会先上升然后达到饱和,再持续增加深度则会导致准确率下降。这并不是过拟合的问题,因为不光在测试集上误差增大,训练集本身误差也会增大。假设有一个比较浅的网络达到了饱和的准确率,那么后面再加上几个的全等映射层,起码误差不会增加,即更深的网络不应该带来训练集上误差上升。而这里提到的使用全等映射直接将前一层输出传到后面的思想,就是ResNet的灵感来源。
ResNet相当于将学习目标改变了,不再是学习一个完整的输出,只是输出和输入的差别,即残差。ResNet有很多旁路的支线将输入直接连到后面的层,使得后面的层可以直接学习残差,这种结构也被称为shortcut或skip connections。
Inception Resnet
两者结合
NIN
- 我们知道CNN高层特征其实是低层特征通过某种运算的组合。于是作者就根据这个想法,提出在每个局部感受野中进行更加复杂的运算,提出了对卷积层的改进算法:MLP卷积层。另一方面,传统的CNN最后一层都是全连接层,参数个数非常之多,容易引起过拟合(如Alexnet),一个CNN模型,大部分的参数都被全连接层给占用了,故这篇paper提出采用了:全局均值池化,替代全连接层。
- 全局均值池化:
本文提出采用全局均值池化的方法,替代传统CNN中的全连接层。与传统的全连接层不同,我们对每个特征图一整张图片进行全局均值池化,这样每张特征图都可以得到一个输出。这样采用均值池化,连参数都省了,可以大大减小网络,避免过拟合,另一方面它有一个特点,每张特征图相当于一个输出特征,然后这个特征就表示了我们输出类的特征。这样如果我们在做1000个分类任务的时候,我们网络在设计的时候,最后一层的特征图个数就要选择1000。
天才!
总结
VGG和Alex只是深度上有所提升,而后面两个则是有本质变化。关键在于减少参数的同时又增加了深度!
第二章:图像检索
图像检索按描述图像内容方式的不同可以分为两类,一类是基于文本的图像检索(TBIR, Text Based Image Retrieval),另一类是基于内容的图像检索(CBIR, Content Based Image Retrieval)。
往往会选择那些抗干扰性比较好的不变性局部特征,比如SIFT1、SURF2、ORB3等,并以此为基础通过不同的编码方式构建图像的全局描述
对于相同类别图像检索,面临的主要问题是属于同一类别的图像类内变化巨大,而不同类的图像类间差异小
哈希编码主要是为了速度快
相比基于树结构的图像检索方法,基于哈希的图像检索方法由于能够将原特征编码成紧致的二值哈希码,使得基于哈希的图像检索方法能够大幅的降低内存的消耗,并且由于在计算汉明距离的时候可以使用计算机内部运算器具有的XOR异或运算,从而使的汉明距离的计算能够在微秒量级内完成,从而大大缩减了单次查询响应所需要的时间
局部敏感哈希被认为是高维空间(比如成百上千维)快速最近邻搜索的重要突破,它在构造哈希函数的时候采用随机超平面的方法,即使用随机超平面将空间分割成很多子区域,每一个子区域可以被视为一个”桶”,如图2.1右图所示。在构建阶段,局部敏感哈希仅需要生成随机超平面,因而没有训练的过程;在索引阶段,样本被映射成二进制哈希码,如图2.1右图示意的二进制哈希码,具有相同的二进制哈希码的样本被保存在同一个“桶”中;在查询阶段,查询样本通过同样的映射后可以锁定查询样本位于哪个“桶”中,然后在锁定的”桶”中将查询样本与该“桶”中的样本进行逐一的比较,从而得到最终的近邻。
LSH, unsupervised
第三章:RNN
LSTM只是有三份原来的W,一个叫input,一个output,一个forget。用了一种gating behavior,其实可以看成一个黑盒子。
第四章:Flask
Flask Login
通过session保存用户的登陆状态。设为 'strong' 时,Flask-Login 会记录客户端 IP 地址和浏览器的用户代理信息,如果发现异动就登出用户。
之后login,logout都是很简单的调用函数
而且还提供多种装饰器来限定路由,如@login_required
Flask-SQLalchemy
- 多对多,要使用关联表。如class和students,要加一个表叫registrations
class Comment(db.Model):
__tablename__ = 'comments'
id = db.Column(db.Integer, primary_key=True)
body = db.Column(db.Text)
body_html = db.Column(db.Text)
timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
disabled = db.Column(db.Boolean)
author_id = db.Column(db.Integer, db.ForeignKey('users.id'))
post_id = db.Column(db.Integer, db.ForeignKey('posts.id'))
class User(db.Model):
# ...
comments = db.relationship('Comment', backref='author', lazy='dynamic')
class Post(db.Model):
# ...
comments = db.relationship('Comment', backref='post', lazy='dynamic')