逻辑回归与神经网络-逻辑回归详解

相信在上面小节中,对于什么是逻辑回归一定非常好奇,这一节就来详解一下逻辑回归。

逻辑回归是应用最为广泛的二分类模型,并且也是进一步学习神经网络等深度学习模型的基础。

本节我们从下面三个角度来详解逻辑回归:

1、什么是线性分类
2、逻辑回归的算法原理
3、PyTorch实现逻辑回归

什么是线性分类

来看下面这个例子:

在这里插入图片描述

在平面 x1-0-x2 中,分布着蓝色圆圈表示的正样本,红色叉叉表示的负样本,它们有两个特征 x1 和 x2 .

其中正样本的标签是 y = 1,负样本的标签是 y = 0,然后在平面上画出一条直线:x1 + x2 - 3 = 0

该直线交 x1 轴于点(3, 0) ,交 x2 轴于点(0, 3):

在这里插入图片描述

此时可以观察到正负两种样本刚好分布在直线的两侧。

对于任意的某个样本(x1, x2) ,如果将该样本向量带入表达式 x1 + x2 - 3,当计算结果大于等于 0 时那么该样本就是正例,否则就是负例:

在这里插入图片描述

这样我们就通过直线 x1 + x2 - 3 = 0,对样本进行了分类,这条直线就是这个分类问题的决策边界。

当使用一条直线来区分样本是正例还是负例,那么这就是线性分类问题。

而逻辑回归算法会训练出一个由直线表示的决策边界,因此逻辑回归是线性分类器。

逻辑回归的算法原理

逻辑回归的假设函数

任何机器学习模型都需要一个假设函数,我们通过假设函数来表示输入数据与输出结果之间的关系。

也就是将样本的特征向量 x ,输入到假设函数中 Hθ(x) 中,计算出模型的预测结果:

在这里插入图片描述

逻辑回归的假设函数如下所示:

在这里插入图片描述

下面我们就基于分类问题本身,来解释逻辑回归的假设函数 Hθ(x) 。

设平面上的样本正例的标记为 y=1,负例的标记 y=0,那么逻辑回归模型需要预测样本的标记值:预测未知的样本 x 是0还是1。

也就是将未知样本 x 输入到逻辑回归模型,然后模型预测该样本是0还是1。

实际上,我们希望模型的预测结果也就是 Hθ(x) 的输出是 0 到 1 中间的某个值,这样就可以将预测结果 h 看作是样本 x 属于某个类别的概率了。也就是当我们发现预测 h 接近 1 时,样本 x 就更可能是正例,h接近0时,样本 x 更可能是负例。

在这里插入图片描述

具体来说,在使用逻辑回归预测样本的类别时,会提前设置一个阈值 p 用来控制分类的界限:

在这里插入图片描述

比如阈值 p 设置为 0.5 的话,假设预测值Hθ(x) = 0.75,那么 0.75 >= 0.5 ,因此 x 为正例。

因此基于这样的考虑,为了使得 Hθ(x) 的输出是 0 到 1 区间中的某个值,我们引入 sigmoid 函数,设 sigmoid 函数为 g(z),那么其为下图右侧的公式:

在这里插入图片描述

观察 sigmoid 函数会发现,自变量 z 的范围是负无穷到正无穷,z 趋近于负无穷时函数值接近于0,z 趋近于正无穷时,函数值趋近于 1:

在这里插入图片描述

并且该函数在 z=0 的位置左右对称。

任意直线的表达式为:

在这里插入图片描述

我们将该表达式用 z 表示,并带入到 sigmoid 函数中:

在这里插入图片描述

此时就得到了自变量是 x1 到 xn,参数是 θ0 到 θn,值域是 0 到 1 的函数 Hθ(x) 。

该函数就是逻辑回归的假设函数,它由直线 z 和 sigmoid 函数两部分组成。

逻辑回归的代价函数

机器学习模型的代价函数衡量了模型在训练集上所犯的错误大小,因此需要准确的描述样本预测值与真实值之间的误差。

在逻辑回归中,使用交叉熵损失函数作为模型的代价函数:

在这里插入图片描述

我们要求出代价函数 J 取得最小值时,逻辑回归模型中的参数 θ0 到 θn 它们的具体值是多少。

下面我们具体来说明为什么逻辑回归的代价函数是交叉熵损失误差:

设下面的公式是某一个样本的代价:

在这里插入图片描述

J(θ) 为 m 个样本的平均代价:

在这里插入图片描述

在 cost 函数中,Hθ(x)表示样本属于某一个类别的预测概率,y表示样本的标签,cost函数描述了模型对于一个样本所犯错误的大小:

在这里插入图片描述

我们希望一个样本的代价 cost,有如下性质:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

