欢迎光临散文网 会员登陆 & 注册

[Quant 1.1] 尝试只用Numpy实现逻辑回归

2022-05-12 15:49 作者:安平生一人好_  | 我要投稿

之前关注了一个up主,看了两个视频之后感觉他讲的非常好。因为当时还没放假,所以就没有仔细看,就想着放假之后一定好好修炼修炼技术。祝自己能坚持下去,同时非常感谢大神的视频。

从我的水平看,up调取了pytorch的包,把numpy array转化成张量然后带入到自己写的逻辑回归函数中循环。因为我感觉短期可能没法把pytorch学的那么扎实,所以就想只用numpy试试能不能把逻辑回归写出来(我也不想做调包侠)。然后这个仅作为我看完原up视频之后的一点小练习和记录,所以我不会说的非常的细致。如果读到这篇的朋友需要我在哪个地方详细说明的话我会更新这篇。我会尽快附上代码链接。感兴趣的朋友可以私我一些意见/把我拉进金工金数量化或者CFA2级备考的群,菜鸟不胜感激!


1. 模型

在开始讲代码之前,我们先整理一下逻辑,也相当于复习一下逻辑回归的框架了。

逻辑回归模型是基于sigmoid激活函数的,也就是

f(z)%20%3D%20%5Cfrac%7B1%7D%7B1%2Be%5E%7B-z%7D%7D

模型是

%5Cbegin%7Balign%7D%0AP(y%3D1%7Cx)%20%3D%20%5Cfrac%7B1%7D%7B1%2Be%5E%7B-(wx%2Bb)%7D%7D%0A%5Cend%7Balign%7D

左边的条件概率相当于一个关于x的函数。x是一个样本的attributes向量,例如对你来说,你有一个x向量,x_1%0A是你的身高,x_2是你的体重...。同样,对你来说,你还有一个性别y(不好意思我这里暂时不考虑trans),y=1说明你是女性,y=0说明你是男性。w是针对所有的人来说每一个attribute对判断你性别的影响,例如w1就是一个人的身高在判断这个人是男是女的时候的重要性。

%5Cbegin%7Balign%7D%0A%5Cvec%7Bw%7D%20%26%3D%20(w_1%20%5C%2Cw_2%20%5C%2Cw_3%20...%20w_n)%20%5C%5C%0A%5Cvec%7Bx%7D%20%26%20%3D%20(x_1%20%5C%2C%20x_2%20%5C%2C%20x_3%20...%20x_n)%5ET%5C%5C%0A%5Cend%7Balign%7D


在线性回归里面,我们用的损失函数是MSE。而在逻辑回归里面我们要用的损失函数是cross entropy。

%5Cbegin%7Balign%7D%0Ag(y%2C%5Chat%7By%7D)%20%26%3D%20-y%20%5Ccdot%20log(%5Chat%7By%7D)%20-%20(1-y)%20%5Ccdot%20log(1-%5Chat%7By%7D)%0A%5Cend%7Balign%7D%0A

y是你真实的性别,%5Chat%7By%7D是之前预测的你的性别

这是因为在逻辑回归模型下,损失函数MSE非凸,所以不能使用梯度下降法来求最小的loss。如果你在逻辑回归中用了MSE,那么你要最小化的损失函数很可能长这个样子。

Plot by Wolfram

但是如果你使用了cross entropy,损失函数基本就长这样子。


Plot by Wolfram

多说一句,即使cross entropy损失函数是凸的,我们也没办法用first order condition来求解他的全局最小值,因为他没有。我是愚蠢的用手推了很久才发现的。


所以之后要做的事情就是:我们先猜想一组 %5Cvec%7Bw%7D 和 b,然后我们把attributes向量一个一个的代入到这个逻辑回归模型里面。我们就会获得1个预测值,然后用1个预测值和1个真实值来计算出1个对应的loss。然后计算这个loss对各个attribute的偏导数,就可以更新我们的%5Cvec%7Bw%7Db了。

%5Cbegin%7Balign%7D%0A%5Cvec%7Bw%7D_1%20%26%3D%20%5Cvec%7Bw%7D_0%20-%20%5Calpha%20%5Cnabla%20g%7C_%7B%5Cvec%7Bw%7D_0%7D%5C%5C%0Ab_1%20%26%3D%20b_0%20-%20%5Calpha%20%5Cfrac%7B%5Cpartial%20g%7D%7B%5Cpartial%20b%7D%7C_%7Bb_0%7D%0A%5Cend%7Balign%7D%0A

这里因为在计算 %5Chat%7By%7D 的时候要用到 %5Cvec%7Bw%7D 和 b ,所以g也是关于 %5Cvec%7Bw%7D 和 b 的函数。

%5Chat%7By%7D%20%3D%20%5Cfrac%7B1%7D%7B1%2Be%5E%7B-(%5Cvec%7Bx%7D_0%5Cvec%7Bw%7D_0%2Bb_0)%7D%7D

而实际上,我们可以选择多个attributes向量一起代入,得到多个loss的平均值,然后求这个平均loss的对 X%20 和 b 的偏导数,在用上面同样的式子来更新参数。在这种情况下,向量乘法会变成矩阵乘法,大神在视频2中有详细讲解。


2. 代码

除了numpy之外,sklearn主要是导入和up同样的数据库来检验我自己建立的逻辑回归模型的表现。matplotlib拿来画图。

然后是定义sigmoid函数和cross entropy函数,数学表达式就是上面写到的激活函数和损失函数。

下一个函数是计算损失,大致就是先用X (把前面提到的 %5Cvec%7Bx%7D 纵向堆叠到一起), %5Cvec%7Bw%7D 和 b 来求出 %5Chat%7By%7D ,再对应实际的 y 计算出的多个样本对应损失的平均值。样本个数就是矩阵X 的行数。

下面是用来求梯度的函数,因为numpy本身的diff函数是计算离散数列邻项的差的,因此不能用来求偏导。因此我来定义一个函数,用来求解loss函数在%5Cvec%7Bw%7D 各个方向的梯度。

提取数据,划分训练集和测试集(和原up的代码相同),把 %5Cvec%7Bw%7D 和 b 都初始化为0向量。

下面是主函数。

我的代码用了5000次迭代,最后的loss是0.20495,下面是最后得到的 %5Cvec%7Bw%7D 和 b 的结果。

这个和原up的回归结果有一些出入,但是还好。。

loss随迭代次数的变化

最后计算一下预测的准确率

计算出来是92.647%

[Quant 1.1] 尝试只用Numpy实现逻辑回归的评论 (共 条)

分享到微博请遵守国家法律