前言
Geoffery Hinton 也曾经说过“AI 质疑者一错再错,未来还会继续被打脸”。而最近,我确实深深感受到了自己被打脸了🫢,因为原本也是认为AI是一个噱头而已。 在18~19年的时候,我在中科院的MML待了一年多,当时主要的topic是deep learning in super resolution。当时我接触的项目、阅读的所谓"三大"顶会的论文给我的感觉是虽然performance一直在刷,但好像并不能实用(虽然现在大部分的paper也都是如此)。而后来,我开始从事event-based vision的工作,也是大量的deep learning-based 的方法,一般我看到用learning-based的方法arvix论文都会直接跳过😂。 但随着我在robotic领域的研究,特别是event-based SLAM在传统方法上遇到了瓶颈转而用learning-based framework取得重大进展,以及特斯拉的FSD end-to-end 的vision-to-autonomous driving的突破,我开始重新思考AI的价值。 而回过头来发现之前在learning领域的积累几乎全部忘光光了,为此以本博客作为一个学习的笔记,重新复习以及学习一下AI的基础知识。Machine Learning
Supervised Learning
一些经典的Supervised Learning的例子,如下图。简单而言就是给定一些数据,然后给定一些label,然后让机器学习这个数据和label之间的关系,然后预测未知数据的label。 Supervised Learning可以分为两类:Classification和Regression。Classification是预测数据的label是离散的(分类),而Regression是预测数据的label是连续的(回归,拟合曲线,预测数值)。 回归一般是预测数字,可能有无穷多个值,而分类是预测类别,一般是有限个值。
Linear Regression Model (线性回归模型)
接下来通过实现一个线性回归模型来预测房价,来更好地理解Supervised Learning的基本原理。
流程可以总结如下图
而对于不同的方法其实关键就是f不一样,比如线性回归,那么可以定义为线性方程
f(x)=wx+b
不同的w与b有不同的表现,如下图
监督学习中,通过cost function不停更新迭代,优化w和b,使得f(x)/“y-hat”尽可能接近真实的y,也就是优化的目标(误差最小)。
Cost Function的直观理解
对于只有一个w参数的时候,cost function的图像如下,可以看到cost function是一个凸函数,只有一个最小值点。 而对于有两个参数的时候,cost function如下图所示:
gradient descent(梯度下降)
梯度下降是一个用来求函数最小值的算法。在机器学习中,我们使用梯度下降来最小化cost function。梯度下降的基本思想是:从一个随机的w和b开始,然后不断迭代更新w和b,使得cost function最小化。公式化表达如下:
直观理解梯度下降法,如下图所示。从不同的点开始,可能进入不同的局部最小值点。
公式表达如下:
而所谓的局部最小值,可以理解为w和b不再进一步更新了。接下来通过一维的角度来直观理解learning rate和derivative(应该是partial derivative,偏导)。
首先是偏导数,可以理解为函数在某一点的斜率,也就是函数在这一点的变化率。根据偏导数的符号决定更新的方向,如下图所示。
而learning rate可以理解为每次迭代的步长,也就是w和b更新的幅度。
如果学习率太小,那么收敛速度会很慢;而如果学习率太大,那么可能会错过最小值点(Overshoot or even diverge, 出现抖动但无法收敛的情况)。
对于固定的学习率,会伴随着Derivative变小,update step也变小,最终到达local minimum。
一般如果遇到cost 不下降或者下降方式有问题可以先通过设置较小的学习率,看loss是否下降,如果下降,那么就是学习率太大导致的,但如果还是不下降,那么可能是代码有其他bug。
Gradient Descent for Linear Regression
上述偏微分的详细推导如下: "Batch" gradient descent是指每次更新w和b都是基于(使用)所有的数据。
多变量线性回归(Linear Regression with Multiple Variables)
对应的线性回归模型可以表达如下: 进一步用矩阵/向量的形式表征如下:
Vectorization(向量化) for Coding
更进一步的,把x添加一个维度,全为1,这样就可以把b也合并到w中,从而可以进一步简化代码。 向量化可以大大提高代码的运行速度,因为不需要循环,而是直接用矩阵运算(在代码的底层可以理解为并行运算)。
Feature Scaling(特征缩放)
在我们面对多维特征问题的时候,我们要保证这些特征都具有相近的尺度,这将帮助梯度下降算法更快地收敛。 解决的方法是尝试将所有特征的尺度都尽量缩放到-1到1之间。
Polynomial Regression(多项式回归)
有时候,线性回归并不能很好地拟合数据,这时候可以考虑多项式回归。 注意,多项式回归的特征缩放会更加重要,因为不同的特征的尺度差异会更大。
线性回归代码实现
Logistic Regression(逻辑回归)
上一节的线性回归是用来预测连续值的(回归问题),而逻辑回归是用来预测离散值的,也就是分类问题(Classification)。 而分类问题又可以分为二分类(Binary Classification)和多分类(Multiclass Classification)。 而逻辑回归函数表达如下图所示
Decision Boundary(决策边界)
逻辑回归的cost function
为了让cost function是凸函数,可以用如下的cost function 由于y只有y=1和y=0两种情况,因此简化loss function还是比较直接的(更上图下方的公式基本一样的,只是换数学符号表示而已~):
Training Logistic Regression with Gradient Descent
逻辑回归代码实现
过拟合与正则化(Overfitting and Regularization)
欠拟合与过拟合是机器学习中常见的问题,欠拟合是模型过于简单,无法很好地拟合数据,而过拟合是模型过于复杂,过度拟合了训练数据,导致在测试数据上表现不佳。 解决过拟合的方法:
而正则化参数则是平衡拟合数据(overfit)以及减少权重(underfit)的作用。 接下来看看添加正则化项后的梯度下降:
Neural Network
而逻辑回归可以简单理解为一个神经网络,如下图所示: 而进一步地,如果输入的特征更多,那么可以进一步增加神经网络,如下图所示: 而实际上,每一层的所有输出都是下一层的输入,而并不是如上图般只有某几个输入对应的 下面看看对于人脸识别任务,不同层输出的特征不一样,第一层可能是一些边缘特征(一些轮廓),而第二层可能是一些形状特征(比如眼睛、嘴巴),第三层可能是一些更加复杂的特征(更大区域的特征)。而这些特征将由网络自己去学习而不再是人工提取。如下图所示:
numpy与tensorflow的数据转换
numpy中表达矩阵: 而需要注意的是1D vector与1 x 2和2 x 1的区别,如下图所示: numpy与tensorflow中的数据只是用不同的形式表征一个矩阵,但是实际上是一样的。
基于tensorflow的神经网络代码实现
一个简单的基于numpy实现的神经网络代码如下: 而基于tensorflow的代码实现如下: 接下来看看一个数字分类的模型。
基于python实现神经网络单层前向传播
进一步地简化代码(其实就是以function的形式,但是比起tensorflow的5行代码还是复杂不少~)如下:
向量化实现神经网络
首先是向量化代替循环,如下图所示: 矩阵乘法回顾: 代码实现矩阵乘法: 神经网络的向量化实现如下:
神经网络的训练
代码实现是非常直接的: 与logistic regression的对比:
激活函数的选择
之所以要激活函数,是因为线性函数的叠加还是线性函数,而激活函数可以使得神经网络可以拟合非线性函数。(无激活函数的神经网络本质上就相当于线性回归了)
Sigmoid VS ReLU:
对于输出层的激活函数。根据不同的任务选择不同的激活函数:二分类一般采用sigmoid,而回归问题则是线性激活函数,而如果回归问题中只有正数,那么可以用ReLU。
而对于中间层的激活函数。ReLU是最常用的,因为它的计算速度快,而且不会出现梯度消失的问题(也就是大于0的情况下,走向不会变平,从而使得梯度下降不会变慢,函数的梯度变小了就会导致梯度下降法走得更慢)
基于NN的系列实验代码
实验测试代码请见:
Multiclass Classification
Softmax Regression
Softmax Regression的cost function:
Neural Network with Softmax output
将Softmax Regression作为神经网络的输出层,如下图所示。进而可以实现多分类问题。 基于tensorflow的代码实现如下: 注意通过减少中间值的计算,可以进一步的提升精度: 对于逻辑回归而言,是否这样做是没有关系的,引入的误差不大,但是对于softmax regression而言,这样做会更好 因此整体的代码实现如下:
Multi-label Classification
此类问题应该指的是一个样本可以有多个标签,而不是多分类问题。如下所示,一张图片的输入对应多个label:
比梯度下降更好的优化方法(Adam Algorithm)
首先再次回忆一下基本的梯度下降法,而所谓的Adam Algorithm就是对梯度下降法的改进,就是自适应的调节学习率 此处略掉实际的推导过程,直接给出实现代码如下:
其他不同的网络层类型
之前介绍的一直都是dense layer: 最经典的应该是卷积层: 在后序deep learning部分应该是会详细介绍的,这里就不展开了。
基于NN实现手写数字识别(多分类问题)
Debugging a learning algorithm
对于一个算法,如果发现它的表现不好,那么可以采用的debug的方法有:
评估模型的方法
当模型存在过拟合的情况,如果是简单的函数,可以通过画图可视化,但是如果有多个输入的feature,很难通过图例来直观感受学习到的函数对数据的拟合情况 那么实际上可以把数据集分为训练集和测试集(例如,7、3分),训练集用来训练模型,而测试集用来评估模型的性能。而如果模型在训练集上表现很好,但是在测试集上表现很差,那么就是过拟合的情况。如下图所示: 而对于分类问题中,评估模型的方法则是:
模型的选择以及交叉验证集(cross validation)
直接的方式就是穷举几个模型,然后选择最好的: 但是上面这种做法会导致所选择的模型在测试集上表现好,再用来验证泛化能力就没有说服力了。 那么进一步的,可以将数据集分为三个:训练集、交叉验证集、测试集。训练集用来训练模型,交叉验证集用来选择模型,而测试集用来评估模型的性能。如下图所示: 而进一步的,验证模型的性能也是类似上面验证集的方式: 这样就通过交叉验证集来选择模型,而通过测试集来评估模型的性能,这样来评价模型的泛化能力则是公平的。
Bias and Variance
实际上感觉就是衡量是否过拟合和欠拟合的: 从另外一个角度来看,bias和variance的关系如下: 接下来看看正则化是如何影响bias和variance的: 类似于选择模型的方式,可以通过交叉验证集来选择正则化参数,而通过测试集来评估模型的性能。 进一步地,查看正则化参数对bias和variance的影响: 不过这部分的insight其实是比较少,基本这一整章节都是,质量很低,,怪不得youtube上视频都去掉这部分hhh
Learning Curves(学习曲线)
随着训练集的增加,训练集和交叉验证集的error的变化如下:
训练集上的error随着训练集的增加而增加,而交叉验证集上的error随着训练集的增加而减小。这是因为训练集越大,模型拟合全部数据是更难的,而又由于数据的样本量增大,模型的泛化能力也会增强,所以交叉验证集上的error会减小。
但是无论怎么用在交叉验证集上的error都比训练集上的error要大,这是因为模型是在训练集上训练的,所以训练集上的error会小于交叉验证集上的error。
注意更多的训练集只是对过拟合的模型有效的,对于欠拟合的模型是没有用的。因此虽然learning是数据驱动的,但是也是需要模型足够的强,大数据才有用!
而相反对于过拟合的模型,则是如下(图应该是没画好,是有机会比人类的性能要好的):
基于神经网络的bias与variance分析
前面都是基于线性回归的,此处看看基于神经网络的debugging,但本质上其实是一样的~ 此外一般通过合适的正则化参数,更大的神经网络模型一般会有更好的性能:
数据增广(data augmentation)
除了数据增广以外也可以通过合成/仿真的数据来训练模型。
迁移学习(transfer learning)
所谓的迁移学习就是将一个模型的参数作为另一个模型的初始参数(或fixed大部分,仅改变某些参数),然后再进行训练。这样可以加速模型的训练,提升模型的性能。 换句话说也就是利用别的task中的数据(训练好的模型),如下图所示: 而网络的可解析性其实是可以进行迁移学习的一个关键,如下所示,网络所训练的参数实现的功能是可以用于不同的task的(但注意,输入的类型需要一样,比如cv的输入都是image,一般不可能用NLP的网络来作为预训练模型~)
提升模型性能的总结及系列实验
Unsupervised Learning
与Supervised Learning不同,Unsupervised Learning是没有label的,也就是说,目标是找到数据的结构或者模式,比如聚类(clustering),异常检测(Anomaly Detection),降维(Dimensionality Reduction)等。
Clustering(聚类)
输入的数据并没有label,也没有办法告诉模型什么才是“正确”的答案。
K-means
首先是随机初始化K(下图是两个)个中心点,然后不断的迭代,直到中心点不再变化为止。如下图所示:
将上述过程总结为如下:
若出现某个中心点没有数据点与之对应,那么可以将其删掉变为k-1个中心点或者重新初始化
而对于数据之间界限没有明显的区分的情况,如下图所示:
K-means也有它的优化目标,两个step的本质都是将cost最小化。如下所示:
进一步的,初始化K-means也是非常重要的,不恰当的选择容易导致局部最优解。如下图所示:
不过可以通过多次计算,然后选择cost最小的结果,来避免局部最优解的问题。
而选择合适的K值也是非常重要的,可以通过如下的方法来选择:
基于Elbow(肘部)method的K选择方法如下:
进一步的,通过下游任务的效果来看,选择合适的K值也是一个方法:
Anomaly Detection(异常检测)
而实现检测最常用的方式就是density estimation(密度估计),也就是找到数据的分布。如下图所示: 基于Gaussian(Normal)Distribution的异常检测方法: 而对于多维特征,可以通过独立分布的原则来计算: 总结异常检测的流程如下: 接下来通过一个例子来更直观的认识异常检测: 对于异常检测,若有真实的label数据来评估模型的性能则可以比较好的获得阈值.但是为何不直接用supervise Learning呢?分析对比如下: 进一步地,对于异常检测系统而言,选择合适的特征是非常重要的. 首先保证特征尽量服从高斯分布是非常重要的,因为异常检测的基础是基于高斯分布的: 接下来看看缺陷检测的误差分析,通过引入新的特征来提升模型的性能:
K-means与异常检测的实验代码
Reinforcement Learning
强化学习是要告诉模型什么是“正确”的答案,而是通过奖励来告诉模型什么是“好”的行为。也就是告诉模型what to do而不是how to do it,由模型自己来学习如何做。 RL的核心:状态(state),动作(action),奖励(reward),下一状态(next state)。 RL的Return(回报)是指从当前状态开始,未来所有奖励的总和,需要综合考虑成本和效益(下面额外加了一个discount factor)。 RL的策略(policy)有不同,比如以最近的reward,以最大的或者最小的reward,又或者基于return来选择。 而RL的目标其实就是找到最优的策略,使得对于每个state采取什么样的action使得return最大化。 下面总结一下上面的几个概念在不同的应用场景的表现: 而上述的也被称为MDP(Markov Decision Process),the future only depend on the current state。
State-action value function/Q-function
Bellman方程
Bellman方程是用来计算Q-function的,也就是用来计算在某个state下采取某个action的return。如下图所示: 接下来通过一个例子来直观理解这个方程 进一步理解Bellman方程的意义: 进一步的,由于action实际上可能有误差,因此应该为系列return的期望值:
Deep Reinforcement Learning
训练一个神经网络来学习Q-function,也就是DQN(Deep Q-Network)。如下图所示: 通过仿真各种state下的action的情况来获取训练数据: 进一步地,DQN可以采用更有效的结构,如下(同时输出四个action):
ϵ-贪婪策略
ϵ-贪婪策略是指在训练的过程中,以一定的概率ϵ来选择随机的action,而不是根据Q-function来选择action(这样可以避免由于初始化不够好导致陷入局部最优)。如下所示:
Mini-batch与soft updates
此处提供两个策略来提升模型的性能,一个是mini-batch,一个是soft updates。
当样本量很大时,可以通过mini-batch的方式来训练模型(将全部数据分为若干个batch),而不是一次性全部输入。如下图所示:
这样做的好处是可以减少计算量,提高训练速度。(虽然每一次获得的结果可能会更noise一些,但是更高效,最终的结果应该是差不多的~)
而所谓的soft updates是指每次更新模型的时候,不是直接将新的Q-function替换掉旧的,而是通过一个参数来控制新旧Q-function的比例。如下图所示:
基于强化学习的实验代码
Deep Learning
由于篇幅有限,关于Deep Learning的内容将在博客中详细介绍。
Artifical General Intelligence (AGI)
参考资料
- 机器学习(Machine Learning)- 吴恩达(Andrew Ng)
- 2024公认最好的 | 吴恩达机器学习
- B站更全的2022-Machine-Learning-Specialization
- Stanford CS229: Machine Learning Full Course taught by Andrew Ng | Autumn 2018
- 机器学习笔记目录
- 机器学习课程代码参考
- 机器学习课程代码参考2
- 2022-Machine-Learning-Specialization
- Machine-Learning-Specialization-Coursera
- deep learning- 吴恩达(Andrew Ng)
- Stanford CS230: Deep Learning | Autumn 2018
- coursera-deep-learning-specialization
- 深度学习笔记目录