为了实现拥有这样性质的 cost 函数,我们引入 log 函数,我们将 -log(x) 和 -log(1-x) 两个函数画在坐标系中,这两个函数以 x = 0.5 左右对称,接着将自变量 x 的值限制在 0 到 1 之间:

在这里插入图片描述

观察函数图像可以发现,蓝色函数在 x 趋近于 0 时函数值趋近于正无穷,x=1时蓝色函数值为 0.

橙色函数则正好相反。

因此如果函数的自变量 x 就对应模型的预测值 h,那么蓝色函数就恰好可以代表样本为正例时代价 cost 随预测值 h 的变化。

橙色函数则可以表示样本为负例时,代价 cost 随预测值 h 的变化:

在这里插入图片描述

基于这样的考虑,就可以设计出如下的 cost 函数:

在这里插入图片描述

将上图中的两个函数合成一个,也就是用 Hθ(x)、y 和 log 函数同时表达一个样本的代价值 cost:

在这里插入图片描述

最后将 m 个样本的代价值相加到一起除以 m,就得到了逻辑回归的总代价函数 J(θ):

在这里插入图片描述

J(θ) 即为我们的交叉熵损失误差。

PyTorch实现逻辑回归

接下来我们使用深度学习框架来训练逻辑回归模型。

首先我们要清楚我们要构建的场景类似如下,也就是我们刚刚一直在说的例子:

在这里插入图片描述

因此我们可以写出如下代码:

from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
import numpy
import torch


# 实现逻辑回归的假设函数hθ(x) 的计算方法
# 计算逻辑回归模型的预测值hθ(x)
def hypothesis(theta0, theta1, theta2, x1, x2):
    z = theta0 + theta1 * x1 + theta2 * x2
    h = torch.sigmoid(z)
    return h.view(-1, 1)


# 实现逻辑回归的代价函数J(θ)的计算方法
# 计算预测值h与真实值y的交叉熵损失函数
def J(h, y):
    return -torch.mean(y * torch.log(h) + (1 - y) * torch.log(1 - h))


if __name__ == '__main__':
    # 使用mak_blobs函数,在平面上随机生成50个随机样本,包含两个类别
    x, y = make_blobs(n_samples=50, centers=2, random_state=0, cluster_std=0.5)
    # x1, x2分别保存样本的两个特征
    x1 = x[:, 0]
    x2 = x[:, 1]
    # 使用plt.scatter绘制正样本和负样本
    # 其中正样本使用蓝色圆圈表示,负样本使用红色叉叉表示
    plt.scatter(x1[y == 1], x2[y == 1], color='blue', marker='o')
    plt.scatter(x1[y == 0], x2[y == 0], color='red', marker='x')

    # 将两个特征x1、x2和标签y,转为张量形式
    x1 = torch.tensor(x1, dtype=torch.float32)
    x2 = torch.tensor(x2, dtype=torch.float32)
    y = torch.tensor(y, dtype=torch.float32).view(-1, 1)
    # 定义直线的3个参数,θ0、θ1、θ2
    θ0 = torch.tensor(0.0, requires_grad=True)
    θ1 = torch.tensor(0.0, requires_grad=True)
    θ2 = torch.tensor(0.0, requires_grad=True)
    # 定义Adam优化器optimizer,优化三个θ参数
    optimizer = torch.optim.Adam([θ0, θ1, θ2])

    for epoch in range(10000):  # 进入逻辑回归模型的训练迭代
        # 计算模型的预测值
        h = hypothesis(θ0, θ1, θ2, x1, x2)
        # 调用函数J,计算预测值h与真实值y之间的损失loss
        loss = J(h, y)
        loss.backward()  # 计算loss关于参数θ的梯度
        optimizer.step()  # 更新模型参数
        optimizer.zero_grad()  # 将梯度清零

        if epoch % 1000 == 0:
            # 每一千次迭代打印一次当前的损失,loss.item()是损失的标量值
            print(f'After {epoch} iterations, the loss is {loss.item():.3f}')

    # 完成训练后,再基于迭代出的参数,绘制出逻辑回归的蓝色决策边界
    w1 = θ1.item()
    w2 = θ2.item()
    b = θ0.item()
    x = numpy.linspace(-1, 6, 100)
    d = -(w1 * x + b) * 1.0 / w2
    plt.plot(x, d)
    plt.show()

代码运行输出如下:

在这里插入图片描述

在这里插入图片描述

可以看到分类效果是不错的。

相信经过上面这一连串的流程讲解,逻辑回归与神经网络应该已经很容易明白了。

上一篇:【大数据学习 | kafka】kafuka的基础架构


下一篇:IDEA解决 properties 文件乱码问题