吴恩达机器学习基础课程笔记

吴恩达机器学习课程笔记记录
(已完结 2024.2.1)
课程资料https://github.com/kaieye/2022-Machine-Learning-Specialization
• 定义(非显式编程)
学习内容包括
• 监督学习 course 1,2
• 非监督学习 course 3
• 强化学习(了解)
• 实操学习算法
第一课 监督学习
Week1
监督学习
算法输入,训练对应输出 x to y 的映射
• 回归(regression):从大量可能的输出中预测数字
• 分类(classification):输出的结果(数字或非数字)被分为几种可能的类别,预测的结果是小的预设集合

非监督学习(无监督学习)
在未标记的数据集中找到一些有趣的特性,例如聚类算法(clustering)。
无监督学习并不会给出所谓的“正解”(只有输入x但没有输出标签y),由算法自动找出特性。在谷歌新闻,基因分类中有所应用。

• 聚类(group similar data together)
• 异常检测(发现异常数据点)
• 降维(dimensionality reduction)压缩数据,同时丢失尽可能少的信息
Jupyter notebook
线性回归模型 linear regression

输入特征x,输出目标y,训练集

y_hat是y(真实值)的估计值,f是函数(模型),x -->f to y即特征通过模型进行预测。
只有一个变量的线性回归叫做单变量线性回归。
代价函数(成本函数)cost function
f(X)=wX+b
w,b成为参数,或系数,或权重

成本函数的自然导出:

J(w,b)通过计算方差的方式来构造成本函数,使得可以找到最接近于真实值的f参数。
除以2是为了简化计算,m是(x,y)训练样例总量
差值平方成本函数是常用的线性回归成本函数。
数学上,寻找最佳直线的过程就是minimize J的过程。

如果同时考虑w和b,代价函数会出现汤碗状(二元函数J)

等高线图形式:

梯度下降算法
概念
用于最小化w,b的成本函数,自动处理线性回归问题,是一种更系统的方法
事实上是一种可用于尝试最小化任何函数的算法,甚至是具有两个以上参数的其它成本函数:J(w1…wn,b)
• 不断改变w,b的值(初始设置为0,0),来减小J,直到J被设置为或者接近于一个最小值。
• 最小值可能有多个(也就是极小值,局部最小值)
• 沿着梯度下降的方向(方向导数最大值)减小J。

实现梯度下降算法
• 更新w值,α是学习率,决定了每次下降的步幅。
• derivative→导数

• 同时更新w,b是正确的方法

• 学习率过大或过小的影响

• 随着导数值的减小,即使学习率是固定的,更新的值也会变小。

用于线性回归的梯度下降
• 计算成本函数关于w和b的偏导数。

此时成本函数是凸函数,只要学习率合适,J总是会收敛到全局最小值,(碗形底部)。

运行效果:
使用批量batch梯度下降进行线性回归,指的是每次都使用所有的训练样例。

Week2
多维特征

• 注意符号的含义:下标数字表示的是不同的特征;上标带括号的数字表示的是每个特征的第i个训练样例,且箭头是可选的指示符,用于强调这是一个包含1…4个特征样例的向量。如果上下标同时出现,就表示是Xj特征的第i个样例。

多元线性回归:
写成向量点积形式,不同特征乘不同的w相加

• 不是多元回归,是多元线性回归。前者是其它的概念。
向量化
有助于实施学习算法时缩短代码提高效率。
• 使用了Numpy——一个Python和机器学习中使用最广泛的数值线性代数库
• 使用向量化的方法(dot)能够在计算机中并行使用硬件,无论是普通计算机还是CPU,GPU,通常都能加速机器学习作业,且代码更短。

  1. 普通实现,不好,n很大时不现实
  2. 用循环,一般
  3. 矢量化,用Numpy库的dot方法,又快又好

• 普通方法是一个一个相加,而矢量化方法有专门的硬件并行完成。
• 在梯度下降算法中:

用于多元线性回归的梯度下降法
向量化方法表示:

将J的偏导数具体表示:

另外:正规方程法(处理线性回归问题的另一种方法)
• 不能够泛化解决其他学习算法
• 特征数量大时慢
• 一些线性回归库使用,机器学习从业者一般不会自己实现
推荐的方法是梯度下降法
特征缩放
让梯度下降更快
• 特征数值较小时,其对应参数w往往较大;而特征数值较大时,其对应参数往往较小;这样其预测结果更接近真实值。

• 因此,特征之间的散点分布和成本函数等高线图可能会出现如下的情况:
(此时成本函数等高线图没有考虑b,考虑的是向量w的两个特征w1和w2)

• 为了便于梯度下降法快速找到J的最小情况,应该对特征进行缩放,让各个特征数值之间具有良好的比较能力,效果如下:

• 实现方式:
除以最大值,限定范围0-1

均值归一化(均值标准化)
算出特征均值,然后特征-均值μ,除以范围差值

Z-score归一化(Z分数标准化)
算出x1和x2的标准差(正态分布,高斯曲线)

何时进行特征缩放?

目标是让特征数值在-1到1之间,可接受的范围同样也包括-3到3,-0.3到0.3。对于相差过大的情况,为了让梯度下降运行得更快,鼓励进行特征缩放,这几乎没有坏处。
判断梯度下降是否收敛
• 绘制并查看学习曲线
良好的梯度下降学习曲线的J应该随着迭代次数的增加而下降,最终趋于平稳。
横轴是迭代次数,纵轴是成本函数值。不同的迭代方式可能需要不同的迭代次数。通过观察一定迭代次数之后的J值是否趋于平稳,判断其是否已经收敛。
• 采用自动收敛测试
如果J的变化小于一个小量ε,则宣布J到达全局最小值,梯度下降收敛。实际应用中,定义ε的大小是不容易的,因此更倾向于观察学习曲线。

选择适当的学习率
如果学习曲线并不随着迭代次数下降,甚至随着迭代次数上升,即J不收敛,这往往意味着:
• 学习率α过大
• 代码中存在错误
前者会导致每次的参数调整过于剧烈,以至于无法发现J的全局最小值
后者常见的是将调整的➖写成➕,这与梯度下降思想背道而驰。

在实际的代码调试中,判断J是否收敛的一个小技巧是将学习率α设置为一个很小的值,用来判断究竟是学习率过大导致的不收敛,还是由于代码的错误导致的不收敛。
需要强调的是,这只是一个调试的技巧,过小的学习率虽然可以让J收敛,但是却不是一个合理的学习率,会让梯度下降运行得非常慢,需要更多次数的迭代。
尝试选择学习率α的值
例如,从0.001开始,每次更新乘10倍或者3倍,观察对应的学习曲线。
最终选择的学习率应对应一个良好的学习曲线,尝试选择一个最大可能的学习率,或者比其略小一些。

特征工程
例如,定义一个新特征来获得更好的模型:

特征工程可以帮助拟合直线之外的曲线
多项式回归
选择不同的特征,获得不同的模型,例如(根号x,x²,x三次方)。
• 在这种情况下,对应于x的多项式,不同的特征往往具有相差很大的数据范围,此时特征缩放变得尤其重要。

选择什么特征?将会在第二课介绍。
• Scikit-learn工具的使用,在可选实验室中
Week3
学习分类(y不是任意数字输出了)。事实证明,线性回归是不适合分类的,要学习逻辑回归。

• y只有两种输出的叫二元分类(yes/no 0/1 true/false 正例/反例)

线性回归可能会得到糟糕的预测结果,决策边界发生移动。
逻辑回归虽然叫回归,但这是历史原因导致的,实际上用于解决分类问题。
逻辑回归
Sigmoid函数(逻辑函数)
• 逻辑回归得到的曲线应该呈现如图状态(最终取值还是0/1)
• 逻辑回归的输出始终介于0-1之间,这是Sigmoid函数的值域决定的
• Sigmoid函数用于构造曲线,表达式如图

• 如何使用Sigmoid函数:

• 逻辑回归输出的解释:输出的y=1的可能性,因此也有概率P的写法

决策边界
设置一个预测的阈值,fx或gz大于等于该阈值时y预测=1。小于时=0,例如,设定阈值为0.5

• 决策边界示例1:

令z=0,得出的两个特征的临界值(构成一条直线)就是此时的决策边界。
• 决策边界示例2(逻辑回归的多项式回归):

• 更复杂的决策边界(更复杂的多项式)

逻辑回归的成本函数(代价函数)
成本函数提供衡量一组特定参数与训练数据拟合程度的方法,提供了获得更好的参数的办法。
平方误差成本函数并不是逻辑回归的理想成本函数。
训练集示例:

如果采用平方误差成本函数的话,成本函数曲线区别于线性回归,在逻辑回归的情况下并不是凸函数,因此可能会有很多局部最小值,无法保证梯度下降收敛至全局最小值。

单个训练示例的损失函数 & 逻辑回归的成本函数
将之前的成本函数求和内部部分(含1/2)单独定义为逻辑回归的损失函数,表示一个单独示例中fx和y的差距表现。
在平方误差成本函数的情况下,损失函数是1/2(fx-y)²
当我们为损失函数选择不同的形式,那么由损失函数求和形成的成本函数将可以成为一个具有全局最小值的凸函数。(为什么是凸的是一个数学问题,实际上就是求二阶导,这里就不展开了)

用于逻辑回归的损失函数(由此求和得到了新的成本函数)注意点:
• 根据不同的真实标签y具有不同的表达式形式
• fx(由Sigmoid函数定义的)

fx始终介于0-1之间,因此对数函数的曲线有效部分也相应确定。
真实值为1时的逻辑损失函数

fx在0-1之间,因此图像是对应的对数函数一个(0,+∞)的递减部分。
此时预测值fx和真实值y=1定义的损失函数形式-log(fx)表达了一个事实关系,即:
• fx很接近1时,损失值很小,这表明预测的结果更为合理;
• 当预测值fx更接近0,和真实值y=1并不接近时,损失函数的值会较大,甚至趋于+∞,这表明预测的结果并不合理。
可以看出,损失函数激励了算法作出更准确的预测,当真实值y=1时,损失函数在预测值fx接近1时损失最低。
真实值为0时的逻辑损失函数
相较于真实值为1,仅仅作出了表达式的变化,其思想内涵完全一致。

同样的,预测值fx距离目标y越远,损失值越高。
当模型作出了非常肯定的预测,例如99.99%的概率,但却与目标值不一致,此时将会被惩罚而得到一个非常大的损失。因此,假设当真实标签为1时,算法被强激励为不要预测太接近0的结果。

