欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

LogisticRegression

程序员文章站 2022-07-06 11:08:10
...

在给定X的条件下,其被分到 1 类 的概率为:
P(Y=1x,Q)=Sigmoid(a+xQ)(a为偏置,和线性方程a+bx是一个道理)
其中Sigmoid(QX)的计算方式是:

P(Y=1x,Q)=e(a+xQ)1+e(a+xQ)

这样计算有些复杂,化简后为:

P(Y=1x,Q)=11+e(xQ)

Q为权值向量,x为输入样本,比如有5个特征,则Q向量为

[x1 x2 x3 x4 x5]

xQ 后所生成的向量代入Sigmoid() 后就可以得出类别
这是一个概率值,因为Q值是固定的。我们直接输入x矩阵值就好了,算法会告诉我们 Y 值能取到多少,也就是概率值为多少 ,然后大于y>0.5为1类,y<0.5为0类;

def sigmoid(self,x):
    return 1.0/(1+np.exp(-x))

相应的其被分到 0 类的概率为:
P(Y=0x,Q)=1P(Y=1x,Q)

但Q值怎么算和为什么这个算法可以这么算?我的理解是这样的,多元回归函数可以表示为:

Y1=a+bx1+cx2+dx3....+mxn

其实他就是一个概率的问题,可以这么理解:回归预测后得出的值是控制了自变量后得出的概率 ;也就是说预测值Y越高,自变量可能更具有某种特性,从而影响了Y值;线性回归假设了概率与X值呈现出一条直线。(就像你每增长一岁,你被催婚的概率会增大)
但 这个多元函数所带来的一个麻烦就是:概率最大值为1,最小值为0;如果单纯看这个函数的话,Y值总有一刻会>1或<0,这和我们的思维很不和谐,解决这样的问题的一个最好的办法就是:任何>1的值都用1替代,任何<0的值都用0替代;这样就会出现任何>1的值和<0的值都将呈现出一条直线:
LogisticRegression
这样的做法的确解决了概率大小超出范围的问题,但是它显得太绝对了一点,它把一切>1和<0的值都瞬间变为一条直线,也就是表达了当自变量达到一定值得时候对因变量就没有影响了,这样显然太绝对了,举一个例子:
“Y就像你买一套房子的期望,x1是你的工资,x2是你所在的城市,x3是房子的地段
假如你的工资上涨,或房子地段相对不好,那么你买房子的概率就会上升,反之亦然;当你工资 多到一定程度 的时候,工资即使再涨,对你买房子的概率也不会有很大很大的影响,因为你已经有很多钱了,再往上加工资没有太大意义,但没人会和钱过不去,钱当然是越多越好,你可以买更好的房子或你可以更快买到房子;同样的,当你工资少的可怜的时候,即时再给他降低工资也不会对他产生很大很大的影响,因为他不可能买到房。
而对于中间一部分人来说,加/减 工资 或地段等其他因素带来的影响会很大,但加了工资换了地段你就会买房子么?不一定,因为你还没满足条件,只是说你买房子的概率会上升“
避免这样太过绝对的方法就是当自变量大到一定程度的时候,对因变量的影响相对于中间部分的影响变得很小,刚好有这样的曲线可以很好的达到我们想要的效果:
S形曲线:无限趋于上下限,也就是Logit模型,也就是sigmoid:
LogisticRegression
但回归不是一条直线么?怎么会变成曲线?可以看下这幅图:
LogisticRegression
把切线上的斜率取均值,得到一条趋势线,用直线模拟曲线。
但我们很容易发现对于这种线性关系,因变量和自变量的关系在极限段是被高估了的,而在中间段是被低估了的,因变量对自变量的影响是不对的,要么过大,要么过小;我们想要以S形状曲线预测,但是从回归可以看出每一个自变量本身都会对因变量产生影响,但当某个自变量大到足以让Y很接近1的时候,其他自变量就没法工作了,他们就不可以相互作用了,也违背了回归的原则,这样的话直接拿一个因变量检测好了,干嘛还要那么多自变量?解决这个矛盾的方法就是排除上下限,也就是需要把Logit函数做一些转化;

