Jean's Blog

一个专注软件测试开发技术的个人博客

0%

算法说明

最简单的算法:逻辑回归介绍

机器学习算法的运作原理

经过之前的学习,我们知道实际上系统进行识别和预测的流程就是:

  • 针对用户数据提取特征

  • 从模型中查询对应的特征与权重

  • 将所有特征权重进行累加

最后的累加过程类似:

这里面至关重要的一点就是如何确定每个特征的权重,而这正是机器学习算法需要做的事情。用一句话总结就是,用户负责提取特征算法负责计算出这些特征的权重

所以这个算法的公式其实就是:

  • y代表预测结果

  • x代表特征

  • w代表权重

  • b是偏移量

其实还会有其他的参数, 比如L1和L2, 这两个是正则化,用来防止过拟合的,不过我们目前不需要了解这么多。 这个算法的名字就是线性回归。之所以叫线性回归,因为函数是线性函数。在图中是一条直线。

image-20250716170559422

上面的图中,所有红色的叉就是数据的分布,我们可以理解为算法要做的就是拟合出一条线,让这条件与这些叉的距离最近。

回归与分类

一般来说模型的应用场景有几种通用的区别。其中回归算法是用来预测一个具体的值,比如我们要做一个预测房价的模型,也就是 y=wx+b。它是用来预测某个具体的数字的,这种场景和模型被称为回归类型的。(还有一个常见的场景,大数据杀熟)

而分类算法是在一群实体中将物品进行分类,例如二分类算法中,预测值只有 0 和 1,就如我们说的反欺诈模型正式一个二分类模型. 而逻辑回归算法是一个二分类算法,同样用了线性回归公式,也就是 y=wx+b。 但是我们的期望值是 0 或者 1。

所以其实我们是使用一个激活函数来把我们的预测值给变换成 0 和 1. 这就是为什么逻辑回归虽然叫回归但却是二分类算法的原因 (它多了一个激活函数把预测值变换成 0 或者 1 的数值)。

而除了二分类意外,还有多分类场景。

激活函数

激活函数不是真的要去激活什么。在算法中,激活函数的作用是能够给神经网络加入一些非线性因素,使得神经网络可以更好地解决较为复杂的问题。例如我们给逻辑回归用的 Sigmoid 函数:

image-20250716171110885

线性回归算法计算出的结果是一个数值, 而sigmoid则会把这个数值转换成0~1之间的数值。 我们可以把它理解成模型帮我们计算出了一个概率。比如在反欺诈场景中,当模型输出的值是0.8时,我们可以认为有80%的概率是一个信用卡盗刷的行为。这样上只需要设置一个置信度(也叫阈值),比如0.7,代表着凡是概率超过0.7的我们就认为它是信用卡盗刷行为。 这样我们就完成了一个二分类的场景。

当我们再把激活函数换成名为Softmax的时候,它就会变成一个多分类的算法,比如我们有一个图像识别的算法,它可以识别出人,狗,猫,老鼠。那么它的输出会变成这样:

1
2
3
4
猫: 0.1
狗:0.2
老鼠:0.3
人:0.4

softmax函数会输出每一种识别对象的概率(所有对象的概率加起来等于1)。这样我们就又得到了一个多分类的模型。所以虽然业务上的场景不同,但背后的算法是一样的,不同的只是最后的激活函数的不同。

测试人员尤其需要注意这一点,在很多性能测试场景中不要过度的进行场景覆盖,比如每种识别对象都单独测试一次,这是没有必要的。

逻辑回归,损失函数与梯度下降

算法的目的就是通过一定的方法来计算出特征最合适的权重,而这个方法就是梯度下降,梯度下降算法应该是人工智能领域中最基础也是最重要的方法了。 因为它是逻辑回归的基础,而逻辑回归是最常用的算法之一,并且也是目前流行的深度学习的最主要的算法基础。

而梯度下降算法则按照一定的方法不停的去更改w和b的值,最终追求一个合适的w和b的值让我们的结果与真实的情况最接近,而要完成这个目标,我们需要一个损失函数,来衡量算法的运行情况,或者说衡量以这次计算的结果是不是更好。实际上损失函数就是在比较算法计算的结果和真实的结果的差距。

image-20250716172235310

上面是成本函数的图, 可以看到成本函数是一个凸函数,它只有一个最优解。我们要做的就是随便初始化一个 w 和 b 的值 (通常是 0), 也就是图中最上面的那个红点。 然后接下来要做的就是一轮又一轮的迭代,每一次迭代都减少 w 和 b 的值让红点向下走,一直到最下面的那个小红点, 或者最接近那个小红点的地方。这也就是我们找到全局最优解的地方。在这里成本函数的值最小。也就是说我们的预测值是最接近实际值的。这样我们的训练过程就结束了,也就是我们学习到了最适合的 w 和 b 的值。

在梯度下降算法中,我们不停的变换 w 和 b 的值来一次次的迭代,再通过损失函数来评估这一轮w和b的值是否比上一轮更优,至于要怎么变换w和b的值呢, 我们每一次都用 w 自身减去α(学习率) 和成本函数 J 对 w 的导数(也就是斜率)。