• 所有单个训练示例的损失函数定义了整个训练集的成本函数,成本函数总结了所有训练样例的损失,衡量了整个训练集的表现。
• 单个训练示例的损失函数表示了预测值与实际值的差距
接下去仍然是找到一组w,b时这个新的逻辑回归成本函数最小化。
简化逻辑回归成本函数
为了更简洁地实现梯度下降,对逻辑回归的成本函数进行简化。
(将函数的两个表达式写成一个等价的表达式)

用简化的损失函数构造成本函数:

另外,为什么我们会在如此多的可能成本函数中选择了这种形式作为逻辑回归的成本函数?这实际上是用最大似然估计的统计原理推导的,它通过寻找最大化样本观测值的概率(似然函数)的参数值来估计参数值。而且这个成本函数具有凸的优良特性。
在逻辑回归中实现梯度下降
根据学习率和对应导数值的乘积重复同步更新w,b

右边的导数形式需要注意。带入就可以得到逻辑回归的梯度下降表达式:

尽管成本函数的导数形式导致w,b的更新方式非常相似,但是逻辑回归与线性回归的函数fx是不一致的。
同样可以判断收敛,向量化实现,特征缩放。
(可选实验室里有逻辑回归梯度下降的可视化,以及scikit-learn的用法)

欠拟合/过拟合问题
我们学习的算法可能会遇到过拟合的问题,与过拟合相反的情况成为欠拟合。我们将学习过拟合的概念以及解决过拟合的正则化方法。
如下的三个房价的例子,分别对应欠拟合,正好,过拟合:

• 欠拟合的数据显然和训练数据非常不符合,因此具有”高偏差“(High Bias)。高偏差和欠拟合是等价的表达。高偏差在这里指的是该算法没有清晰地捕获到训练数据的一个清晰的模式,没有很好地拟合训练数据。或者说存在类似于算法先入为主地认为数据是线性的这样的情况而导致拟合不足。特征太少可能会更容易导致欠拟合问题。
• 正好的拟合说明学习算法能够很好地泛化数据,推广至其它例子。
• 如果采用四次多项式来拟合房价数据,会出现过拟合的情况,此时预测的价格能够完美地符合训练数据,甚至使得成本函数为0。然而这并不代表学习算法是好的算法,因为这样的算法具有”高方差“——由于它实在是太符合训练数据了,因此对于不同的训练数据,训练的结果将会大不相同,并不能很好地泛化数据,这说明了算法出现了过拟合问题。过拟合和高方差也是等价的表达。
机器学习的目标是找到一个既不是过拟合也不是欠拟合的模型,也就是一个既不是高偏差也不是高方差的模型。
过拟合同样会出现于分类问题:

在z中具有非常多的高阶项时,其决策边界(Sigmoid函数的z=0对应的曲线)可能会呈现出最右边图的复杂形状,此时出现了过拟合。
解决过拟合
后续我们会讨论发现过拟合的手段,在此我们先讨论如何解决过拟合问题。
• 首先是可以收集更多的训练数据

这会迫使模型去对抗过拟合
• 其次是选择包括更少的特征
如果包括的特征非常多而对应的训练数据又很少的时候,模型很可能过拟合。
这涉及特征选择的问题,因为在这种情况下不得不丢失一些和结果预测有关的信息。后续会介绍算法来选择一个最小的特征集合。

• 第三是正则化(即将具体介绍)
在实际的过拟合例子中,各个特征的参数往往都比较大,这是过拟合的一个特点,尝试减小这些参数往往会让结果更容易避免过拟合的情况。上述特征选择以减少特征的方法实际上对应将特征前对应的参数设置为0。与之不同,正则化可以保留所有的特征,转而只是防止特征产生过大的影响而产生过拟合。
在实际应用正则化时,通常只对w1…wn(wj)作变小的操作,对于b没有要求。一般而言减小b也不会有什么效果。

可选实验室介绍了过拟合的解决方法示例,建议看看。
正则化
上面已经提到了正则化的基本思想就是减小一些参数值的大小,减弱其对应特征的影响,这比直接删除某个特征更加温和。它的做法可以简单表述为:

我们不再最小化原先的成本函数,而是现在成本函数后加上若干个很大的数乘上对应希望减小的几个参数的平方。之后再进行最小化。因为很大的数和参数的乘积会阻碍成本函数的最小化,因此这些参数都会被最小化方法改变得很小,这达到了我们的目的。
通常而言,我们并不知道应该惩罚哪一个特征使其参数变小,因此我们会惩罚所有的特征。
确切的做法是这样的:
寻找一个正则化参数λ,用如下的式子改变成本函数(即加上一系列参数平方与λ的乘积)

需要注意:
• λ的值也按2m进行缩放,这种正则化方式有助于我们确定λ的值,同时在训练集规模m增长时让之前确定的λ仍然具有可行性。
• 实际中,是否惩罚b对结果没有太大作用。本课程不考虑b。
因此,需要最小化的成本函数变成了均方误差成本加上额外的正则化项,前者能够鼓励模型更好地拟合数据,后者则鼓励模型尽量避免过拟合。
其中,正则化参数λ的作用就是平衡这两部分的关系:
在λ较小时,模型会更加重视拟合数据的部分,即将平方误差最小化,可能导致过拟合,如λ=0时;
在λ非常大时,模型会更重视避免过拟合的问题,可能会导致欠拟合。例如λ趋向于∞时,所有的参数wj都会接近于0,此时整个模型只剩下b的一条直线(b没有参与正则化惩罚),这是失败的拟合结果。
因此选择一个既不偏大也不偏小的λ是非常重要的。在后续的学习中,会介绍具体的确定λ值的方法。

用于线性回归的正则方法
如何让正则线性回归和梯度下降一起工作。
事实上梯度下降的方法并没有本质的变化,只是因为我们修改的成本函数J的内容,因此每次更新wj的方法因J的导数发生了改变。课程中关于介绍导数的计算部分可以忽略,因为我们学过高数(不得不感慨这门课程的人性化程度)。另外,我们不考虑b的正则化,因此b的更新方式不变:

同步更新依然必不可少。
内部的数学机理和方法本身的对应:

更新wj的行为在数学上可以移项成为先将wj乘上一个略小于1的数然后进行通常的梯度下降更新,这也解释了为何正则化在梯度下降法中缩小参数的值。
用于逻辑回归的正则方法
由于二者的梯度更新惊人地相似,因此正则化逻辑回归的更新与正则化线性回归的更新非常相似。
逻辑回归的成本函数我们之前进行了简化,现在我们在原本的成本函数后加上正则化所需的正则化项:

正则化项保证了我们的参数尽可能减小。这可以让我们的分类结果更有效地防止过拟合,来更好地泛化模型。

由于逻辑回归的成本函数关于wj和b的导数和线性回归的成本函数关于wj和b的导数惊人地一致,因此他们的更新公式几乎完全相同,唯一的区别在于逻辑回归的fx是Sigmoid函数gz复合线性和z=wjx+b的形式
实验室里增加了正则化代码。

李飞飞访谈
”我希望我们能用简洁而美丽的公式来描述AI,我们现在正处于‘Pre Newton‘的阶段,处于人工智能激动人心的阶段,就像牛顿不会梦到爱因斯坦。“——李飞飞
Caltech 101数据集
AI changes the world. Who changes AI?
第二课 神经网络(深度学习算法),决策树
课程安排
• week1 week2 神经网络:包括推理预测 训练
• week3 构建机器学习系统的实质性建议
• week4 决策树
Week1

神经元和大脑
神经网络最初用于模拟人脑(生物大脑)
尽管今天的神经网络几乎与大脑的学习方式无关,但是早期的动机是尝试构建软件来模仿大脑。

从生物大脑的神经系统简化出的神经数学模型:

这是一个松散的类比,因为目前人脑的运作机理几乎也没有被揭示,每隔几年就会有新的突破。因此用我们目前对于大脑的理解来构建一个原始的智能很可能是不合理的。
但是这些极其简化的神经元模型可以帮助我们构建非常强大的深度学习算法。
因此生物学动机不是重点,目前也不能成为重点,从事深度学习研究的人并不关注生物学动机,而只是用工程原理构建更有效的算法。
为什么深度学习算法在近几年内起飞了?
传统的机器学习算法(线性回归,逻辑回归)性能有限,构建更大的神经网络有助于提升性能表现,再加上大数据的支持。同时,更快的计算机处理器和GPU的发展也是重要原因。
神经网络举例:需求预测
一个简单的需求预测示例
预测什么样的价格会让一件衬衫成为畅销商品:

用逻辑回归计算出了预测值fx,这是衬衫畅销的概率,最终被分类为0/1(不畅销/畅销)。此时将这个概率记为a,它实际上是叫做激活(activation),这是神经元的概念,指输入价格后神经元输出的衬衫成为畅销商品的概率。我们简化神经元的概念在这里体现为将神经元的功能简化为一个逻辑回归的输入和输出,实际的神经元功能要复杂得多。将这些简化的神经元串在一起就构成了神经网络。
更复杂的需求预测示例
如果影响商品成为畅销品的因素包含四个不同的特征:

• 先由这四个特征用逻辑回归得到商品的”可负担性“,”顾客认知“,和”感知质量“,然后再从这三者中得到最终成为畅销商品的概率
• 左边三个神经元构成一个”层“,层是一个或若干个神经元或特征的组成。神经元的输出叫做激活。所有的特征组成了输入层,中间的神经元组成的层得到输入层的输入输出各个激活值。在图中,右边粉色的神经元得到了上一层的三个对应于商品三种特点的输入用逻辑回归输出一个激活值——畅销的概率,因此这个神经元自己单独构成了输出层。中间层被称为隐藏层。
实际情况下,设置某一层中的每个神经元输入哪些特征是比较繁琐的,因此不妨将所有特征输入,用参数设置使各神经元只关注对自己影响最大的特征集合:

为了简化表示,可以将所有输入特征写成一个向量,同理也可以将每一层的激活值写成向量的形式送往下一层:

由此我们将一个四个数字特征的向量(输入层)喂给隐藏层,得到一个由三个激活值构成的激活向量,再将其喂给输出层,得到最终的激活值——畅销概率。
中间层被称为隐藏层的原因:在数据集的输入输出(vector(x), y)中,数据集往往隐藏中间的激活值,因此你不知道正确的中间激活值,它们是隐藏的。
一个需要注意的特点:我们之前会通过手动特征工程来提高预测的可靠性,例如我们在房价预测中,在地皮地块长宽x1,x2以外构建了草坪面积=x1*x2这一特征,帮助我们更好地进行预测;虽然我们在这里人工指明了隐藏层的内容,但实际上神经网络则不需要我们手动设计特征,它可以学习,即自己计算出隐藏层中应该使用什么样的特征。
多个隐藏层的示例

