数据挖掘学习--逻辑回归1

本文深入探讨了逻辑回归的基本概念,解释了其如何通过线性回归结合sigmoid函数进行分类预测,详细介绍了损失函数、梯度下降法及其实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.前言

这几天一直在学习逻辑回归(在书上是叫逻辑斯提回归),听着这个名词并没有其他的机器学习方法那么容易知道他是做什么的。而实际上,逻辑回归类似与线性回归,只不过线性回归中是将每个数据样本(可能这个样本是一个向量)进行回归,而回归的结果是一个值,是一个预测的回归值。而逻辑回归就是在线性回归的基础上将这个回归值,通过函数计算得到一个概率值,再通过概率值来进行分类,从而得到分类的效果。

2.逻辑回归的数学理论

前言所讲到的逻辑回归是通过利用线性回归的基础通过某个函数进行分类(计算概率)。比较常见的就是一个sigmoid函数:
其中p就是概率值,σ()就是sigmoid函数,而x_b是一个带预测的样本向量,而θ是一个模型的超参数的向量要计算的目标结果变了,那么自然我们逻辑回归模型的损失函数J(θ)就要改变。我们先从p_hat这个概率值的损失函数进行讨论,不难看出,我们的原则就是若p_hat超过0.5的话,就将这个带预测样本归为1类,而若不超过0.5,就归为0类,达到分类的目标。
cost函数的目的就是要惩罚那些分类错误的情况:举个例子就是,当一个训练样本本来是1类的,意味这最理想的状态就是p_hat是超过0.5的,但是通过计算得出的p_hat却低于0.5,可以看作错误分类的情况,那么对于这个样本的cost就应该很大很大。由这种思路,就可以很好理解这个cost函数了:
在这里插入图片描述
又或者换一种形式:
在这里插入图片描述
这两者是等价的。

那么对于n个训练样本就有n个cost,将这些样本的cost值全部累加起来自然就能得到一个模型的总损失函数J(θ):
在这里插入图片描述到这里损失函数就很容易理解了,自然我们想用的梯度下降法来求得θ参数,就应该得到损失函数的导数:
在这里插入图片描述
用梯度下降法就能求出最佳的θ,从而使得模型损失最小。逻辑回归模型就很容易理解了。

3.逻辑回归代码:

import numpy as np
from sklearn.metrics import accuracy_score

class LogisticRegression:

    def __init__(self):

        self.coef = None
        self.theta = None
        self.interception = None

    #当传进来的t是一个向量,那么就自然的sigmoid函数后就是一个向量
    #公式中的y_hat相当与p_hat,也是一个向量
    def _sigmoid(self , t):
        return 1. / (1. + np.exp(t))

    def fit(self , x_train , y_train):

        # 损失函数,自变量是theta,因变量是J,对不同的x_train或者不同的theta,会有不同的J
        # 在梯度下降法中,主要考虑theta变化后,损失函数J变成什么
        def J(x_train , y_train , theta):
            assert x_train.shape[0] == y_train.shape[0] , "The shape of x_train is not equal to y_train."

            p_hat = self._sigmoid(x_train.dot(theta))

            try:
                return - np.sum(p_hat * np.log(p_hat) + (1 - p_hat) * np.log(1 - p_hat)) / len(y_train)
            except:
                return float('inf')

        #损失函数的导数,也需要用到训练集,以及参数theta
        #区别开类的theta是最终theta,fit的theta是仍然在调整的theta
        def dJ(x_train , y_train ,theta):
            assert x_train.shape[0] == y_train.shape[0], "The shape of x_train is not equal to y_train."
            return x_train.T.dot(self._sigmoid(x_train.dot(theta)) - y_train) / len(y_train)

        def gradient_descent(x_train , y_train , initial_theta , eta = 0.01 , n_iter = 1e4 , epsional = 1e-8):
            count = 0
            theta = initial_theta
            while count < n_iter:
                history_theta = theta
                gradient = dJ(x_train , y_train , theta)
                theta = theta - gradient * eta
                if(abs(J(x_train , y_train, theta) - J(x_train , y_train, history_theta)) < epsional):
                    break
                count += 1
            return theta

        X_b = np.hstack([np.ones((x_train.shape[0] , 1)) ,x_train])
        initial_theta = np.zeros(X_b.shape[1])
        theta = gradient_descent(X_b , y_train , initial_theta)

        self.theta = theta
        self.coef = theta[1:]
        self.interception = theta[0]

    def predict(self,x_predict):
        assert self.theta is not None , "The model needs to be fitted before you predict."
        assert x_predict.shape[1] == len(self.coef) , "No."

        x = x_predict.copy()
        x1 = np.hstack([np.ones((len(x) , 1)) , x])
        p_hat = self._sigmoid(x1.dot(self.theta))

        return np.array(p_hat >= 0.5 , dtype='int')

    def score(self , y_predict , y_test):
        assert y_test.shape[0] == y_predict.shape[0] , "The shape of x_predict need to be equal to y_predict."

        return accuracy_score(y_predict , y_test)


    def __repr__(self):
        return "Logistic Regression()"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值