机器学习之逻辑回归来龙去脉

线性回归 和逻辑回归

   逻辑回归 也是求解分类问题。

线性回归

前面我们讲了 线性回归 其实就是 求出一条直线 尽量的让所有的数据 离这条直线 距离最小 。 来了新的数据 根据 这条直线去预测。一般是求解 连续的数值。

在这里插入图片描述

逻辑回归

比如根据人的饮食,作息,工作和生存环境等条件预测一个人"有"或者"没有"得恶性肿瘤,可以先通过回归任务来预测人体内肿瘤的大小,取一个平均值作为阈值,假如平均值为y,肿瘤大小超过y为恶心肿瘤,无肿瘤或大小小于y的,为非恶性.这样通过线性回归加设定阈值的办法,就可以完成一个简单的二分类任务.如下图:

在这里插入图片描述

上图中,红色的x轴为肿瘤大小,粉色的线为回归出的函数的图像,绿色的线为阈值.

预测肿瘤大小还是一个回归问题,得到的结果(肿瘤的大小)也是一个连续型变量.通过设定阈值,就成功将回归问题转化为了分类问题.但是,这样做还存在一个问题.

我们上面的假设,依赖于所有的肿瘤大小都不会特别离谱,如果有一个超大的肿瘤在我们的例子中,阈值就很难设定.加入还是取平均大小为阈值,则会出现下图的情况:
在这里插入图片描述

从上边的例子可以看出,使用线性的函数来拟合规律后取阈值的办法是行不通的,行不通的原因在于拟合的函数太直,离群值(也叫异常值)对结果的影响过大,但是我们的整体思路是没有错的,错的是用了太"直"的拟合函数,如果我们用来拟合的函数是非线性的,不这么直,是不是就好一些呢?

上述这个实例中 求这个 因为有个别超大 数据的影响导致 求解的 这个阀值 不太精确 。

怎么求解这个阀值呢 ?

sigmod函数

sigmod 公式:
在这里插入图片描述
sigmod函数的图像如下
在这里插入图片描述
因为这个 sigmod 函数的特性 所以 很容易找到阀值。中间 x=0 的时候 y=0.5 作为 一个二分类 。那么肿瘤实例的线性方程 带入 这个式子中 就可以很明确的区分 求得阀值。

将 sigmod函数 中的 z = WX 带入 。
g(x) = 在这里插入图片描述

那么 只要 g(x) 大于 0.5 就是 癌症 小于 0.5 就是 正常 。 很容易定义这个阀值。 不管 y = wx 取值多大 也不影响取阀值。
将一个连续的 线性回归 转换成 一个二分类问题。

损失函数:

均方差

如果按照线性回归的逻辑 损失函数是这个:

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

那么带入去求解 将非常的困难 。

最大似然估计

转换成概率问题

那么我们不妨来换一个思路解决这个问题。 将上述问题转换成 以下描述:

在这里插入图片描述

p(y=1|x;w)= ϕ(wTx+b)=ϕ(z)
p(y=0|x;w)=1−ϕ(z)

y=1 表示 其中的一个分类 比如 换了癌症。

最大似然估计

最大似然估计的意思就是最大可能性估计,其内容为:如果两件事A,B相互独立,那么A和B同时发生的概率满足公式

P(A , B) = P(A) * P(B)

P(x)表示事件x发生的概率.

如何来理解独立呢?两件事独立是说这两件事不想关,比如我们随机抽取两个人A和B,这两个人有一个共同特性就是在同一个公司,那么抽取这两个人A和B的件事就不独立,如果A和B没有任何关系,那么这两件事就是独立的.

也可以根据 伯努利分布得到 。

p(y|x;w)=ϕ(z)y(1−ϕ(z))(1−y)
其中 y = 1 , 0

用极大似然估计 求参数 W

接下来我们就要用极大似然估计来根据给定的训练集估计出参数w。

在这里插入图片描述

为了简化运算,我们对上面这个等式的两边都取一个对数

在这里插入图片描述

我们现在要求的是使得l(w)最大的w。没错,我们的代价函数出现了,我们在l(w)前面加个负号不就变成就最小了吗?不就变成我们代价函数了吗?

在这里插入图片描述
为了更好地理解这个代价函数,我们不妨拿一个例子的来看看

在这里插入图片描述

在这里插入图片描述
我们来看看这是一个怎么样的函数
在这里插入图片描述

从图中不难看出,如果样本的值是1的话,估计值ϕ(z)越接近1付出的代价就越小,反之越大;同理,如果样本的值是0的话,估计值ϕ(z)越接近0付出的代价就越小,反之越大。