这种多层的架构很多时候被称为“多层感知器”,指的就是这种情况。
决定有几个隐藏层以及每个隐藏层有几个神经元是神经网络的架构问题,这会对算法的性能产生影响。后续会学习选择神经网络合适架构的技巧。
神经网络举例:图像感知
例如一个1000px*1000px的图像(px=pixel 像素)
每个像素格是一个从0-255的数字,表示像素强度或亮度,整张图片可以按行排列或展开成一个包含1000000(1million)的列表,我们的任务是构建一个神经网络来从这些数字中输出人的身份信息。

神经网络中包含多个隐藏层。如果我们试图观察每一层中的各个神经元的行为,来猜测它实际上在计算什么,我们就会发现:
• 第一层的第一个神经元似乎是在图片中寻找垂直的短线,第二个神经元则是寻找其它朝向的短线,各个神经元都在寻找一些短线或者偶尔是小方块这样的部分。
• 第二层的神经元们则开始抓住一些可能是“眼睛”,“鼻子”这样大块的面容特征的部分。
• 第三层的神经元已经开始获得不同粗糙程度的面容,它们输出的一系列丰富的激活值能够让输出层输出一个图像人员身份信息的概率。
我们能够注意到每一层的激活值在逐渐变得更加高级。
同样地,对于车的图像识别,这个神经网络的工作细节也十分相似:

不同层的神经元开始从边缘细节,到车辆零件,到整体车辆得到越来越高级的激活值。这些特征都是由神经网络自己学习的。
接下去我们将学习神经网络的具体实现细节与方式。
神经网络中的网络层
如何构建一个神经元层以组合一个大型神经网络。
以需求预测为例
我们将输入层记作第0层layer0,之后是第一层和第二层——layer1,layer2
对于layer1:

layer0的向量x输入layer1的每一个神经元。每一个神经元都是一个简单的逻辑回归gz,g是逻辑函数Sigmoid,z是wx+b。每个神经元对应一个激活值,这些激活值一起构成了激活向量vector(a),作为layer2的输入。
其中参数和激活向量带方括号[i]的上标表示第i层layer i,而参数下标表示这是第当前层几个神经元的参数。
对于第二层:

输入是layer1的激活向量vector(a)[1],第二层只包含一个神经元,进行一个简单的逻辑回归,此时的z是wa+b,a是上一层的输入。
对应参数和输出激活向量右上角添加上标[2]用于指明这是与第二层相关联的量。
在这之后,我们还有一些可选步骤,用于设置阈值以分类预测结果,毕竟逻辑回归是一个分类算法。

更复杂的神经网络
用多个隐藏层的神经网络作为示例

• 在这里,我们逻辑回归函数的地位被定义为“激活函数”,逻辑回归函数是我们目前唯一见到过的激活函数形式,我们在将来的学习中会看到更多的激活函数形式。
• 方括号上标[l]依然代表当前层的参数或者激活,在这里,每一个神经元的简单逻辑回归用的是上一层的激活作为输入,因此有了下面方框内的激活计算公式。
• j指的是单元,也就是第几个神经元,他们是等价的表达
• 将输入层定义为第0层,x写为a[0],那么这个公式同样也适用于第一层。
下面我们将把我们学到的东西组合成一个算法,让我们的神经网络进行推理或预测。
神经网络前向传播
手写数字识别例子,将手写的数字二元分类为0/1,输出数字是1的概率。
数字被放在8*8的图中,255是白色,0是黑色。
神经网络包含三层(输入层不算),其中有两个隐藏层,分别包含25和15个单元。
a[1]和a[2]的激活函数都是Sigmoid函数。

之后计算a3激活值(fx),也就是神经网络的输出,激活函数仍是Sigmoid。

这就是前向传播,因为我们在传播神经元的激活。
之后我们会学习反向传播。
前向传播的架构最初几层有更多的隐藏单元,随着离输出层越来越近,隐藏单元的数量会减少。
有了前向传播方法,我们就可以下载别人训练好的模型参数进行推理,下面是tensorflow的实现。
Tensorflow实现推理
Tensorflow是实现深度学习算法的领先框架之一。另一个常用框架是Pytorch。
烤咖啡豆的例子:

根据这个神经网络架构,Tensorflow的基本实现步骤如下:

创建np数组x,x是一个温度和持续时间的向量。
创建layer1,类型是Dense(后续会介绍其它层类型),含三个单元(神经元),激活函数是Sigmoid。
激活值a1=layer1在x输入时的输出。
同样创建只有一个单元的Dense类型的layer2,激活值a2是layer2在a1输入时的输出。
之后根据a2的值判断yhat(分类结果)。

对于手写数字识别的例子:

x是所有像素格展开的亮度数组。
每一层设置单元数和激活函数,分别创建激活值。
最后进行输出分类yhat的二元预测。
Tensorflow中的数据形式
如何在Numpy和Tensorflow中表示数据,这一点很重要。
Numpy在Tensorflow之前被创造,作为线性代数的标准库,而之后的Tensorflow和Numpy的数据表示方式有些许不一致。

可以注意到有两层方括号,内层表示矩阵的行,外层表示行组合成矩阵。
矩阵实际上是一个二维数组。

如果使用了双方括号,那么()内表示一个矩阵,即有行有列,是一个二维的量,即便它只是一个行向量或一个列向量。
在之前的课程中,我们只使用一个方括号,这表示()内部仅仅是一个一维向量,不是一个矩阵。在Tensorflow中,使用双方括号的形式让数据成为一个矩阵而不仅仅是一个简单的一维向量有助于更高效的内部计算。这是一个约定。
因此我们刚刚看到的咖啡豆代码的x用的是双[[…]]

然后,a1=layer_1(x)得到的激活值a1也是一个矩阵,例如[[0.2, 0.7, 0.3]]。如果我们试图打印a1,那么就可以看到a1是tf.Tensor()(张量)类型,这是一个Tensorflow创建的数据类型,用于有效存储和执行矩阵运算,实际上张量比矩阵更加通用,但是本课程将其视为矩阵的一种形式。同时可以查看矩阵内容和矩阵形状,以及表示矩阵元素的数据类型。
因此,Tensorflow内部的矩阵表示形式和Numpy是不同的。如果要将Tensorflow的矩阵转化为Numpy的形式返回,需要调用a1.numpy()方法。

对于第二层,输出a2作为一个激活值,是1*1的矩阵形式,例如[[0.8]],同样是一个二维数组;通过.numpy()方法可以将其转化为Numpy数组(Numpy矩阵)。
由于历史遗留的问题,Numpy和Tensorflow表示矩阵的方式有所不同。通常我们习惯于在Numpy中加载操作数据,但将Numpy数组传递给Tensorflow时,Tensorflow习惯于将其转化为喜欢的Tensor格式,并用其高效操作。读回数据时,我们可以直接读取Tensor,或者将其转化回Numpy数组。虽然我们不得不做一些额外的转换,但是事实证明Tensorflow和Numpy可以很好地协同工作,我们在coding时要注意这些转换的问题。
搭建一个神经网络
之前的显示计算方式:

Tensorflow中构建神经网络的不同方法:

创建层的操作与显示计算相同。然后只需使用顺序函数Sequential,将[layer_1, layer_2](层组成的列表?)传入,就得到一个由第一层和第二层顺序构成的神经网络模型model。
之后,将我们的训练集数据用Numpy数组表示(矩阵和一维向量),进行compile和fit函数操作,就可以用predict函数进行对x_new值的预测。其中compile和fit函数的具体细节在之后介绍。
另一个更复杂的例子(数字分类,有三层):

过程是一致的。同时我们可以不对创建的三个Dense层进行变量赋值,将其直接传入顺序函数Sequential():

方括号包括三个Dense层。
接下去我们介绍一下用Python实现的前向传播。尽管实际中我们更多地是直接使用Tensorflow这样的专业库,但了解这些代码到底在做什么对我们解决和理解问题很有帮助。
单个网络层的前向传播

如果我们直接对前向传播的过程coding,那么就应该是这样的过程。
所有的向量都用一维Numpy数组表示。
我们知道第一层和第二层所有的参数w(向量),b,那么输入x,我们就用最基本的过程计算出向量a[1]的三个元素,然后计算出向量a[2]的一个元素。
这就是用Python和np实现前向传播的过程。
这个过程可以简化。
前向传播的一般实现
读懂理解就足够。
在这里我们将所有的参数也放入了np数组,在需要时提取;并且采用了循环的方式计算出每个单元的激活函数值,从而计算出每个单层的激活值。
对于每个单层,逐层顺序计算激活值,构成顺序函数,就可以得到最终输出。这就是Tensorflow实现的底层原理。

• shape[1]指的是矩阵列数,在这里是提取每层的单元数。
• 将w向量参数按列构成矩阵,使用时也按列提取(按列是因为每一列对应一个不同单元的参数,激活值的每一列也对应一个激活函数值;同样有利于向量化的矩阵乘法实现)
强人工智能(AGI)

狭义的AI(ANI)正迅速发展并成果卓著,这推动了整个AI的发展,但并不代表AGI也随之发展。
再者,逻辑回归的激活方式相较于人脑神经元真正的工作方式,实在是过于简化了。因此试图模拟人脑而发展AGI是困难的。
希望同样存在,有研究发现生物脑的特定部分可以学会其它的功能,这是否意味着存在一个未知的学习算法?是否有望在计算机上实现?未来可期。
神经网络如何高效实现
秘诀在于矢量化,这样可以利用GPU等非常善于做大型矩阵乘法的硬件。

对之前的代码矢量化后,可以看到矩阵乘法matmul方法代替了提取每一列w向量参数相乘的循环,这是很高效的。
矩阵乘法代码
线性代数中我们非常熟悉矩阵乘法。

• 转置函数.T
• @可以代替.matmul
对应过程和代码实现:

实际上Tensorflow的实现不需要对输入进行转置,默认按行排列。老师这里使用的转置是为了解释矩阵乘法的原理。本来一行一列就挺好的。能看懂代码即可。
Week2
TensorFlow中模型训练实现
对于数字0/1识别的例子,我们要导入相应的模块,比如tensorflow,Sequential,Dense;第一步是创建神经网络;第二步骤用compile方法编译模型,并指定损失函数,这里是二元交叉熵损失函数;第三步用fit方法训练模型,epchs是梯度下降的步骤数。

这是Tensorflow训练神经网络的基本代码实现。
模型训练细节

