逻辑回归

作者: 抹茶不加茶 | 来源:发表于2020-03-08 22:35 被阅读0次

原理

逻辑回归用于解决分类问题,但是你可能会疑惑,为何名字偏偏称为回归,嘿嘿嘿,这时因为我们在逻辑回归中将连续取值结果的函数,一分为二,连续值便变成了0、1这样的离散值,这样便成了分类,这样说实在过于抽象,下面来具体看一下

  • 我们先将样本的特征和样本的概率联系起来,而且我们定义: 通过概率进行分类
  • 我们首先计算出p这个概率值,这是一个连续值,如果我们就此打住,这便可以称为一个回归算法,如果我们按照上面的的定义,将不同概率分为两类,这样就成了分类算法
  • 我们来看看计算过程,这里注意一下sigma函数


    过程
  • 对于sigma函数,我们通常选择:


    sigma函数
  • 总结一下 1

    那么问题就变成了,对于给定的xy,寻找theta参数,使得这种方式下能获得最好的分类效果。

  • 这时候我们要考虑损失函数,这里不加推导给出:


    损失函数
    对于所有样本,我们得到损失函数

    其中,有:


    p_hat值
    所以我们得到损失函数完整表达式:
    损失函数完整表达式
  • 对于此损失函数,不像线性回归中那样,具有公式解,我们目前只能采用梯度下降法进行求解
  • 我们在这里特别看看其与线性回归的差别(在求梯度的时候)


    梯度比较

    我们注意到,其实最大的差别就是y_hat的值,是否使用了sigma函数而已
    我们进行矩阵形式化简


    矩阵形式

简单实现

对于逻辑回归,其重要性是不用多说的,吴恩达的课程里面占了较大的篇幅。
所以这里的实现写的比较全面,希望读者自己也可以试一试,相信你将获益匪浅!

import numpy as np
from metrics import accuracy_score
#这里采用类进行封装的形式
class LogisticRegression:

    def __init__(self):
        """初始化Logistic Regression模型"""
        self.coef_ = None
        self.intercept_ = None
        self._theta = None
    def _sigmoid(self,t):
        return 1/(1+np.exp(-t))



    def fit(self, X_train, y_train, eta=0.01, n_iters=1e4):
        """根据训练数据集X_train, y_train, 使用梯度下降法训练Logistic Regression模型"""
        assert X_train.shape[0] == y_train.shape[0], \
            "the size of X_train must be equal to the size of y_train"

        def J(theta, X_b, y):
            y_hat=self._sigmoid(X_b.dot(theta))
            try:
                return - np.sum(y*np.log(y_hat)+(1-y)*np.log(1-y_hat)) / len(y)
            except:
                return float('inf')

        def dJ(theta, X_b, y):
            
            return X_b.T.dot(self._sigmoid(X_b.dot(theta)) - y)  / len(X_b)

        def gradient_descent(X_b, y, initial_theta, eta, n_iters=1e4, epsilon=1e-8):

            theta = initial_theta
            cur_iter = 0

            while cur_iter < n_iters:
                gradient = dJ(theta, X_b, y)
                last_theta = theta
                theta = theta - eta * gradient
                if (abs(J(theta, X_b, y) - J(last_theta, X_b, y)) < epsilon):
                    break

                cur_iter += 1

            return theta
        X_b = np.hstack([np.ones((len(X_train), 1)), X_train])
        initial_theta = np.zeros(X_b.shape[1])
        self._theta = gradient_descent(X_b, y_train, initial_theta, eta, n_iters)

        self.intercept_ = self._theta[0]
        self.coef_ = self._theta[1:]

        return self
       
    def predict_proba(self, X_predict):
        """给定待预测数据集X_predict_proba,返回表示X_predict的结果概率"""
        assert self.intercept_ is not None and self.coef_ is not None, \
            "must fit before predict!"
        assert X_predict.shape[1] == len(self.coef_), \
            "the feature number of X_predict must be equal to X_train"

        X_b = np.hstack([np.ones((len(X_predict), 1)), X_predict])
        return self._sigmoid(X_b.dot(self._theta))
 


    def predict(self, X_predict):
        """给定待预测数据集X_predict,返回表示X_predict的结果向量"""
        assert self.intercept_ is not None and self.coef_ is not None, \
            "must fit before predict!"
        assert X_predict.shape[1] == len(self.coef_), \
            "the feature number of X_predict must be equal to X_train"

        proba=self.predict_proba(X_predict)
        return np.array(proba>=0.5,dtype='int')

    def score(self, X_test, y_test):
        """根据测试数据集 X_test 和 y_test 确定当前模型的准确度"""

        y_predict = self.predict(X_test)
        return accuracy_score(y_test, y_predict)

    def __repr__(self):
        return "LinearRegression()"

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
iris=datasets.load_iris()
x=iris.data
y=iris.target
x=x[y<2,:2]#只取y=0,1的两个分类,为了方便可视化而只取两个特征
y=y[y<2]

