在使用numpy实现线性回归与逻辑回归的总结

逻辑回归相对与线性回归主要的区别有3点:

一、loss函数

线性回归的loss函数一般为:
loss=(ytrueypred)2.............(1)loss=(y^{true}-y^{pred})^2.............(1)
逻辑回归的loos函数一般为:
loss=f(x1)(1f(x2))f(x3)....f(xn).............(2)loss=f(x_1)(1-f(x_2))f(x_3)....f(x_n).............(2)
假定(2)式中ff函数为逻辑回归计算出的是种类一的概率
对于(1)loss值越小越好,但是对于(2)loss值是越大越好,但是对于我们通常的理解loss一般都是都是越小越好的,因此我们对(2)取对数并且取负数得到(3)如下,那么这个loss就是越小越好了。
loss=ln(f(x1)(1f(x2))f(x3)....f(xn))..........(3)loss=-ln(f(x_1)(1-f(x_2))f(x_3)....f(x_n))..........(3)

为什么在逻辑回归中不用(1)呢?

首先逻辑回归的函数如下:
f=sigmod(wx+b)f=sigmod(wx+b)

z=wx+bz=wx+b
ww的梯度函数
2(ytruef(xn))fzzw2(y^{true}-f(x_n))\frac{\partial f}{\partial z}\frac{\partial z}{\partial w}
化简后最简式如下
2(ytruef(xn))f(xn)(1f(xn))x...........(4)2(y^{true}-f(x_n))f(x_n)(1-f(x_n))x...........(4)
设定ytrue=1y^{true}=1,在ypred=1f(xn)=1y^{pred}=1 即f(x_n)=1的情况下:
lossw=0\frac{\partial loss}{\partial w}=0
这是合理的,但是在ypred=0f(xn)=0y^{pred}=0 即f(x_n)=0的情况下:
lossw=0\frac{\partial loss}{\partial w}=0
这就不对了,ypred=0y^{pred}=0完全没有预测对,但是他的梯度仍然为0,因此逻辑回归不能使用平方差作为loss函数

二、sigmod函数

其实我们可以将逻辑回归简单理解为对线性回归的结果在结果一次sigmod函数处理。sigmod函数的作用可以简单理解为将线性回归的结果映射到(0,1)的范围内。

三、输出不同

对于普通的线性回归结果一般是(,+)(-\infty,+\infty),对于逻辑回归的结果由于sigmod函数与最后四舍五入操作最后都是{0,1}。

numpy编写逻辑回归时的code理解

计算loss值

def cross_entropy_loss(y_pred,Y_label):
    return -np.dot(Y_label,np.log(y_pred))-np.dot((1-Y_label),np.log(1-y_pred))

我们对(3)再进行进一步的化简
loss=ln(f(x1)(1f(x2))f(x3)....f(xn))..........(3)loss=-ln(f(x_1)(1-f(x_2))f(x_3)....f(x_n))..........(3)
利用对数函数运算法则
loss=[lnf(x1)+ln(1f(x2))+lnf(x3)+...+lnf(xn)]loss=\sum{-\left[ lnf(x_1)+ln(1-f(x_2))+lnf(x_3)+...+lnf(x_n) \right]}
loss=n[y^lnf(xn)+(1y^)ln(1f(xn))]...........(5)loss=\sum_{n}{-\left[ \hat{y}lnf(x^{n})+(1-\hat{y})ln(1-f(x^{n})) \right]}...........(5)
在(5)中y^\hat{y}:1对应种类1,0对应种类2。公式(5)对应上述的代码。

计算ypredy^{pred}

def predict(x,w,b):
    return np.round(f(x,w,b)).astype(np.int)

在上述代码的ff函数中,已经计算了sigmod函数,这一段代码就是要将sigmod函数的输出值进行四舍五入整数化。

计算ww,bb的梯度

def gradient(x,Y_label,w,b):
    y_pred=f(x,w,b)
    pred_error=Y_label - y_pred
    pred_error=np.array([pred_error.tolist()])
    w_grad=-np.sum(pred_error*x.T,axis=1)
    b_grad=-np.sum(pred_error)
    return w_grad,b_grad

假定xx的shape为(8,577),其中8为batch_size,577为feature_size,那么y_labely\_label的shape为(8,1)与xx的batch_size相对应,ww的shape为(577,1)与xx的feature_size相对应。
上述代码中的pred_error shape为(8,1),将pred_error与xx的转置矩阵对位相乘得到的结果shape为(577,8)然后按照横轴方向相加,得到的结果shape为(577,1),这个结果就是梯度,然后将梯度更新到ww上,完成梯度下降。