训练模型的建模代码有这样一段:

1
lr = LogisticRegression(labelCol="label", featuresCol="feature")

这行代码我们就初始化了一个逻辑回归的算法(LR就是逻辑回归的缩写)它需要最少两个参数,featuresCol是特征向量,而labelCol是label,也叫标注,或者y值。它是这一行数据的真实的预测结果。损失函数也是通过这个真实的结果来评估算法效果的。

超参数

参数与超参数的区别

机器学习算法中有很多让人迷惑的术语。 比如参数和超参数,我们作为测试人员其实可以不用知道所有的超参数所代表的含义和原理,但是也需要知道一些基本 的概念,否则在项目中进行交流也会有障碍。

而其中参数和超参数就很容易让人迷惑。 很多人会把算法用到的一些参数叫成参数,但实际上它们被称为超参数,比如:

  • L1,L2正则
  • 学习率
  • batch size
  • ……

这些控制算法在迭代过程中的表现的,统统被称为超参数。

那为什么不叫参数而叫超参数呢, 因为参数在机器学习中有别的含义。 那就是特征权重,事实上模型服务往往会被称为参数服务。这也算是特征权重的另外一种叫法了。

mini batch 与相关的超参数

mini batch算是最需要我们理解的一个超参数了。 我们已知在梯度下降中需要对所有样本进行处理过后然后走一步,那么如果我们的样本规模的特别大的话效率就会比较低。假如有 500 万,甚至 5000 万个样本 (在我们的业务场景中,一般有几千万行,有些大数据有 10 亿行) 的话走一轮迭代就会非常的耗时。这个时候的梯度下降叫做 full batch。

所以为了提高效率,我们可以把样本分成等量的子集。 例如我们把 100 万样本分成 1000 份, 每份 1000 个样本, 这些子集就称为 mini batch。然后我们分别用一个 for 循环遍历这 1000 个子集。 针对每一个子集做一次梯度下降。 然后更新参数 w 和 b 的值。接着到下一个子集中继续进行梯度下降。

这样在遍历完所有的 mini batch 之后我们相当于在梯度下降中做了 1000 次迭代。 我们将遍历一次所有样本的行为叫做一个 epoch,也就是一个世代,也被人成为训练轮数,这个训练轮数也是常见的超参数之一,可以控制模型训练的次数,要不然算法就永远无法收敛了。 在 mini batch 下的梯度下降中做的事情其实跟 full batch 一样,只不过我们训练的数据不再是所有的样本,而是一个个的子集。 这样在 mini batch 我们在一个 epoch 中就能进行 1000 次的梯度下降,而在 full batch 中只有一次。 这样就大大的提高了我们算法的运行速度。

image-20250717145829544

如上图,左边是 full batch 的梯度下降效果。 可以看到每一次迭代成本函数都呈现下降趋势,这是好的现象,说明我们 w 和 b 的设定一直再减少误差。 这样一直迭代下去我们就可以找到最优解。 右边是 mini batch 的梯度下降效果,可以看到它是上下波动的,成本函数的值有时高有时低,但总体还是呈现下降的趋势。 这个也是正常的,因为我们每一次梯度下降都是在 min batch 上跑的而不是在整个数据集上。 数据的差异可能会导致这样的效果 (可能某段数据效果特别好,某段数据效果不好)。但没关系,因为他整体的是呈下降趋势的。

image-20250717145946028

把上面的图看做是梯度下降空间。 下面的蓝色的部分是 full batch 的而上面是 mini batch。 就像上面说的 mini batch 不是每次迭代损失函数都会减少,所以看上去好像走了很多弯路。 不过整体还是朝着最优解迭代的。 而且由于 mini batch 一个 epoch 就走了 5000 步,而 full batch 一个 epoch 只有一步。所以虽然 mini batch 走了弯路但还是会快很多。

既然有了 mini batch 那就会有一个 batch size 的超参数,也就是块大小。代表着每一个 mini batch 中有多少个样本。 我们一般设置为 2 的 n 次方。 例如 64,128,512,1024. 一般不会超过这个范围。不能太大,因为太大了会无限接近 full batch 的行为,速度会慢。 也不能太小,太小了以后可能算法永远不会收敛。 当然如果我们的数据比较小, 但也用不着 mini batch 了。 full batch 的效果是最好的。

这种支持mini batch的模式也被叫做随机梯度下降,需要注意的是这种模型训练的模式是十分重要的。 这个模式代表着模型是可以实时更新的,只要来一批数据就可以进行一次模型训练并更新模型。 这是后面涉及到的迁移学习和实时训练的基础。那么总结一下我们目前见到过的超参数:

  • batch size:随机梯度下降中,每一批的数据量。

  • 训练轮数:遍历所有样本的次数。

  • 激活函数:控制算法最终的输出形式,或者在神经网络中每一层也可以设置相关的激活函数来更好的拟合数据。

  • 学习率:通常是0~1的值,可以理解为步长,控制在梯度下降中每次走的距离, 或者说是每一次变换w和b的幅度。

  • L1与L2正则:用来防止过拟合的参数,这个我们暂时不涉及, 测试人员比较少会关注这个指标。