我们先看看这堆数据的散点图


原始数据散点图
###使用逻辑回归
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.2,random_state=6)
#实际上这里size默认是0.2
log_reg=LogisticRegression()
log_reg.fit(x_train,y_train)

结果
决策边界
决策边界
其实在二维情况下的函数,就是初中高中的二元一次函数,使用这一直线对数据进行分割。
上面示例的划分如图
划分
对于非直线划分的情况呢?——多项式特性
圆形决策边界
类似于我们在多项式回归中使用的技巧,将x12、x22视为一个特征进行计算即可,由此我们还可以得到其他圆形,曲线一类的......
这里就不进行额外的实现了

用sklearn实现逻辑回归&&正则化

不同于前面多项式回归中的模型正则化,我们有一点点的区别:


正则化区别

常数参数由alpha变成了C,实际上我们可以视为1/alpha,其效果类似,但是使用c进行正则化,主要是考虑到逻辑回归时,L1,L2一般是要为1,所以便于计算,我们取了C放在J前面,其原理类似之前。

#sklearn 中的逻辑回归
import numpy as np
import matplotlib.pyplot as plt
X=np.random.normal(0,1,size=(200,2))
y=np.array(X[:,0]**2+X[:,1]<1.5,dtype='int')#抛物线

for k in range(20):
    y[np.random.randint(200)]=1#加20个噪音
plt.scatter(X[y==0,0],X[y==0,1])
plt.scatter(X[y==1,0],X[y==1,1])

我们先看看散点图分布


散点图
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test=train_test_split(X,y,test_size=0.2,random_state=6)
#实际上这里size默认是0.2
from sklearn.linear_model import LogisticRegression
log_reg=LogisticRegression()
log_reg.fit(x_train,y_train)

这里我们先留意一下逻辑回归的参数,因为后面调参可能会用到


参数

我们先看看使用线性的逻辑回归进行分类的结果,可以预见的,效果并不好,因为我们的数据实际是需要二次函数进行分类的


结果1
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import PolynomialFeatures
def PolyLogisticRegression(degree):
    return Pipeline([
        ("poly",PolynomialFeatures(degree=degree)),
        ("std_scacler",StandardScaler()),
        ("lin_reg",LogisticRegression())
    ])
poly_log_reg=PolyLogisticRegression(degree=2)
poly_log_reg.fit(x_train,y_train)
poly_log_reg.score(x_train,y_train)

这里我们使用二阶进行分类,查看结果


结果2

我们可以看到,结果显然好了不少
我们可以接着改变degree进行测试,这里就不做展开了

OVR&&OVO

我们前面进行的都是二分类,但是二分类显然无法满足实际,作为用处最为广泛的分类算法,逻辑回归自然也具有多分类功能。

  • OVR一对剩余所有


    OVR
  • OVO一对一
    OVO
    一般来说一对一要准确度更高,但是复杂度也更高,遵循排列组合中的Cn2计算出需要进行分类的次数,这显然比一对剩余的n次要复杂的多。
    下面使用鸢尾花数据集(3分类)进行三分类
    sklearn中非常人性化地给我们自动添加了多分类的功能,查看参数得知,默认是OVR ,即我们不用担心我们现在是几分类问题
#三分类
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
iris=datasets.load_iris()
x=iris.data
y=iris.target
x=x[:,:2]#为了方便可视化而只取两个特征
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.2,random_state=6)
from sklearn.linear_model import LogisticRegression
#sklearn中自动封装了多分类
log_reg=LogisticRegression()
log_reg.fit(x_train,y_train)#默认支持且使用ovr方式
log_reg.score(x_train,y_train)