操作原理|逻辑回归过程|神经网络代码
• 创建模型

• 损失函数和成本函数

—— 二元交叉熵损失函数的二元用于强调分类问题的性质,实质上就是逻辑回归的损失函数。交叉熵是统计概念。
—— 大写的W和B表示所有参数w,b。
—— 如果想要使用回归的损失函数,比如平方误差损失函数,可以令loss=mean suqare error。
—— Keras是合并到Tensorflow的,最初是一个完全不同的项目
• 梯度下降
Tensorflow用反向传播算法计算偏导数项来更新参数值。

• Libraries介绍
• Tensorflow需要另外学习了

接下去看看如何交换不同的激活函数。
Sigmoid函数的替代方案
以房屋价格为例:
对于神经网络某一隐藏层每个单元的激活,我们都可以采用不同的激活函数。我们之前只使用了逻辑回归的Sigmoid函数。

我们常会使用ReLU(Rectified Linear Unit)函数,全称是整流线性单元函数。
图像如图所示,可以定义为gz=max(0,z)。z=wx+b

除此以外,还有“线性激活函数”。由于gz=z,因此a=gz=wx+b,这看起来似乎和没有激活函数一样,因此有时也把线性激活函数叫做“没有激活函数”。
后续还会介绍Softmax激活函数,有了这些激活函数,就可以构建强大而复杂的神经网络。
如何选择激活函数
输出层根据目标标签或真实标签y是什么,输出层的激活函数会有一个相当自然的选择,然后我们再看隐藏层的各个单元的激活函数。
输出层

• y=0/1的二元分类问题,一般就会选择Sigmoid函数;
• 对于有正负值的结果(回归问题),可以使用线性激活函数;
• 对于只有0和正值结果的回归问题,可以使用ReLU函数;
隐藏层

对于隐藏层,目前最常用的就是ReLU函数作为激活函数的方案。
• ReLU函数计算比Sigmoid函数更快,因为后者有取幂等操作。
• ReLU函数只在<0处平坦,而Sigmoid函数在两处平坦。这会导致Sigmoid构造出的成本函数在很多地方比较平,这会减慢梯度下降的速度。
总结
这就是常见方案,输出层根据输出决定;隐藏层默认ReLU。

其它激活函数:tanh,swish,LeakyReLU……
激活函数到底是什么,为什么重要,为什么模型需要激活函数
为什么我们不直接将每个神经元进行线性回归(没有激活函数)?
——因为这和直接进行线性回归没有什么区别,破坏了我们构建神经网络的初衷。

只使用多个线性回归单元并不会让神经网络比线性回归更复杂,可以说是完全等价的。如果只有输出层是逻辑回归,那么整个模型和逻辑回归是等价的。
—— 经验法则,不要在隐藏层中使用线性激活函数(也就是一定要用激活函数),使用ReLU就可以。

多分类问题
可能有两个以上的输出标签,不仅仅是0/1。

将了解算法学习出这样的决策边界。
Softmax
对逻辑回归算法作的多分类推广

逻辑回归中我们可以计算出gz,记为a1,这是预测结果y=1的概率;根据概率原理,预测值y=0的概率是0.29。
如果我们将这种方式推广至多分类问题,就得到了Softmax回归的表达式。
• zj=wjx+b,j代表N个分类可能输出的某一个。
• aj=e的zj次,除以所有的e的zk次方之和。代表结果是某一预测值的概率。
• 所有的aj(1…n)之和是1
损失函数和成本函数形式

对于之前的逻辑回归损失函数,我们可以将1-a1的部分写为a2(P|y=0)。在之前对逻辑回归损失函数的讨论中,我们不强调和概率有关的表达方式,但是它实际上可以这样做。逻辑回归的损失函数就可以表示成:
• if y=1:loss= -log a1
• if y=0:loss= -log a2
转化成了真实标签和对应该标签的预测概率的表达形式。
由此推广至Softmax回归。对于每一个可能的预测y(1…n),损失函数是一个n段的分段函数,每一段都是针对当前的真实标签y=j取其对应的预测概率负对数-logaj(注意aj的表达式不再是Sigmoid),这也印证着我们之前”预测值=当前y的概率越大,概率越接近于1,则损失函数越小的思想“,我们希望预测尽可能接近真实标签,那么这个损失函数正好符合我们的需求,我们也希望它越小越好。同样对于其构成的成本函数,应该也要能够是凸的以顺利运行梯度下降。
再次强调,我们之前没有考虑很多和概率有关的问题,因为当时是二元的逻辑回归,我们单纯地构造了y=1和y=0时都满此时足要求的损失函数并用它构造了一个凸的成本函数。而我们现在考虑多分类问题,此时用到了和概率有关的表达方法。事实证明,这种方法也适用于二元的逻辑回归情形,可以视为是二元逻辑回归的推广。
注意对于不同的真实标签y,损失函数的表达式是不同的,因此成本函数是所有标签损失函数的平均值。
以Softmax为输出的神经网络
为了构建一个可以进行多分类的神经网络,我们将采用Softmax回归模型并将其放入神经网络的输出层。

我们将之前逻辑回归只有一个单元的输出层变成了有N个(输出分类数,这里是10)单元的Softmax层。Softmax层的每个输出aj是每个单元的激活值,来源于z1…z10(每一个zj)的计算表达式,代表y=1…10的概率,它们构成一个N维向量a[3],3代表第三层。
与之前的Sigmoid或者ReLU不同,这里Softmax输出层的激活向量中的每一个激活值都是z1…z10的函数,不单单是一个z的函数,单个单元的输出同时用到了其它单元的参数。
tensorflow实现
依然是使用Sequential将三个Dense层串在一起,但是输出层的激活函数使用Softmax。损失函数使用SparseCategoricalCrossentropy函数(稀疏分类交叉熵损失函数),稀疏指的是数字不会同时是多分类中的两个,只会是一个。
之后是compile和fit。
这个版本虽然可以正常工作,但不要使用,有更好的方式,仅供理解。

Softmax的改进实现
虽然我们计算Softmax成本函数的方法是正确的,但有一种不同的公式可以减少类似于浮点数的精度丢失这样的数值误差,从而在tensorflow中实现更准确的计算。

如图:计算误差

不使用a作为计算损失函数的中间值,可以避免计算带来的舍入误差。损失函数参数from_logits=True,同时将输出层的激活函数设置为linear。logit实际上指的是z。
这种方法并不直观,逻辑回归是否使用不影响结果,但是Softmax回归的数值舍入误差会更糟糕,因此需要。
对于Softmax情形:

将输出层的激活函数改为线性,添加from_logits=True参数。
这样和我们之前的做法相比,做的事情没有区别,但是数字更准确,同时也更难以阅读。但还是建议在底层就使用这种形式。
输出层激活函数改成线性实际上也代表”没有”激活函数,稍后肯定需要指定。
• 实际的Softmax代码

• 实际的逻辑回归代码(这个差不多)

预测的logits是z,不是真正的激活值,真正的预测输出通过指明Sigmoid或者Softmax激活函数得到。
这样就能以数值稳定的方式实现分类问题。
多个输出的分类(多标签)
输出可能是一个包含多个数字的向量,不仅仅是一个数字。

道路识别案例的多标签输出

分别使用三个神经网络预测不同的输出是不合理的。我们可以在输出层使用不同的单元预测不同的输出,最够组成一个包含多标签的向量。
需要区分多分类问题和多标签问题。多分类问题是输出标签可能有N个不同的值;而多标签问题则是要处理多个分类问题,例如3个二元分类问题。
高级优化方法(相较于梯度下降)

我们在对成本函数进行梯度下降时,如果下降方向一直都比较一致,那么可以考虑增大学习率;如果梯度下降的偏导数方向非常不一致,那么需要减小学习率。利用Adam算法可以自动调整学习率的大小。
ADAM=Adaptive Moment Estimation 自适应矩估计
Adam算法对每个参数使用不同的学习率,而不是全局一致的α。

实现逻辑和我们描述的一致,根据参数下降的方向是否经常一致来增大或减小该参数对应的学习率:

Adam算法的实现细节此处不考虑,在更高级的深度学习课程中会有介绍。
在代码中,我们添加优化器optimizer参数,指定Adam算法和默认初始学习率。

Adam是很好的选择,大多数从业者都在使用,可以让学习速度更快。
其它的层类型
现在我们所使用的都是密集层类型,每一层获得上一层所有激活的输入。使用密集层足以构建强大的学习算法。
现在我们将介绍其它层类型。
• 复习密集层

• 卷积层

• 在数字识别例子中,每个单元只取一部分像素作为输入。这可以导致更快的计算和更少的数据集需求,并且更不容易过拟合。
• 有多个卷积层的神经网络称为卷积神经网络。
详细说明一个卷积层,隐藏层是卷积层的神经网络例子:
心电图数据预测

通过有效选择卷积层的单元数和每个单元获取的输入窗口这些架构参数,然后在输出层使用Sigmoid二元分类,可以构建更有效的新版本神经网络。
Python的导数操作
使用Sympy库:

计算图
深度学习的关键概念,tensorflow等编程框架计算神经网络导数的方法。
• 计算成本函数J的计算图:

这是一个单元的神经网络(线性回归)。在得知了w,b,x,y之后可以计算J,这是前向传播。
• 计算偏导数的计算图
在前向传播计算J的基础上,将成本函数计算公式拆分为各部分,用反向传播方式逐步计算增量比值,实际上模拟出了链式法则求导的过程,得出每一部分的导数,最终得到J对w的偏导。

通过计算图进行反向传播是计算相关偏导数的高效方法:

例如图中,J对a的导数可以用于计算J对w和b的导数,因此在含有N个节点的计算图中,如果要计算P个参数的导数,由于节点重复利用的性质,计算的次数约是N+P次而不是N*P次。
大型神经网络示例
ReLU隐藏层和输出层(输出非负的选择)

也是根据计算图逐步反向传播计算导数。

如果我们不进行反向传播,那么每次计算参数微小变化导致的J的变化以计算导数的方法是N*P复杂的,是低效的方法。而进行反向传播,我们可以重复利用某个节点的导数值,因此是N+P的高效方法。
曾经的研究人员手动微积分计算,现在都使用框架的backprop以及forwardprop——>autodiff(自动微分)
Week3
下一步做什么?——关于构建机器学习系统的建议

以房价预测为例,如果模型出现不理想的错误预测结果,那么我们可以做的事情有很多(红色箭头→),如何选择?
机器学习诊断:

通过诊断测试,可以知道哪些事情对于学习算法是有作用的。虽然诊断需要时间,但可以帮助我们更好地利用时间。
模型评估——算法的性能

模型可能可以很好地拟合数据,但是不能泛化;另外在特征很多的时候也fx也很复杂,需要评估性能的方法。
我们常将数据集3/7或者2/8分为训练集training set和测试集test set:

用括号上角标表示训练集或测试集的第m个样例,m是训练集和测试集各自的大小。
线性回归的训练和测试程序(用平方误差成本)

最小化成本函数之后,对模型进行评估时,分别计算其训练成本和测试成本,对应于训练集数据预测结果与真实数据的误差以及测试集数据预测结果与真实数据的误差。
• 过拟合的数据可能在训练成本上非常小,但是测试成本很大

• 成本函数最小化时有防止过拟合的正则化项。但是计算训练成本和测试成本时没有,它们只是显示模型是否合理,不需要最小化操作,也就不需要正则化。

分类问题的训练测试程序

• 用逻辑回归误差计算训练成本和测试成本。
如果不使用逻辑回归成本函数类似的形式定义训练成本和测试成本,那么可以直接根据预测值y_hat的个数定义Jtest和Jtrain:

训练成本和测试成本分别为错误分类占总的分数。
模型选择和训练/交叉验证/测试集
直观原始的方法,不建议使用:

对于不同的模型(多项式次数),分别计算Jtest来评估泛化能力,选择测试成本最小的模型。该模型的误差可能乐观地低于实际误差,因为测试集参与了多项式的阶数选择,这就让评估泛化能力的目的遭到了不公平的干扰。
交叉验证集——用于自动选择模型
也叫验证集validation set,开发集dev set。

同时根据验证集数据计算验证误差/开发误差:

于是我们使用训练集来拟合参数,交叉验证集选择模型:

直到需要评估模型的泛化性能时,我们才使用测试集。

在训练和选择模型时,我们不会使用测试集,而只使用训练集和交叉验证集,例如图中Jcv最小的神经网络被选中。只有在模型完成进行评估时,我们才使用未参与过模型训练和选择过程的测试集,以保证避免过分乐观的公平评估。
诊断偏差bias和方差variance
模型通常不可能在第一次训练完成后就表现良好,查看学习算法的偏差和方差可以为下一步的尝试提供很好的指导。
我们之前了解过欠拟合=高偏差以及过拟合=高方差等相关概念,在只有一维输入x时,我们可以很好地通过可视化判断这些现象。但是当输入的特征更多时,我们可能画不出图像,因此我们需要通过模型在训练集和开发集上的表现来判断模型是否出现了高偏差或高方差:

• 训练集成本很高是高偏差的强条件,同时Jcv即开发集成本也会很高。
• 训练集成本Jtrain很低但是Jcv很高,说明模型过拟合,高方差。
• Jtrain和Jcv都低时说明模型刚刚好。
诊断高偏差和高方差的方法:

和我们刚刚用语言描述的一样:
• Jtrain高——高偏差
• Jcv>>Jtrain——高方差
• 同时高偏差和高方差(偶尔会出现这种情况),Jtrain高且Jcv>>Jtrain

正则化对偏差和方差的影响
之前我们介绍过线性回归的正则化方法,可以用于减少过拟合。具体的思想是在成本函数后加上一个带有正则化参数λ的正则化项,这个项由参数的平方乘上lambda构成,以此让各个参数尽可能随着minJ的过程变小,避免特征的过分影响,从而避免过拟合。

现在,我们可以指出,正则化参数λ的取值或许会影响我们的模型性能。
• 过大的λ会导致高偏差,因为要使正则化项很小,我们的参数都会接近于0。
• 过小的λ会导致高方差(过拟合),此时正则化的效果很弱。
假设我们正在拟合上面的四阶多项式,模型如上且使用正则化方法。我们该如何选择一个好的λ值?
注意,我们已经确定了多项式的阶数,现在我们只是在选择正则化参数的值。之前我们用了很类似的方法(改变阶数选最小Jcv)选择了多项式的阶数=4。
针对不同的λ,分别计算Jcv,选取Jcv最小的值,也就是交叉验证误差最小的模型。

同样地,我们可以画出横轴是λ大小的曲线图,左侧是小λ导致的高方差,右侧是大λ导致的高偏差。可以看到Jtrain和Jcv的变化。事实上Jtrain和Jcv的变化本质上是高偏差和高方差的体现,横轴在什么地方高偏差/高方差,它们就会出现很大的值或者很小的值。因此这张图和之前多项式阶数为横轴的图看起来是镜像的。
选择最小Jcv这种方法可以帮助我们选择一个好的多项式阶数或正则化参数。

性能评估的基准——到底什么是“高”,“大得多”

语音识别的例子中,人类的错误率是10.6%,那么相对于它而言的训练误差10.8%看似很高,实际上就是很低的水平。反之,Jcv即交叉验证误差就显得跟高了,因此方差问题更严重。
基准的确定:
• 人类的表现,对于非结构化数据(音频,图像,文本等)是很好的基准。
• 竞争算法的表现
• 根据经验猜测

有了我们根据训练目标设定的基准,我们能更好地判断高偏差和高方差。
学习曲线
学习曲线是一种帮助理解学习算法作为拥有一定量的经验函数的行为的方法。经验指的是训练样例。

训练集的大小和Jcv与Jtrain的关系如图,Jcv减小(模型更好)而Jtrain增大(更难拟合)。且Jcv总是比Jtrain大一些。
高偏差学习曲线

• 高偏差(欠拟合)的情况下,Jtrain很大,且再多的训练数据也不可能帮助模型达到基准。因此此时不适合只是继续投入大量数据来改善模型表现。
高方差学习曲线

• 高方差的情况可以追求更多的训练数据,因为此时Jcv要远大于Jtrain,基准在二者之间。训练数据多,更容易拟合一个更好的模型,而不是过度的拟合。
实际情况中,计算各种学习曲线是比较复杂的任务,但是这样建立的直觉有助于我们判断模型高偏差和高方差的情形。
更好地决定下一步做什么
遇到的问题和手段对应关系如下:

根据高方差还是高偏差的不同情况,选择不同的修复手段以改正模型。
• 高方差:获取更多训练数据,简化模型(减少特征集合),提高正则化参数。
• 高偏差:获取额外特征,添加多项式特征,减小正则化参数。
神经网络的偏差和方差
模型的偏差方差权衡:

• 简单的模型容易高偏差,复杂的模型容易高方差。
对于一个神经网络,它自身有一个解决高偏差和高方差问题的流程图:

高偏差使用更大的网络,高方差则增加更多的训练数据。这虽然不是永远有效的(有时候计算成本很大,有时候数据不能再多),但可以指导下一步做什么。GPU可以很好地加速计算,机器学习的重新兴起也得益于此。在训练一个模型的过程中,可能在不同的时间节点存在或是高偏差或是高方差的问题。

一个大型的神经网络往往是一个低偏差的机器,只要正则化合适,一个更大的神经网络往往也不会导致更高的方差,但是会导致更多的计算,减慢训练过程。
Tensorflow中实现神经网络的正则化

每一层的成本函数都加上正则化项,指定一个正则化参数λ。简单起见,可以将所有层的正则化参数设置为相同的。
机器学习开发的迭代循环
• 选择架构(模型,数据,参数)
• 训练模型
• 诊断(偏差,方差,错误分析等)

以处理垃圾邮件的文本分析为例:

之后做什么?考虑偏差和方差问题👆
错误分析
下一步做什么的关键影响因素,仅次于偏差和方差。
依然以垃圾邮件识别为例:

抽取交叉验证集中错误分类的,进行手动分析。猜测一些特定的特征,例如药品相关右键,可疑的邮件路由,错误的拼写。统计这些错误识别的垃圾邮件不同特点各自具有的邮件数目,以决定我们对于模型的修复如何进行。
例如,如果药品相关的邮件很多被错误识别,那么可以增加更多的药品相关的训练数据。对于比较少出现的错误特点,其修复的优先级也较低。
如果交叉验证集的错误很多,那么要根据团队规模和时间成本来抽取一部分进行错误分析。
错误分析擅长解决人类擅长的问题,因为我们是手动分析的,对于主观性较强的问题,则不太适用。
获取并添加数据的好方法
对于不同的应用程序,我们都有添加数据的不同技巧。
之前的错误分析告诉我们,如果限于获取所有类型数据的大量成本,可以只考虑对于性能影响最大的因素来添加数据。
数据增强 Data Augmentation
修改一个现存的训练示例来创造一个新的示例,例如将字母A的识别样例进行旋转放大缩小

还有扭曲版本:

也适用于语音识别:在原来声音的基础之上,加入了各种背景噪声,例如汽车的声音和人群嘈杂的声音,甚至是手机信号不好时质量较低的音频。我们在语音输入进行数据增强的时候,一个技巧是对数据所做的更改或扭曲应该代表测试集中噪声或扭曲的类型,也是我们期望可能发生的情况,添加无意义的噪声并不会帮助很大。

数据合成 Data Synthesis
手动创建一些训练数据:
例如在照片OCR中,通过不同的字体可以模拟照片中可能出现文本的情况。

一般用于计算机视觉。
数据工程 Engineering the data used by your system

迁移学习 Transfer Learning
如果没有那么多的数据,那么应用程序可以使用迁移学习。这是一种很棒的技术,它可以让你使用来自不同任务的数据来帮助应用程序。

迁移学习用一句话概括来说就是我们将一个没有什么关系的神经网络及其相关任务应用于我们自己所需要训练的神经网络之中,例如,将一个识别动物和人以及汽车等图像要素的神经网络应用于我们零到九的数字识别中。迁移学习分成两步。第一步,称为监督预训练,这是训练那个无关神经网络的过程,获得相关的参数。第二步称为微调,将上述除输出层以外的所有参数应用于我们自己的模型,作为我们模型的参数或者我们模型参数的初始值进行微调,在这个基础上重新生成各个参数。
此时有两种选择。
Op1:我们只训练输出层的参数,直接应用无关模型的隐藏层参数作为我们模型的参数。
Op2:隐藏层和输出层我们都进行重新的参数训练,不使用原有的参数,但是原有的参数作为我们训练的起点。 无关模型的参数对我们的参数进行初始化,然后我们应用梯度下降等方法优化我们的参数。
一般来说,用小数据集的模型一般使用第一种选择,即使用其无关模型的参数直接作为我们自己模型的参数。而对于较大数据集的模型,我们通常会训练所有的参数。
在实际使用建议学习的情况中,我们通常不会自己训练一个无关的模型。也就是说,我们不会自己进行监督预训练。现在网上有大量人工智能机器学习研究人员发布的免费的神经网络模型。 下载这些模型,并在它们上面进行参数的微调可以帮助我们迅速地构建一个可以较好完成我们学习任务的神经网络。
为什么迁移学习是有效的?