梯度函数

我们最终的目的是求 g(x) = 在这里插入图片描述 那么就是要求 最佳的 W 参数值 。 W 这个值 均一化后 取值 在 (0,1) 之间 y = w0 * x0 + w1x1 …Wnxn 那么我们可以使 W0 —Wn 初始值都设置成1 。 那么慢慢的减少w里面的值 看看是否是符合整个数据模型 。 这个过程 就是 梯度下降 求解法 。 反之 让 W初始值设置为 0 慢慢 增加到 符合的值 就称为 梯度上升 。

怎么样 上升 或者下降呢?

在这里插入图片描述
如上图 比如一个盲人在山顶 怎么能最快的下山呢 , 盲人 会脚或者 拐杖 探路那边 陡峭 就忘哪里走 。那么我们换成 刚刚的问题 。 W 怎么样减少呢?

我们都知道 一阶 求导 得到 速度 二阶求导 得到加速度。

那么 我们想让 W 里面的值 从 1 下降到 合适的值 。就求 这个 W 所在的 函数 g(x) 的 一阶导数得出的速度方向下降就可以了。

所以
w:=w+Δw, Δw=−η∇J(w)

wj:=wj+Δwj, Δwj=−η∂J(w) / ∂wj

η 是人为设置的参数 表示 给下降加一个速度 控制下降步长 。Δw 就是我们要下降多少和下降方向。

那么现在 就可以将 求W 转换成 求 J(w) 的导数问题。

求解W过程

已知:

1, 对数求导知识 :

在这里插入图片描述

2,sigmoid 求导

ϕ′(z)=ϕ(z)(1−ϕ(z))
z(i)=W *x(i)+b
∂z(i) / ∂wj = X(i)

3, 求解 ∂J(w) / wj

在这里插入图片描述
有了上述预备知识 可以得出下面的 推导过程。
在这里插入图片描述

所以,在使用梯度下降法更新权重时,只要根据下式即可

在这里插入图片描述

python 实现

sigmoid函数和初始化数据

def sigmoid(z):
    return 1 / (1 + np.exp(-z))

def init_data():
    data = np.loadtxt('data.csv')
    dataMatIn = data[:, 0:-1]
    classLabels = data[:, -1]
    dataMatIn = np.insert(dataMatIn, 0, 1, axis=1)  #特征数据集,添加1是构造常数项x0
    return dataMatIn, classLabels


//  梯度上升
def grad_descent(dataMatIn, classLabels):
    dataMatrix = np.mat(dataMatIn)  #(m,n)
    labelMat = np.mat(classLabels).transpose()
    m, n = np.shape(dataMatrix)
    weights = np.ones((n, 1))  #初始化回归系数(n, 1)
    alpha = 0.001 #步长
    maxCycle = 500  #最大循环次数

    for i in range(maxCycle):
        h = sigmoid(dataMatrix * weights)  #sigmoid 函数
        weights = weights + alpha * dataMatrix.transpose() * (labelMat - h)  #梯度
    return weights


// 计算结果
if __name__ == '__main__':
    dataMatIn, classLabels = init_data()
    r = grad_descent(dataMatIn, classLabels)
    print(r)
随机梯度

上述公式 可以得出 没一次 求参 W 就需要 所有的数据 都计算一次 当数据量 非常庞大的时候 效率就很低。

每次循环矩阵都会进行m * n次乘法计算,时间复杂度是maxCycles* m * n。当数据量很大时, 时间复杂度是很大。
这里尝试使用随机梯度上升法来进行改进。
随机梯度上升法的思想是,每次只使用一个数据样本点来更新回归系数。这样就大大减小计算开销。

改进算法:

def stoc_grad_ascent(dataMatIn, classLabels):
    m, n = np.shape(dataMatIn)
    alpha = 0.01
    weights = np.ones(n)
    maxCycle = 3  #最大循环次数

    for j in range(maxCycle):
	    for i in range(m):
	        h = sigmoid(sum(dataMatIn[i] * weights))  #数值计算
	        error = classLabels[i] - h
	        weights = weights + alpha * error * dataMatIn[i]
    return weights

// 计算结果
if __name__ == '__main__':
    dataMatIn, classLabels = init_data()

    r = stoc_grad_ascent(dataMatIn, classLabels)
    print(r)

参考文献

https://blog.csdn.net/zjuPeco/article/details/77165974

https://blog.csdn.net/weixin_39445556/article/details/83930186

https://www.jianshu.com/p/4cfb4f734358

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值