(这里可视化的代码有点复杂,懒得去理解了,故不作可视化了)


结果1

注意这里的将ovr改成ovo的方式,一是需要改multi_class,二是由于解法不能使用ovr的默认解法,故也许更改,这里查阅手册,可以改成newton-cg

log_reg2=LogisticRegression(multi_class="multinomial",solver="newton-cg")#ovo方式
log_reg2.fit(x_train,y_train)
log_reg2.score(x_train,y_train)

这是不仅仅只用两个特征的例子,使用的完整数据

#使用所有数据
#三分类
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
iris=datasets.load_iris()
x=iris.data
y=iris.target
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.2,random_state=6)
from sklearn.linear_model import LogisticRegression
#sklearn中自动封装了多分类
log_reg=LogisticRegression()
log_reg.fit(x_train,y_train)#默认支持且使用ovr方式
log_reg.score(x_train,y_train)
log_reg2=LogisticRegression(multi_class="multinomial",solver="newton-cg")#ovo方式
log_reg2.fit(x_train,y_train)
log_reg2.score(x_train,y_train)
结果2

sklearn中其实也封装了ovr、ovo两个类,我们调用试试

#sklearn中特地封装了ovr、ovo两个类
from sklearn.multiclass import OneVsRestClassifier
ovr=OneVsRestClassifier(log_reg)#传进去一个二分类器即可
ovr.fit(x_train,y_train)#自动使用ovr方式
ovr.score(x_test,y_test)

from sklearn.multiclass import OneVsOneClassifier
ovo=OneVsOneClassifier(log_reg)#传进去一个二分类器即可
ovo.fit(x_train,y_train)#自动使用ovr方式
ovo.score(x_test,y_test)

结果和前面应该是一样的

总结

逻辑回归的全部内容到这里就结束了,这是用的最多的一种机器学习算法,里面含括了不少我们前面学到的重要知识,能够掌握好前面整个部分的代码原理是很重要的,可算是码完字了,溜了溜了!

相关文章

  • 机器学习day7-逻辑回归问题

    逻辑回归 逻辑回归,是最常见最基础的模型。 逻辑回归与线性回归 逻辑回归处理的是分类问题,线性回归处理回归问题。两...

  • ML03-逻辑回归(下部分)

    本文主题-逻辑回归(下部分):逻辑回归的应用背景逻辑回归的数学基础逻辑回归的模型与推导逻辑回归算法推导梯度下降算法...

  • ML02-逻辑回归(上部分)

    本文主题-逻辑回归(上部分):逻辑回归的应用背景逻辑回归的数学基础逻辑回归的模型与推导逻辑回归算法推导梯度下降算法...

  • 逻辑回归模型

    1.逻辑回归介绍2.机器学习中的逻辑回归3.逻辑回归面试总结4.逻辑回归算法原理推导5.逻辑回归(logistic...

  • Task 01|基于逻辑回归的分类预测

    知识背景 关于逻辑回归的几个问题 逻辑回归相比线性回归,有何异同? 逻辑回归和线性回归最大的不同点是逻辑回归解决的...

  • 11. 分类算法-逻辑回归

    逻辑回归 逻辑回归是解决二分类问题的利器 逻辑回归公式 sklearn逻辑回归的API sklearn.linea...

  • 机器学习100天-Day4-6逻辑回归

    逻辑回归(Logistic Regression) 什么是逻辑回归 逻辑回归被用于对不同问题进行分类。在这里,逻辑...

  • SKlearn_逻辑回归小练习

    逻辑回归 逻辑回归(Logistic regression 或logit regression),即逻辑模型(英语...

  • R glm

    R 逻辑回归 R 怎么做逻辑回归

  • 逻辑斯蒂回归在二分类中的应用

    逻辑回归简介 逻辑斯蒂回归(logistic regression,又称“对数几率回归”)是经典的分类方法。逻辑斯...

网友评论

    本文标题:逻辑回归

    本文链接:https://www.haomeiwen.com/subject/smxsdhtx.html