事实上,在类似于计算机视觉这样的场景之下。 神经网络会首先学会识别一些横竖线,边缘,曲线等元素。这些图像元素的识别能力可以应用于其它的场景,因此进行监督预训练,对我们训练自己的模型是很有帮助的。 需要注意的是,如果我们在监督预训练的基础上进行模型的微调,我们需要确保输入X的类型是一致的。

因此,迁移学习通常在网络上下载已经经过大量数据集训练的成熟的神经网络模型,在用自己的小数据集进行微调,这样就可以得到一个较好完成我们任务的神经网络模型。例如GPT3等都用到了迁移学习。
机器学习项目的完整周期

• 项目范围
• 收集数据
• 训练模型
• 部署生产
上面的过程大体上是按顺序的。但是在训练模型的过程中,我们有可能会需要收集更多的数据。待部署模型的过程中,我们也可以收集到更多的数据。我们的课程里已经介绍了前三部分关于项目范围收集数据和训练模型的内容。现在我们即将进入在生产中部署模型的内容。

移动应用,通过API call来唤醒推理服务器。 机器学习模型被部署在推理服务器中,它在推理之后将结果传递给移动应用。 在我们的例子中,声音切片作为API call的内容传递给推理服务器,得到服务器的文本转化结果。
部署机器学习系统时,可能会用到大量的软件工程。软件工程配合MLOps(机器学习操作)确保模型可监控可扩展且良好维护。
公平,偏见有害与道德伦理

建议:

• 更多元的团队进行头脑风暴
• 查阅标准和建议
• 部署前的审查
• 提前制定缓和计划
倾斜数据集的误差指标
如果正例和负例的比例非常不均,和50-50相去甚远,那么通常准确度效果不佳。
例如在罕见疾病诊断的例子中:

如果患病率是0.5%,直接预测y=0的模型比错误率为1%的模型的错误率还要低,但是这并不代表这个模型的行为是正确的。
用精准率和召回率来衡量模型的准确度:

请查看各自的定义:
• 精准率指我们的预测有多少次是正确的。真阳性数量/预测阳性数量
• 召回率是指我们成功预测了多少个阳性。真阳性数量/实际阳性数量
在二者都较高时,说明我们的模型具有更少的误差。
精确率与召回率的权衡

• 设置仅当非常自信时才将二元分类的结果定为1,会导致高精确度,同时降低召回率(预测结果很肯定但是可能会漏判)。例如当预测需要侵入性治疗的高成本疾病时,采用这种方法。
• 设置一个低的阈值,则会导致高召回率(几乎不会漏判)和低准确度(可能有更多误判)。
• 绘制一个精确率和召回率的曲线可以权衡二者。
F1 Score
自动选择一个能够权衡精确率和召回率的方法。
(使用平均值是不理想的)
F1分数是P和R的调和平均值,可以关注到二者的很小的值。对于P或R很小的算法,F1分就会比较低。

Week4
决策树模型
并不广泛但是非常重要的工具。
猫分类示例

输入三个特征x1,x2,x3:分别表示对象的耳朵形状,脸型,是否具有胡须,二元分类输出是否预测为猫。
• 此处的特征都只有两个可能值,后续我们会讨论连续值以及多个离散值的情况。

决策树的分支节点叫决策节点,叶节点作为输出。
决策树学习算法的工作原理是从所有可能的决策树中,尝试选择一个希望在训练集上表现良好的树,然后理想地泛化到新数据,例如交叉验证和测试集。

训练过程——给定训练集构建决策树

从根节点开始,决定每个决策节点采用什么特征分类。直到分类出来的子群体只有猫/非猫。
做这些决定的细节在接下来介绍。

  1. 首先是决定使用什么特征
    实际上,选择的是让纯度最高的特征(下面介绍)。例如如果我们有关于DNA的信息,那么它几乎可以将猫和狗完全区分开来,那么这个特征就会导致很高的纯度。

  2. 决定何时停止节点的分裂
    • 100%分类时停止
    • 达到最大树深度时停止(通常根节点为0深度),这可以防止树变得太高和笨重,也不太容易过拟合。
    • 纯度的提升过小
    • 节点分出的示例数量低于某个阈值,也可以防止过拟合
    纯度 purity 衡量(熵,杂质)

定义p1分数,即是猫的示例占总示例的分数。
建立关于p1的函数H(p1),用于描述熵的大小。最混乱的50-50情况下,H=1。最纯净的只有猫或没有猫的情况,H=0。
H的公式如下,同样是类似于逻辑损失函数的定义方法,数学原理一致,此处不深究:

• 取log2而不是ln,是为了让峰值为1便于解释。ln也可以工作。
• 0处事实上是未定义值,但是极限是0。
熵函数的方法适用于大多应用,其它例如Gini也对决策树构建起作用。
选择拆分:信息增益
熵的减少也叫信息增益,下面我们看看如何计算信息增益,从而选择在决策树的每个节点上使用哪些特征进行拆分。

计算出根节点和每个特征分裂出的决策节点的p1分数,用熵函数计算出其熵值。
由于左右分裂出的节点所含有的示例数不同,我们往往希望示例较多的节点具有更小的熵值,因此对左右节点的熵进行加权平均,用于相互对比。
实际上我们比较的是熵的减少量,这个减少量就是信息增益。我们用根节点(父节点)的熵减去左右孩子熵的加权平均值,选择一个熵减少最多的特征作为分裂特征。这样做的原因还包括熵的减小是我们考虑是否继续分裂的一个因素,如果熵的减小小于一个阈值,那么这个分裂的意义并不大,而且可能导致树过于庞大而产生的过拟合问题。

• p表示节点p分数
• w表示加权平均权重
• H表示熵函数
整合上述知识——构建决策树

• 从根节点开始,计算信息增益,选择最高的信息增益特征进行分割。
• 重复分割直到满足停止分割的四个条件。
• 这是一个递归的过程
• 决策树深度类似于多项式的阶数,可以用交叉验证集选择合适的参数或者使用开源库的默认值。
分类特征的独热编码使用 one-hot encoding
我们之前的特征都只有两个可能值,现在我们引入分类特征:

耳朵的形状有3个可能值。拆分特征时节点分裂如下:

这里我们采用独热编码的方式处理两个值以上的特征。

将有三个值的特征转化成三个有两个值的特征:是否–,是否–,是否–

如果一个分类特征有k种取值,那么创建k个二元特征来转换——独热编码。取值为1的称为热特征,因此称为独热编码。
将特征取值转化为数字输入,独热编码也适用于神经网络的训练:

连续取值的特征处理
设置不同的阈值进行分类,阈值可以取特征排序中间的值,对每个阈值导致的分类结果计算信息增益,选择让信息增益最大的阈值。同时用这个信息增益比较其它的特征的信息增益,最后决定节点的分裂依据。

回归树
我们之前只讨论决策树的分类算法,现在我们将其泛化为能够预测一个数字的回归方法。
假设我们不再预测动物类别,而是预测动物体重:

这个模型最后对叶节点的示例体重取平均值作为预测的结果。

然而和分类问题不同,我们如何在每一个节点选择分裂的依据特征?我们不是试图减少熵,而是减少每个数据子集的Y的加权方差,让平均加权方差尽可能降低。
我们计算每个子集的方差,进行加权平均,再计算出方差的下降(类似于信息增益),最后选择方差下降最大的特征来作为分裂的依据。
之后递归地进行这个过程,直到满足停止分裂的条件。
决策树集成——使用多个决策树
单棵决策树可能对数据变化非常敏感。为了提高健壮性,采用树集成的方法。

我们只需改变一个小猫的特征,决策树的根部分裂特征就发生了变化,这让模型不够健壮。

如果我们有这样一个三棵树的集成,就可以根据所有的预测结果决定最终的预测结果。
让大量的决策树投票,让算法整体不拘泥于一棵树的具体行为,降低敏感性,使算法整体更加健壮。
树的集成方法——Sampling with replacement 带放回抽样法

带放回抽样法有重复,且结果不一定包含所有示例。得到了新的训练集,这是树集成的关键构建块。
随机森林算法
现在我们有办法用带替换抽样来创建新的训练集,这些训练集和原始训练有点相似但也有很大不同。
生成不同的决策树
用创建的新训练集构建决策树,由它们投票产生预测结果。构建的树不要远大于100棵,否则复杂的计算导致整体性能下降。

生成的也叫做袋装决策树,每棵树之间有一些小差异。
这样做比单个决策树更稳健是因为替换的过程导致了算法探索数据的许多小变化,并且训练这些决策树可以导致一种平均的数据变化,因此训练集的小变化不会导致预测结果发生大的改变。
随机森林算法原理
根节点处仍然很可能是相同的特征分割。因此可以进行优化:
每次只选取n个特征中的随机k个,在这k个中找到用于分割的特征。

这就是随机森林算法,k常常取根号n。
树集成——XGBoost
构建每一棵决策树而创建新的训练集时,那些先前表现不佳的示例被选择的概率更大。这是刻意练习的原理。

XGBoost采用极端梯度提升,快速而高效。而且很好地选择默认的分裂标准和何时停止分裂的标准。还内置正则化防止过拟合。

👆XGBoost的优点。
使用方法

何时使用决策树,何时使用神经网络?
决策树和树集成:
• 结构化数据
• 快
• 人类可解释(大型时也不明显)

神经网络:
• 所有类型数据,包括结构化和非结构化数据(图片,视频,音频)
• 可能更慢
• 与迁移学习一起工作
• 大型模型可以串起多个神经网络一起训练

Chirs Maning 谈自然语言处理
NLP
变压器架构 Transformer
第三课 无监督学习 推荐系统 强化学习
Week1

什么是聚类 clustering
监督学习如二元分类有标签y。

在无监督学习中,没有目标标签,因此我们不能告诉算法我们想要预测的正确答案。聚类算法在数据中寻找特定集群结构。

聚类应用:

K-means算法
可视化介绍
K-mean算法先决定将数据分成几个集群,然后初始化一个或若干个集群中心(簇质心),然后反复做两件事:
• 判断所有点和哪个簇质心更近,然后将其分配给对应集群。

• 移动簇质心到所有同集群点的中心

• 重复上述两步,直到簇质心的位置没有变化,此时算法收敛。

得到两个集群:

详细描述

