1、逻辑回归

线性回归模型:h(x)=w^{T}x+b

w=[0.1,0.2,0.4,0.2]
b=0.5
def linearRegression(x):
    return sum([x[i]*w[i] for i in range(len(x))])+b
linearRegression([2,1,3,1])

通常将h(x)=0设为边界条件用于分类。h(x)>0的样本设为一类,反之设为另一类。

在此线性模型的基础上加上一个函数g,即h(x)=g(w^{T}x+b)g(z)=1/(1+e^{-z})。这个函数就是sidmoid函数,也叫做logistic函数。它可以将一个线性回归中的结果转化为一个概率值。此时h(x)表示的就是某件事发生的概率。

import numpy as np
def sigmoid(x):
    return 1/(1+np.exp(-x))
sigmoid(linearRegression([2,1,3,1]))

下图为sigmoid函数图像:

import matplotlib.pyplot as plt
x = np.arange(-10, 10, 0.01)
y = sigmoid(x)
plt.plot(x, y)
plt.show()

逻辑回归的损失函数:

对于一般的二分类的逻辑回归,交叉熵函数为J(θ)=-[yln(y')+(1-y)ln(1-y')],其中y'是预测值。

训练中所有样本的损失:J(\theta )=-\frac{1}{m}\sum [y_{i}ln(y_{i}')+(1-y_{i})ln(1-y_{i}')]

注:θ代表的是所有的参数集合

为什么逻辑回归要采用交叉熵作为损失函数?这是假设逻辑回归中Y服从于伯努利分布,然后从最大似然估计中推导来的。

逻辑回归的优化方法:梯度下降法

函数梯度的方向就是函数增长最快的方向,反之梯度的反方向就是函数减少最快的方向。因此要计算函数的最小值,就朝着该函数梯度相反的方向前进。

假设需要优化的函数为f(X)=f(x_{1},...,x_{n})

首先初始化自变量,从X(0)=(x_{1}^{(0)},...,x_{n}^{(0)})开始。设置一个学习率η。

对于任何i>=0:如果是最小化f,x_{1}^{i+1}=x_{1}^{i}-\eta \frac{\partial f}{\partial x_{1}}(x^{(i)})     x_{n}^{i+1}=x_{n}^{i}-\eta \frac{\partial f}{\partial x_{n}}(x^{(i)})

如果是最大化f,x_{1}^{i+1}=x_{1}^{i}+\eta \frac{\partial f}{\partial x_{1}}(x^{(i)})      x_{n}^{i+1}=x_{n}^{i}+\eta \frac{\partial f}{\partial x_{n}}(x^{(i)})

注:随机梯度下降——每次计算一个样本的损失,然后更新参数θ;下降速度快,但收敛性差,容易陷入局部最优。批次梯度下降——每次根据一批次的样本来更新参数;梯度下降——全部样本,速度慢,但更能达到全局最优。

对于逻辑回归优化的目标函数J(w,b)=-\frac{1}{m}\sum [y_{i}ln(\sigma (w^{T}x+b))+(1-y_{i})ln(1-\sigma (w^{T}x+b))]

需要优化参数w,b,从而使其在已知的样本X,y上值最小。

首先要对J(w,b)求导。令g=\sigma (w^{T}x+b)

\frac{\partial J(g)}{\partial g}=-\frac{\partial}{\partial g}[yln(g)+(1-y)ln(1-g)]=-\frac{y}{g}+\frac{1-y}{1-g}

再令a=w^{T}x+b ,即g=σ(a)        

\tiny \frac{\partial g}{\partial a}=\frac{\partial (\frac{1}{1+e^{-a}})}{\partial a}=-(1+e^{-a})^{-2}-e^{-a}=\frac{1}{1+e^{-a}}\frac{1+e^{-a}-1}{1+e^{-a}}=\sigma (a)(1-\sigma (a))=g(1\boldsymbol{}-g)

根据上述推导和链式法则,\frac{\partial J}{\partial w}=\frac{\partial J}{\partial g}\frac{\partial g}{\partial a}\frac{\partial a}{\partial w}=(-\frac{y}{g}+\frac{1-y}{1-g})g(1-g)x=(g-y)x

                                            \frac{\partial J}{\partial b}=\frac{\partial J}{\partial g}\frac{\partial g}{\partial a}\frac{\partial a}{\partial b}=(-\frac{y}{g}+\frac{1-y}{1-g})g(1-g)=(g-y) 