排除上限

设 x 被 分为 1 类 的概率是:Pi ,则被分为0 的概率就是:1Pi
然后取他们的比作为Y值的概率:Pi1Pi
因为与概率不同的是比没有上限,但下限为0;
当概率值Pi 无限趋于1的时候,其比也就是:Logit=Pi1Pi 被无限放大,上限也就不存在了;
而且比数还有一个作用就是:倍数关系,分子是分母的多少倍,也就是说取到1的概率是取到0的几倍;

排除下限

为了排除下限,我们就需要当自变量Pi1Pi趋于0时,Logit函数趋于负无穷;
刚好:取对数可以做到这一点,有能保证自变量>0:
也就是:Logit=ln(Pi1Pi)
到这里为止 上下限被排除,转化也就结束了
然后把S形曲线线性化:

Logit=ln(Pi1Pi)=a+xiQ

为了更加表达清楚他们是概率的关系:两边取指数

eln(Pi1Pi)=ea+xiQ

化简后就是:

Pi1Pi=ea+xiQ

Pi=ea+xiQ

PiexiQ

1=ea+xiQPiea+xiQ

Pi=ea+xiQ1+ea+xiQ

按理来说,Y被取到1 的概率应该就是这样的,接下来该是做的就是看如何把Q值算出来,对于模型的参数(Q)估计,这里使用极大似然函数
我们用Li(Q)表示:

Li(Q)=ni=1{P(y=1xi)yiP(Y=0xi)1yi}

Li(Q)=ni=1{(ea+xiQ1+ea+xiQ)yi(11+ea+xiQ)1yi}

取对数后化成加法:

Li(Q)={ni=1yiln(ea+xiQa+ea+xiQ)+ni=1(1yi)ln(11+ea+xiQ)}

Li(Q)=ni=1yiln(ea+xiQ1+ea+xiQ)+ni=1ln(11+ea+xiQ)ni=1yiln(11+ea+xiQ)

Li(Q)=ni=1yiln(ea+xiQ1+ea+xiQ11+ea+xiQ)ni=1ln(11+ea+xiQ)

Li(Q)=yi(a+xiQ)ni=1ln(1+ea+xiQ)

整个模型的代价函数化到这里就没办法再化下去了:
根据多元函数求极值法:对代价函数求偏导后得:

Li(Q)Q=NI=1yixini=111+ea+xiQea+xiQxi

然后令其为0:一看就解不出Q,这样的话要求解只能用梯度上升/下降求最优解了:这里希望Y值尽可能取到1的概率增加,所以用梯度上升(不知道说的对不对,没有对的话还请指教,感激!)
先初始化一个权值矩阵Q,在进行迭代:

Qt+1=Qt+αni=1xi(yiea+xiQt1+ea+xiQt)

这里我们也看到了Sigmoid函数,经过反复迭代后得到一个局部最优解,可是如何防止跳过局部最优解还得慢慢试,不知道有没有其他的模型能帮忙解决这个问题。
迭代完后保存权值矩阵,a值可以设为1;
之后把权值矩阵做一个处理就可以看到效果,或者直接把预测结果写入文件在来一次K折交叉看看模型的准确率。

最后附代码片段

class LogisticRegressionClassifier(object):
    def __init__(self,alpha,n_iter):
        self.alpha = alpha
        self.iter = n_iter

    def sigmoid(self,x):
        return 1.0/(1+np.exp(-x))

    def train(self,X,y):
        samples,features = np.shape(X)
        weights = np.ones((features,1))
        error = np.ones((features,1))
        for times in range(self.iter):
            output = self.sigmoid(X*weights)
            error = y-output
            weights = weights+self.alpha*X.transpose()*error
            return weights

    def predict(self,X,weights):
        results = self.sigmoid(X*weights)
        return results
相关标签: 机器学习算法