使用python实现逻辑回归算法(logistic regression,完整代码及详细注释)

本例中使用的代价函数为:
J = − y log ⁡ a − ( 1 − y ) log ⁡ ( 1 − a ) J = -y\log a -(1-y)\log (1-a) J=yloga(1y)log(1a)
如果对这个代价函数或者其求导不了解,可以先看看这篇文章交叉熵(the cross-entropy)代价函数的详细介绍及推导过程

如代码有误或不理解欢迎留言讨论

# -*- coding:utf-8
"""
作者: Jia
日期: 2022年01月30日
描述: 逻辑回归的算法实现
"""
import numpy as np


class LogisticRegression:
    def __init__(self):
        """
        初始化 Logistic Regression 模型
        """
        self.coef = None  # 权重矩阵
        self.intercept = None  # 截距
        self._theta = None  # _theta[0]是intercept,_theta[1:]是coef

    def sigmoid(self, x):
        """
        sigmoid 函数
        :param x: 参数x
        :return: 取值y
        """
        y = 1.0 / (1.0 + np.exp(-x))
        return y

    def loss_func(self, theta, x_b, y):
        """
        损失函数
        :param theta: 当前的权重和截距
        :param x_b: 修改过的数据集(第一列为全1)
        :param y: 数据集标签
        :return:
        """
        p_predict = self.sigmoid(x_b.dot(theta))
        try:
            return -np.sum(y * np.log(p_predict) + (1 - y) * np.log(1 - p_predict))
        except:
            return float('inf')

    def d_loss_func(self, theta, x_b, y):
        """
        损失函数的导数
        :param theta: 当前的权重和截距
        :param x_b: 修改过的数据集(第一列为全1)
        :param y: 数据集标签
        :return:
        """
        out = self.sigmoid(x_b.dot(theta))  # 计算sigmoid函数的输出结果
        return x_b.T.dot(out - y) / len(x_b)

    def gradient_descent(self, x_b, y, initial_theta, eta, n_iters=1e4, epsilon=1e-8):
        """
        梯度下降函数
        :param x_b: 修改过的数据集(第一列为全1)
        :param y: 数据集标签
        :param initial_theta: 初始权重矩阵
        :param eta: 学习率
        :param n_iters: 最大迭代周期
        :param epsilon: 当两次训练损失函数下降小于此值是提前结束训练
        :return:
        """
        theta = initial_theta
        i_iter = 0
        while i_iter < n_iters:
            gradient = self.d_loss_func(theta, x_b, y)
            last_theta = theta
            theta = theta - eta * gradient
            i_iter += 1
            if abs(self.loss_func(theta, x_b, y) - self.loss_func(last_theta, x_b, y)) < epsilon:
                break
        return theta

    def fit(self, train_data, train_label, eta=0.01, n_iters=1e4):
        """
        模型训练函数
        :param train_data: 训练数据集
        :param train_label: 训练数据标签
        :param eta: 学习率,默认为0.01
        :param n_iters: 最大迭代次数
        :return:
        """
        assert train_data.shape[0] == train_label.shape[0], "训练数据集的长度需要和标签长度保持一致"
        x_b = np.hstack([np.ones((train_data.shape[0], 1)), train_data])  # 在原有数据集前加全1列
        initial_theta = np.zeros(x_b.shape[1])  # 初始化权重值
        self._theta = self.gradient_descent(x_b, train_label, initial_theta, eta, n_iters)  # 使用梯度下降训练数据
        self.intercept = self._theta[0]  # 得到截距
        self.coef = self._theta[1:]  # 得到权重矩阵
        return self

    def predict_proba(self, x_predict):
        """
        得到预测的实际结果
        :param x_predict: 待预测值
        :return: 预测的实际结果
        """
        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):
        """
        对数据进行分类
        :param x_predict: 待分类的数据集
        :return: 数据集分类
        """
        proba = self.predict_proba(x_predict)
        # 由于sigmoid函数的输出值是在0-1的,因此将小于0.5的归为一类,将大于0.5的归为一类
        return np.array(proba > 0.5, dtype='int')

你可能感兴趣的:(深度学习,python,回归,机器学习)