根据以上公式,写一个根据随机梯度下降进行优化的函数。

import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
X=datasets.load_iris()['data']
Y=datasets.load_iris()['target']
Y[Y>1]=1
X_train,X_test,y_train,y_test=train_test_split(X,Y,test_size=0.4,stratify=Y)

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

def cal_grad(y, t):
    grad = np.sum(t - y) / t.shape[0]
    return grad

def cal_cross_loss(y, t):
    loss=np.sum(-y * np.log(t)- (1 - y) * np.log(1 - t))/t.shape[0]
    return loss

class LR:
    def __init__(self, in_num, lr, iters, train_x, train_y, test_x, test_y):
        self.w = np.random.rand(in_num)
        self.b = np.random.rand(1)
        self.lr = lr
        self.iters = iters
        self.x = train_x
        self.y = train_y
        self.test_x=test_x
        self.test_y=test_y


    def forward(self, x):
        self.a = np.dot(x, self.w) + self.b
        self.g = sigmoid(self.a)
        return self.g

    def backward(self, x, grad):
        w = grad * x
        b = grad
        self.w = self.w - self.lr * w
        self.b = self.b - self.lr * b

    def valid_loss(self):
        pred = sigmoid(np.dot(self.test_x, self.w) + self.b)
        return cal_cross_loss(self.test_y, pred)

    def train_loss(self):
        pred = sigmoid(np.dot(self.x, self.w) + self.b)
        return cal_cross_loss(self.y, pred)

    def train(self):
        for iter in range(self.iters):
            ##这里采用随机梯度下降的方法

            for i in range(self.x.shape[0]):
                t = self.forward(self.x[i])
                grad = cal_grad(self.y[i], t)
                self.backward(self.x[i], grad)

            train_loss = self.train_loss()
            valid_loss = self.valid_loss()
            if iter%5==0:
                print("当前迭代次数为:", iter, "训练loss:", train_loss, "验证loss:", valid_loss)
model=LR(4,0.01,100,X_train,y_train,X_test,y_test)
model.train()

 通常直接调用sklearn包:

import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
X=datasets.load_iris()['data']
Y=datasets.load_iris()['target']
from sklearn.linear_model import LogisticRegression
X_train,X_test,y_train,y_test=train_test_split(X,Y,test_size=0.1,stratify=Y)

model=LogisticRegression(penalty='l2',class_weight=None,random_state=None,max_iter=100)
model.fit(X_train,y_train)
model.predict_proba(X_test)

penalty:惩罚系数,也就是正则化,默认为L2。

L1:J(\theta)=-\frac{1}{m}\sum [y_{i}ln(y_{i}')+(1-y_{i})ln(1-y_{i}')]+|\omega|  加上参数w绝对值的和。

L2:J(\theta)=-\frac{1}{m}\sum [y_{i}ln(y_{i}')+(1-y_{i})ln(1-y_{i}')]+||\omega^{2}||  加上参数w平方和。

当我们假设参数ω服从正态分布的时候,根据贝叶斯模型可以推导出L2正则化,当我们假设参数ω服从拉普拉斯分布发时候,根据贝叶斯模型可以推导出L1正则化。

class_weight:类别权重,一般在分类不均衡的时候使用。

max_iter:最大迭代次数。

特征离散化:一般我们不会将连续的值作为特征输入到逻辑回归的模型之中,而是将其离散成0,1变量。这样的好处有:

1、稀疏变量的内积乘法速度快,计算结果方便存储,并且容易扩展;

2、离散化后的特征对异常数据有很强的鲁棒性:比如一个特征是年龄>30是1,否则0。如果特征没有离散化,一个异常数据“年龄300岁”会给模型造成很大的干扰。

3、逻辑回归属于广义线性模型,表达能力受限;单变量离散化为N个后,每个变量有单独的权重,相当于为模型引入了非线性,能够提升模型表达能力,加大拟合;

4、离散化后可以进行特征交叉,由M+N个变量变为M*N个变量,进一步引入非线性,提升表达能力;

5、特征离散化后,模型会更稳定,比如如果对用户年龄离散化,20-30作为一个区间,不会因为一个用户年龄长了一岁就变成一个完全不同的人。当然处于区间相邻处的样本会刚好相反,所以怎么划分区间是门学问。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值