• 随机初始化K个簇质心
• 重复计算每一个点(两个数字的向量)到每个簇质心的距离,将它们归入一个簇质心的集群。ci是集群索引数字

• 取所有同类点的平均中心,作为新的簇质心
• 重复2,3直到所有簇质心不变
• 没有点的簇质心通常直接删除。如果一定要限定簇质心数量,可以重新随机初始化尝试。

在分隔不明显的例子中,K-means算法也能很好地工作。
K-means算法优化的成本函数(失真函数 Distortion)

成本函数定义为每个示例点到其簇质心距离的平方的算术平均值。
最小化这个平均值可以找到簇质心的最佳位置。

最小化成本函数减少失真事实上就是我们算法的操作步骤所做的内容,它们的机理是一致的。

这个成本函数一般不会上升,通常处于下降或不变的状态,以此我们可以判断代码是否错误以及K-means是否收敛。对于下降非常缓慢或者不变一段时间的情况,我们认为已经足够好了,可以认为收敛。
初始化K-means
随机初始化K个簇质心的具体过程。
• K(簇质心数量)<m(示例数量):比示例数量还要多的簇质心数量是没有意义的,多余的簇质心无法分配到示例。
• 随机选择m个中的K个训练样例作为簇质心μ1…k的初始位置(不同于我们之前说的任意完全随机的位置)

• 有时不同的随机初始化会导致成本函数陷入不同的局部最小值,得到不同的聚类结果:

可以多次运行K-means,比较每个局部最小值的成本函数J,以找到最佳的局部最小值。
具体描述:

选择聚类数量 K
有时聚类的数量没有一个标准答案,因为它是无监督算法,并没有特定的标签形式,数据本身就无法明确指出可以分成几个集群。

参考方法:肘法 (elbow method)

选择不同的K值计算成本函数,这种方法并不建议,因为成本函数曲线很可能几乎是平滑的,难以选择。
推荐的方式是用之后的聚类目的来选择K的值:

例如T-shirt的尺码分类,可以是三种,也可以是更精细的五种。这是我们在衣物生产成本和尺码需求进行的权衡。类似的还有图像压缩的K-means,需要在图像的压缩程度和图像的视觉效果之间进行权衡。
异常检测算法 —— 发现不寻常事件
以飞机发动机检测为例:

我们用概率密度判断异常情况的可能性:

先计算出已有的发动机参数的概率模型,椭圆的中心处具有很高的概率,意味着新的发动机最可能具有接近这部分示例的参数,外部椭圆的概率则逐渐减小。如果新测试示例的概率很小,落在所有椭圆的外部,那么它可能需要重点关注。
异常检测的应用:

欺诈检测,制造业……
异常检测 —— 正态分布(高斯分布)

改变μ和σ的值可以影响正态分布的曲线:

最大似然估计:

异常检测算法
对于训练集,选择可能能够指示异常的m个示例x(1)…x(m),每个训练示例有n个特征。
根据每个示例的n个特征计算补充正态分布的参数,得到每个特征的概率计算正态分布公式。
对于一个新的示例,将其每个特征和该特征对应的正态分布概率计算出来之后进行连乘(特征之间可视为独立),得到一个新的示例的概率p(x),这个概率如果小于一个特定值,那么说明它很可能存在异常。

如果新示例仅仅只有一个特征的p(xj)非常小,那么总的乘积也会很小,因此异常检测算法是一个系统的方法,用于量化一个新示例x是否具有异常大或者异常小的特征,通过正态分布予以概率的体现。
可视化例子:

如果看两个特征的正态分布乘积,那么可以根据原有的示例选择特征,填充参数,写出公式,从而可视化一个二元函数图形。对于新示例x(test1)和x(test2),分别将他们的x1,x2带入概率的计算公式,将结果与ε比较,就可以推测哪个新示例可能存在异常。
如何选择异常检测概率阈值ε & 异常检测系统性能评估
实数评估 real number evaluation
开发算法时,如果我们在改变特征或改变参数时能够有一种计算数字的方法来告诉我们算法是好是坏,那么我们会更容易作出决定。

虽然我们目前在讨论无监督学习,但是在大量的示例中,我们可以获取一些带有标签的示例,例如飞机发动机故障与否的1/0。由此我们可以设置交叉验证集和测试集。

在飞机发动机例子中,我们构造训练集,交叉验证集,测试集。其中训练集是全部ok的示例,cv集我们用于调整ε和xj特征(含异常),测试集用于测试其它样例(含异常)。
如果异常示例过少,那么也可以不含测试集,只有cv集。虽然可能导致对于cv集的过度适合,但是这是相对理想的办法。

在cv集和测试集上计算之前提到的可能需要的性能指标,例如真阳性,假阳性,精确率和召回率,f1分数等。
异常检测算法 vs 监督学习
既然我们对异常检测进行了结果的0/1标记,那么我们为什么不使用监督学习算法?
或者说,我们何时选择异常检测算法,何时选择监督学习呢?

通常来说,正例少负例多的采用异常检测,也就是说,正常情况多,异常情况少的时候,异常检测更合适。因为任何偏离正常的都会被系统认为是异常,而且未来的异常和目前已经出现过的大不相同,例如欺诈识别,飞机发动机故障识别,未知目标的产品检测。
对于正例很多但是负例很少的时候采用监督学习。算法通过大量的正例感知正例应该具有什么特点,从而预测未来可能会出现的正例,这些正例往往不会有很新的形式,例如垃圾邮件或有目标的产品检测。

选择异常检测算法的特征
在监督学习中,如果特征不完全或者有额外的特征是不影响的。 因为监督学习算法可以自己忽略一些特征或者缩放特征。
但是仔细选择特征对于异常检测很重要。
非高斯分布特征

将非高斯分布的特征转换为更符合高斯分布的形态。

修改Jupyter notebook中的hist内容,可以选择使数据更符合高斯分布的转换。同时对交叉验证集和测试集也要应用相同的转换。
异常检测的错误分析

对于没有检测出的异常(例如概率还不够小的情况),可以考虑增加一些能够让它们概率小到足够的特征,让异常示例的概率具有明显的可比性。
例如数据中心的计算机检验:

创造了新特征x5,帮助检测CPU负载很高但是网络流量很低的异常遗漏。
Week2 推荐系统
推荐系统的框架例子

使用每个特征(per-item features)
为每一个用户拟合不同的线性回归模型:每个用户都有自己的参数w,类似于线性回归的预测。
(此时的w(1)是学习出来的,不是根据评分得来的)

因此用户j的成本函数如下:
参数的含义如图:

注意:
• i:r(i,j)=1是只对已评分的电影求和均值归一。
• 实际可以把已评分电影数量m(j)提出来
转化成所有用户的成本函数,即将每一个用户的成本函数求和。

非常类似于线性回归,但是现在每一个用户的参数不同。
协同过滤算法
如何取得上述x=(x1,x2)这样的关于电影的特征?
假设我们已经通过某种方式(后续介绍)知道了预测各个用户电影评分的参数w1…4以及b1…4=0。我们由此猜测x(j)=(x1(j),x2(j))的值:

再定义了成本函数:

对单个示例的成本函数(平方误差含每个特征的正则化项)以及对所有电影示例的成本函数(全部求和)。
至此,我们讨论了有x=(x1,x2)特征但没有参数的学习过程以及有用户参数但没有特征的学习过程,将其合并为协同过滤算法:

两个不同最小化变量的成本函数合并在一起组成了协同过滤的成本函数,事实证明,使这个成本函数最小化是有效的。

因此在梯度下降中,我们也要更新协同过滤算法新加入的变量x,x也是一个需要调整的参数。
协同过滤算法可以利用多个用户的协作,猜测所具有的特征,预测未来和其它用户的评级。
二元标签:favs,likes and clicks
以电影为例,定义标签0/1/?的含义的方式有多种:

从回归到二元分类,我们采用和逻辑回归很相似的行为,来预测用户很可能参与项目的可能性:

同时也要选择更适合逻辑回归的成本函数:

均值归一化
对于没有进行评分的用户,我们目前的策略会预测它对所有的电影评0分,这是由于成本函数中的正则化项(不考虑b),因此它的参数都是0。这并没有起到真正预测的作用。因此需要采取均值归一化。

将评分列为矩阵,对一部电影来自所有用户的评分取平均值,所有的存在评分都减去这个平均值,再参与模型的训练。这样导致了“负分”的出现,也就使没有参与过评分的用户打出0分变得合理。最后得出预测结果时,要加上该部电影的评分均值μ(i),这样未评分或很少对任何电影评分的用户的预测结果都是该部电影评分的均值,这样比直接打出零分更加合理。
这个过程是行归一化,是针对一个未评分的新用户采用的合理化手段。如果是列归一化,那么是对一部从未有人打分的新电影采取的手段。一般而言,新电影并不着急展示评分,因此行归一化的优先级要更高一些。
均值归一化可以让学习过程更快,也更合理。
TensorFlow实现协同过滤算法

• 首先声明参数w,以及x,y,学习率α,做好梯度下降的准备。
• 然后设置迭代次数,设置梯度带,用于告诉tensorflow如何计算成本函数,这是Auto Diff(自动微分)必需的步骤。
• 之后运行梯度下降过程,自动计算导数dJdw,以及用特殊的assign_add()方法更改w。
• Auto Diff 和 Auto Grad是几乎一致的说法,前者更正确。
我们也可以实现更高级的梯度下降,例如带有Adam优化器的:

• 成本函数需要实现
• zip用于合理排序梯度下降函数内部的数字
为什么我们不使用之前学习过的神经网络密集层来完成这些工作?有时候成本函数的形式不支持我们这样做,因此我们采用了tensorflow另一种高效的方式完成,打开全新的思路。
寻找相关的特征
如何实现在推荐系统中推荐类似的电影书籍这样的操作?协同过滤算法已经给了我们一个解决方案。

当特征很难解释的时候,可以使用平方距离来显示示例之间特征的相似程度。
冷启动和边缘信息

基于内容的过滤算法
与协同过滤对比

• 纯粹的协同过滤基于用户评分
• 基于内容过滤是根据用户特征进行匹配
• y(i,j)是用户给出的评分
用户可能具有一些特征,电影也会具有一些特征。特征举例:

基于内容过滤的算法——学习匹配

