Logistic Regression --【python代码实现】

此文章缺乏一些公式推导,只直接给代码和必要的解释

1、 创建一个类

import numpy as np

# 以下包是用来操作数据,检验准确率的。这里没有给出。
from sklearn.model_selection import train_test_split  # 划分数据集
from sklearn.preprocessing import StandardScaler  # 用来去均值和方差归一化,针对每个特征的处理
from sklearn.metrics import accuracy_score  # 分类准确率分数,分类正确的百分比  不同于precise

class LogisticRegression(object):

    def __init__(self, n_iter=5000, eta=0.01, diff=None):
        # 梯度下降循环次数
        self.n_iter = n_iter
        # 学习率
        self.eta = eta
        # 提前停止的阈值
        self.diff = diff
        # 参数w,训练最终需要的结果
        self.w = None

2、 Train Part

# 训练部分
    def _Fit(self, X_train, Y_train):
        """
        首先进行数据预处理.
        X_train 输入的是每个样本水平放置的训练集,在训练集最左侧需要添加一列1.
        (原因为了将偏置也放进参数w中,不懂的话需要自己取补补知识了)
        """
        X_train = self._X_preprocess(X_train)  # 方法①
        # 根据X的特征数初始化参数w
        _, n = X_train.shape
        self.w = np.random.random(n) * 0.05  # 随机初始化 默认shape为(n, 1)
        # 进行利用梯度下降的模型学习
        self._gradient_descent(self.w, Y_train, X_train)  # 方法②

# 部分方法补充
    # 方法①
    def _X_preprocess(self, Xtrain):

        # 数据预处理
        m, n = Xtrain.shape
        # 创建一个矩阵
        new_Train_X = np.empty((m, n + 1))
        # 第一列填充1
        new_Train_X[:, 0] = 1
        # 后面使用源数据集补上
        new_Train_X[:, 1:] = Xtrain
        return new_Train_X  # 返回此新的数据集

    # 方法②
    def _gradient_descent(self, w,  Ytrain, Xtrain):
        # 这是计算loss的时候的y的个数
        m = Ytrain.size
        # 加入有要求 差值(阈值)
        if self.diff is not None:
            loss_last = np.inf  # 这是一个非常大的数

        # self.loss_list = []  # 用来存放loss 方便观察  需要时用

        for step in range(self.n_iter):
            # 计算y_hat
            y_hat = 1. / (1. + np.exp(-np.dot(Xtrain, self.w)))  # 先得到z,然后扔进sigmoid函数求值
            # y_hat = self._predict_proba(Xtrain, self.w)
                                    
            # 计算梯度
            dJ = np.dot(y_hat - Ytrain, Xtrain) / m
            
            # 计算损失(对数损失函数)首先最外层会有一个-1/m(m=y.size)然后是对对数似然函数的计算,再相乘
            loss_new = -1 / m * np.sum(Ytrain * np.log(y_hat) + (1 - Ytrain)*np.log(1 - y_hat))
            
            # 这是书籍里的代码原函数,看不懂和公式的关系。
            # loss_new = -np.sum(np.log(y_hat * (2 * Ytrain - 1) + (1 - Ytrain))) / m   
            
            # 记录损失
            # self.loss_list.append(loss_new)  # 需要时用
            # 显示最新一次损失
            print(f">>第{step+1}次梯度下降,损失:{loss_new}")

            # 达到阈值就停止迭代
            if self.diff is not None:
                if np.abs(loss_new - loss_last) <= self.diff:
                    break
                loss_last = loss_new

            # 更新w
            self.w -= self.eta * dJ 

3、Predict Part

    def _Predict(self, X):
        # 预处理
        X = self._X_preprocess(X)
        # 预测y=1的概率
        y_pred = 1/(1+np.exp(-np.dot(X, self.w)))
        # 根据概率 预测类别
        return np.where(y_pred >= 0.5, 1, 0)

检验准确率结果(过程省略)

经过100次预测观察准确率并取平均值,还挺高,该代码应该可放心使用

在这里插入图片描述

完整代码

import numpy as np

class LogisticRegression(object):

    def __init__(self, n_iter=5000, eta=0.0005, diff=None):
        self.n_iter = n_iter
        self.eta = eta
        self.diff = diff
        self.w = None

    def _Fit(self, X_train, Y_train):
        X_train = self._X_preprocess(X_train)
        _, n = X_train.shape
        self.w = np.random.random(n) * 0.05
        self._gradient_descent(self.w, Y_train, X_train)

    def _X_preprocess(self, Xtrain):
        m, n = Xtrain.shape
        new_Train_X = np.empty((m, n + 1))
        new_Train_X[:, 0] = 1
        new_Train_X[:, 1:] = Xtrain
        return new_Train_X  
    
    def _gradient_descent(self, w,  Ytrain, Xtrain):
        m = Ytrain.size
        if self.diff is not None:
            loss_last = np.inf 

        for step in range(self.n_iter):
            y_hat = 1. / (1. + np.exp(-np.dot(Xtrain, self.w)))
            dJ = np.dot(y_hat - Ytrain, Xtrain) / Ytrain.size
            loss_new = -1 / m * np.sum(Ytrain * np.log(y_hat) + (1 - Ytrain)*np.log(1 - y_hat))
            print(f">>第{step+1}次梯度下降,损失:{loss_new}")
            if self.diff is not None:
                if np.abs(loss_new - loss_last) <= self.diff:
                    break
                loss_last = loss_new
            self.w -= self.eta * dJ 

    def _Predict(self, X):
        X = self._X_preprocess(X)
        y_pred = 1/(1+np.exp(-np.dot(X, self.w)))
        return np.where(y_pred >= 0.5, 1, 0)
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JamePrin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值