这里总结了李宏毅老师的机器学习的课程。首先我们将会了解到机器学习的概念,但是课程的主要观点将会聚焦到Deep Learning。进行了解之后我们会学习到监督学习( supervised learning )的相关网络,还有自监督学习(self- supervised learning)的相关知识,包括生成对抗网络(GAN),BERT,Tansformer等。后面还会讲到强化学习(Reinforcement learning)、可解释化的AI、模型攻击(model attack)、领域自适应(domain adaption)、模型压缩(network compression)、机器终身学习(long-life learning )和元学习(meata learning)
寻找一个函数,解决一个问题。
第一步:设计一个带有未知参数的函数
第二步:定义一个Loss函数
第三步:不断优化更新函数
这里有一个小知识点,局部最优解往往不是神经网络常遇到的问题。
线性的神经网络能解决的问题往往是有限的,例如只能解决简单的回归问题,和二分类的问题。但是像 XOR 异或问题却无法解决。然而我们遇到的问题大多数是非线性的。
那么我们如何让神经网络变成非线性的呢?
这就是我们经常提到的激活函数了。
我们都知道常用的是sigmoid, tanh,relu。
那我们为什么激活函数不是线性的呢?当我们把线性函数带进去的时候会发现,神经网络仍是线性的。所以激活函数都是非线性的。
关于激活函数的内容可参考:
【1】https://zhuanlan.zhihu.com/p/260970955
【2】https://www.jianshu.com/p/1dfe5e05a75c
【3】https://zhuanlan.zhihu.com/p/61616349
【4】https://www.jianshu.com/p/aad9deccbc27
深度学习和是在机器学习的基础上,将神经网络不断地堆叠,让网络变得像一条深深得通道。这便是深度学习。
理论上来说神经网络就是一个巨型的函数,将输入输进去,通过计算就能得出结果。与其把神经网络做的那么深入,为何不直接把神经网络设置成一个只有一层的有很多参数的网络呢?
因为通过实践发现,深层的网络往往能学习到时间或者空间上的更深层次的信息,这是单层神经网络无法学习得到的。
这里需要解决的问题是在我们训练神经网络的时候,会遇到很多的问题使得神经网络的训练效果并不好。这里是具体分析其原因。
这种情况出现主要是两个原因:
如何区分这两种情况呢?
构建深的model,但是loss更加大了,那就是优化器的问题所在了,如果loss变小了,那就是网络不够复杂的问题。
这里极有可能是过拟合( overfitting)了。也就是说神经网络的模型足够复杂,直接把训练集里面的样本直接记下来了。但是遇到新的问题就不会解决了。
解决方案:
参考:
【1】https://www.jianshu.com/p/995516301b0a
【2】https://www.jianshu.com/p/2155e59d14a4
【3】https://www.jianshu.com/p/ad00cf171353
使用更好的优化器,例如Adam等,也可以通过设置learning rate,加速其学习的步伐。还可以使用batch,批量训练。
极有可能是遇到了局部最优解和鞍点,他俩的共同特征就是导数为0,也就使得梯度卡住了,这样的点叫做:critical point。其实实际训练中local minima 是不常见的,我们往往卡在鞍点(saddle point)。通常是通过计算H的值,就能判断是什么情况:
答案肯定是否定的,learning rate的大小需要随着训练不断变化。例如,loss function一开始的坡度很大,我们要使用学习率控制跨步小一点,别直接飞出天际。当坡度非常小的时候,我们要给它一点步伐,别卡住了。这便能够一定程度上解决critical point的问题。
我们通常遇到的问题就是,训练着,结果loss卡住不下降了,难道真的是遇到critical point了嘛?在实际情况中上面说的critical point往往不是问题。它能通过好的优化器很大程度上解决。
那么都有怎么样的解决方案呢?
我们通常将总数居分成三份:训练集,验证集,测试集。我们分别用不同的网络对training set进行训练,在验证集上选出最优秀的那一个,那样的话就比较科学。
当遇到数据集不够的时候可以使用K折交叉验证。
可参考:
【1】https://www.jianshu.com/p/2155e59d14a4
【2】https://www.jianshu.com/p/26b57b25c56d
卷积神经网络主要处理的是图片相关的问题,例如图片分类,如图片分割等。最大的特点是,将权重变成了卷积核这样的形式。卷积核 == 权重矩阵。
可以将其看作是一种特殊的全连接层的网络。其原理是利用一个个的卷积核扫描去探测图片中的重要特征信息。卷积核的个数决定了该层输出的通道数。
虽然一个33的卷积核看起来很小,但是当网络变深的时候,33的区域可能映射到前面的区域是很大的。例如,第一层的时候我们确实检测的范围是3x3,但是在第二个卷积层中,其实3x3的格子在原来的图片中对应的是5x5。
可以通过增加一层:special transformer layer
通过矩阵乘法,将图片旋转,缩放,平移。但是有一个缺点是无法进行梯度下降。
VGG、GoogLeNet、ResNet、ResNet各种变种、DenseNet等
GoogLeNet文章中提出优化模型有两种途径:提高深度或是宽度。但是这两种方法都存在局限性:1.参数太多,容易过拟合,若训练数据集有限;2.网络越大计算复杂度越大,难以应用;3.网络越深,梯度越往后穿越容易消失,难以优化模型。
GoogLeNet正是围绕着这两个思路提出的,其通过构建密集的块结构——Inception(如下图)来近似最优的稀疏结构,从而达到提高性能而又不大量增加计算量的目的。
ResNet解决模型深,易造成梯度消失,继续训练时,很难再更新参数,很难学到特征
可参考:
【1】https://blog.csdn.net/lianghe77/article/details/104486543
【2】https://blog.csdn.net/wangzi11111111/article/details/88945699
注意力机制主要解决的是多输入的问题,例如句子的翻译,每个句子的长度并不是固定的,那么该怎么样操作使得神经网络能够接收,序列信息。
我们认为序列内部是有相关性的,例如I LOVE YOU。主语和谓语之间是有联系的。再比如说,30号上午,北京到天津的航班。这里面的地面也是有联系的。所以主要问题变成了,如何确定这种相关系数?
注意力机制提出了三个注意力的系数:q、k、v
I: input, O:ouput, Q={q1,q2,...qn}, K={k1,k2...kn}, V={v1,v2...vn}
进阶版的注意力机制:multi-head self-attention,多head,就是用多个wq矩阵wk,wv矩阵。理解一下就是说,有不同的关系和理解。
在语音辨识中可能一句语音非常长,如使用self-attention的话输入就会及其大,我们或许不需要看到很远的距离,我们只系要看临近之间的关系。
self-attention 和CNN的关系:
可参考:
【1】https://www.csdn.net/tags/NtTacgxsMTAxODMtYmxvZwO0O0OO0O0O.html
自注意力机制和RNN的比较:
自注意力机制还可以用在图神经网络中:
解决的也是输入输出不确定的应用场景。与self-attention不同,他不是一次性输出N个结果,而是每次输入一个x,输出一个y。
有一个中间结果会被保存下来,一起作为下一层的输入。
演化出了Elman NN和Jordan NN,其不同点仅在于a的取值。其他结构基本没有变化。还有一种双向的RNN叫做:Bidirectional RNN,他设计了正反两个神经网络,共同输出一个结果。其解释为,能够将整个序列了解的更好。
这个网络是一种特殊的RNN。不难发现RNN希望神经网络能够记住一些内容,但是根据RNN网络结构可以发现,它只对上一个输入有考虑。而且关于存储逻辑设计的不是很合理。LSTM重新设计了关于memory的设计。
LSTM设计了三个门来控制,存储单元的存储与否以及怎么样存储,将这三个们封装成一个special Neuron, 已拥有四个输入和一个输出。下面是他的结构:
他的核心结构是长这样的,其具体是怎么运行的呢?
每一个输入不仅是考虑x,还会考虑记忆和上一个单词的输出。也可以堆叠出多层的LSTM神经网络。
可参考:
【1】https://www.freesion.com/article/68911223173/
依然致力于解决seq to seq的问题。多用于文本和自然语言的处理。例如语音翻译,多label分类,目标检测等
transformer的整体结构可分为encoder 和 decoder两个部分,这两个部分都是前面所说的self-attention机制的一个堆叠。
inputs输入过后有一个positional encoding,就是为了确保位置信息。然后输入到多head的自注意力机制里面,与上面说到的self-attention不同,他多了一个Feed Forward,是一个两层的全连接,第一层的激活函数为ReLU,第二层不适用激活函数。
还有一个区别是多了一个add&norm
,这是类似于ResNet的一个残差的设计。
decoder的输入与以往的神经网络不一样,他不是一次性将答案输给他,而是第一次输入START,机器预测出“机”。然后把预测出来的“S+机”作为输入,预测出下一个字“器”一直这样执行下去。但是我们也不难看出缺点,有可能就会一步错,步步错。
Masked Multi-Head Attention的结构和Multi-Head Attention的结构是一样的,只是输入时被掩盖的数据。
Encoder 的 Multi-Head Attention 的结构和 Decoder 的 Multi-Head Attention 的结构也是一样的,只是 Decoder 的 Multi-Head Attention 的输入来自两部分,K,V 矩阵来自Encoder的输出,Q 矩阵来自 Masked Multi-Head Attention 的输出。
可参考:
【1】https://blog.csdn.net/qq_48314528/article/details/122160800
【2】https://www.jianshu.com/p/6ced23376003
【3】https://zhuanlan.zhihu.com/p/403433120
李宏毅老师还介绍了很多transformer的变种,那就已经听不懂了。
前面说过self-attention会将序列长度为N 的输入输出为一个N*N的矩阵。但是我们的输入极有可能是一个非常非常长的向量,这样的话,这个输出的矩阵将会是非常大的,如果在用多个head的话,那计算量又将翻倍。这里讲述了一些方法加速训练。
第一种方式:Local Attention / Truncated Attention / Global Attention。就是说,可能我并不需要看到整个句子之间的关系,我可以选择性的去跳过一些计算点。或者说,不同的head,我们关注的点有不一样。
第二种方法叫做:Clustering(分类归并)。先把sequence的原始向量们计算出的query和key拿出来, 进行聚类, 把比较近的分类在一起, 比较远的则分别属于不同的clustering.然后在计算attention matrix的时候, 只有在query和key被归类到同一个clustering种类里才会去计算他们的attention, 否则直接设置为0.这样就可以加快attention matrix的计算.
但是即使是clustering也是基于人类的理解来判断的.
第三种:利用线性代数的方法,加速运算。
计算结果一样,计算量不一样。
可参考:
【1】https://blog.csdn.net/q1347688324/article/details/123778585