用向量vu和vm代替之前的写法,从用户的特征xu(j)以及电影的特征xm(i)中得到两个size一致的向量vu(j)和vm(i),将它们点积,结果作为评分的预测。xu和xm的size可能不一致,但是v的大小必须一致,因为要进行点积。
vu和vm的含义可以是用户的喜爱程度和电影的类型等,我们的目标是对这两个向量作出适当选择。使其点积能够很好地预测用户j对电影i的评分。
我们之前的协同过滤算法要么是根据用户已有的评分来预测电影评分,最小化成本函数获取w(j),要么是根据电影的特征来获取用户的偏好参数,最小化成本函数获取x(i),要么是二者协同构成成本函数进行学习。现在我们使用的是基于内容过滤的算法,我们获取了用户的特征,也获取了电影的特征,我们的目标变成了选择适合的v向量,用向量点积的方式预测结果,二者是有区别的。
基于内容过滤的深度学习方法
如何计算vu和vm?可以使用神经网络:

输出层是相同的32个单元,构成两个向量vu和vm。
如果要进行二元标签预测,还可以套一层sigmoid函数作为结果。
合并成一张图:

同时我们可以用协同过滤算法中的平方距离法来判断相似的电影:

从大型目录中推荐

目录的数量过于庞大时,计算可能变得不可行。
怎么做?
• 检索,生成一个大的列表代表可能推荐的电影,使用平方误差计算相似度。
• 清除重复或已无须推荐的项目

• 预测评分进行排名

• 作出权衡:是否要检索更多的项目?

推荐系统的道德伦理
推荐系统的目标

更具体的例子:什么推荐是对社会有益有害的?

Amelioration: n. 改进;改善;改良
基于内容过滤的TensorFlow实现

• 定义两个密集层构成的神经网络,使用默认的relu函数作为激活函数。
• 输入特征xu和xm获取vu和vm,并进行归一化(L2范数)
• 利用keras的dot方法获取输出
• 训练模型,最小化成本函数
PCA算法 主成分分析 减少特征数量

以汽车特征举例:
汽车的宽度和轮径一般是偏一致的,因此可以不将其考虑在内
长度和宽度可以通过找到新的轴来测量坐标

3个特征→两个;3D到2D:

50→2特征
PCA算法实现
实际上是找到一个不同的轴,用于减少特征。
准备工作:
• 均值归一化,让特征具有0均值
• 特征缩放,避免特征单位不同的误差

选择一个轴:

• 不错的选择,方差很大说明数据分布分散,信息多

• 不好的选择,点被压缩在一起

• 最好的选择,这时轴被称为(第一)主成分(principle component)。拥有最大方差。

用一个数字表示一个二维特征的方法是构造主成分的单位向量,然后与该特征和原点的向量作点积,得到投影的长度。

第二主成分和第一主成分垂直,添加的任何附加轴都与其它轴垂直。

与线性回归的区别:

• 线性回归有真实标签,寻找的是最接近真实标签的直线。
• PCA是无监督算法,没有真实标签,寻找的是保留原特征最大方差的降维方法。

PCA重建

乘上原来的单位向量,可以估计原始的特征。
PCA算法代码实现
用scikit-learn库实现PCA。

• 先特征缩放
• 然后fit方法,自动进行均值归一化,然后找到新轴
• 计算主成分方差
• 转换
2D→1D

• 0.992指信息保留率
• 转换后打印转换的数组
2D→2D
(实际上没有实际意义)

重建后和原来一致
PCA应用

Week 3 强化学习
什么是强化学习

奖励函数,指出什么是好的,什么时候做的不好,但不说怎么做(不告诉正确输出),算法自己找出好的办法。

示例:火星探测器

• 火星探测器在六个状态中的某一格,其中状态1和6奖励分别是100和40
• 火星探测器每次选择向左或向右移动,直至到达边缘的最终状态(状态1或6)
• R(s)是状态s对应的奖励,s’是移动后的新状态
强化学习的回报
折扣因子

在回报的计算方法中,每一个状态的奖励都会乘上当前折扣因子的幂,且幂逐渐升高。一般采用略小于1的数来定义折扣因子,在此为便于说明,使用γ=0.5。
折扣因子γ体现了决策的“急躁程度”,折扣因子大的情况会让探测器更耐心地长时间寻找更大的回报。
折扣因子也适用于货币等领域。
行动决定回报

总是向左移动和总是向右移动的回报可以逐状态计算,然后选取回报最高的动作。
如果有负奖励,那么强化学习的策略是尽量推迟它的到来。
强化学习的策略

Π函数以状态为输入,输出动作。Π函数在术语中称为Policy。
关键概念:

马尔科夫决策过程
强化学习的程序。未来只取决于现在但不取决于过去(如何到达现在)

状态-动作价值函数(Q-函数/Q*/最优Q函数)的定义

Q函数输入当前状态s和动作a,输出的是一个回报,它来自于在当前状态s做完动作a之后进行一系列最理想(可能的最终回报最高)动作到达最终状态的回报。

• 因此状态s可能的最优回报就是max(a)[Q(s,a)]。
• 状态s可能的最优动作是取得max(a)[Q(s,a)]的动作。
• 若Q(s1,a1)=max(a)[Q(s,a)],则Π(s1)=a1。
Q-函数示例

Jupyter notebook中的示例,调整折扣率和状态回报函数都会改变Q函数以及Π(s)。暂时不考虑失误率。
贝尔曼方程
如何计算Q函数?用贝尔曼方程。

示例:

• 与终端状态相邻的Q不存在a’因此=R(s)。
贝尔曼方程的解释

贝尔曼方程的本质在于将当前状态和动作的回报分为两部分:

  1. 即时回报,即做出动作a的立即回报。
  2. 状态s做动作a导致的下一个状态s’做出最优动作a’以及之后的最优动作的回报。
    不难看出,s’做出最优动作a’及其之后最优动作的回报=max(a’)[Q(s’,a’)]。直觉告诉我,最优序列本身是一个递归的序列,可以采用立即回报+之后最优序列给出的回报来递归地计算Q函数。同时,终端状态的Q函数非常容易计算,可以将其作为递归起点,从而计算每一个状态以及动作的Q函数。

随机(random/stochastic)环境
实际情况下,事情并不会完全按预想发展,例如我们的火星探测器可能会有概率朝相反的状态前进:

因此我们期望得到的回报从一个折扣率加权和转化成了平均的加权和期望。我们需要考虑一个状态所有可能的回报及其可能出现的频率来计算预计的回报。
因此在贝尔曼方程中我们也加入均值符号,因为s’是随机的,s’采取a’导致的新状态也是随机的,所有的Q计算过程都需要采取均值策略:

增加失误率相较于理想状况会减少回报。
连续状态空间应用
不同于之前的离散状态,我们可能会有若干连续的状态,例如卡车的状态向量的每一个分量都是连续变化的值。

对于直升机,甚至还有偏航角之类的连续值分量:

任何连续状态的强化学习问题称为连续状态马尔可夫决策过程(连续MTP)。
月球登陆器模拟

状态含义:
• 坐标位置x
• 坐标位置y
• x方向的速度
• y方向的速度
• 倾斜角度
• 倾斜角速度
• 左腿是否着地(0/1)
• 右腿是否着地(0/1)
奖励函数

指定奖励函数,让登月器在每个状态采取正确且确切的操作。指定奖励函数是一项重要且不易的任务。

监督学习预测Q函数
我们将训练一个神经网络,该网络输入当前状态和当前动作并计算或近似计算Q(s,a)。

• 12个输入中包含8个状态分量和4个动作的独热编码
• 我们只是利用神经网络计算Q函数,并不是像监督学习那样输出动作。选取s状态下最大的Q(s,a_),就可以指定当前的动作。
• 该方法使用贝尔曼方程来创建包含大量示例的x和y的训练集,然后使用监督学习预测Q的值
如何获取计算Q的监督学习训练示例
对于若干个元组(s,a,R(s),s’),计算他们的Q作为y,就可以得到一系列训练示例:

• maxQ的计算并不是我之前直觉的递归,而是通过近似猜测的方式,让其慢慢变好。

记录10000次登月以构造数据集(replay buffer 缓冲重现),将猜测的Q慢慢优化为Qnew,最终用Qnew设置神经网络。
这样的算法也叫DQN=Deep Q-Network,因为我们使用了深度学习神经网络训练模型来学习Q函数。
改进

直接输出所有动作的Q函数,以免训练四次。同时这样对于max也有好处。
算法优化:ε-贪婪策略

我们在上述采取的行动是在我们还没有完整学习完Q函数时采取的。在我们没有很好地估计Q(s,a)的时候,我们如何采取进一步的行动呢?

• 完全随机行动的方式是低效的,需要其它方式取代。
• 第一种方式是采用只取计算出的(例如4个)Q中最大值行动的策略,这是可行的,但是会出现问题。
• 第二种方式是在一些可能下采取随机行动的方式,但是大多数情况下采取选择Q最大值动作的策略。这样做可以避免一些Q往往比较小的动作(例如主推进器启动)被永远地忽视,以至于算法无法发现这样做是让总回报最高的方法。
这被称为ε-贪婪策略,在ε的概率下随机,在1-ε的概率下贪婪(也叫做剥削,取最大Q动作)。我们可以在一开始设置较大的ε,甚至是1,然后逐步减小,表示我们随着Q的预测值变得更加精准而放弃了随机动作的想法。
ε和学习率等参数的选择是强化学习区别于监督学习的困难之处。
小批量(mini-batches)和软更新
小批量

监督学习中,在训练集非常大的时候,可以小批量选取一部分进行梯度下降。

小批量的梯度下降方向可能且往往不是最理想的梯度下降方向,但是最终可以达到成本函数的全局最小值,且速度更快。
强化学习同理:

软更新
软更新可以让Q一点点地接受Qnew的新值,实现更可靠的收敛,避免强化学习算法振荡转移等不良特性。

强化学习的地位
强化学习在其应用程序效用方面的实际意义。

课程总结和致谢
课程总结:

Chelsea Finn访谈

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
对于"吴恩达机器学习笔记2022"的问题,我没有在引用的内容中找到具体的相关信息。根据我所了解到的是,吴恩达是一位著名的机器学习专家,他在机器学习领域有很高的声誉,并且他的机器学习课程非常受欢迎。他的机器学习课程涵盖了从基础概念到实践应用的广泛内容,可以帮助学生建立起对机器学习的扎实理解并掌握相关的技能。如果您对具体的吴恩达机器学习笔记2022有进一步的问题, 请提供更多的细节,我将尽力为您解答。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [【机器学习 吴恩达】2022课程笔记(持续更新)](https://blog.csdn.net/weixin_45837404/article/details/128709041)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [2022吴恩达机器学习课程学习笔记(第一课第一周)](https://blog.csdn.net/Yang0114_/article/details/127400605)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值