【机器学习】4.逻辑回归之Python代码实现

该文章已生成可运行项目,

逻辑回归(Logistic Regression)是机器学习中解决二分类问题的经典算法,本文使用两种方式实现逻辑回归,包括手动实现梯度下降优化和使用scikit-learn库的两种方式,便于理解原理和实际应用。

一、生成样本数据并划分训练集和测试集

导入相关库

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report
# 设置中文显示
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
plt.rcParams["axes.unicode_minus"] = False  # 正确显示负号

1. Python 中 scikit-learn(sklearn) 库提供的make_classification1生成一个随机的 n 类分类问题数据集,包含特征矩阵(X)和标签(y)。它能快速生成具有特定特征的合成数据,避免了处理真实数据时可能遇到的清洗、预处理等复杂步骤。

2. 划分数据集采用scikit-learn库中提供的train_test_split2函数,用于将数据集划分为训练集和测试集。

代码实现如下:

# ----------------------
# 2. 生成样本数据并测试
# ----------------------
if __name__ == "__main__":
    # 生成二分类样本数据
    X, y = make_classification(
        n_samples=1000,  # 样本数
        n_features=2,  # 特征数
        n_informative=2,  # 有效特征数
        n_redundant=0,  # 冗余特征数
        random_state=42
    )
    
    # 划分训练集和测试集
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.2, random_state=42
    )

二、手动实现部分

1. 手动实现逻辑回归

  • 定义了ManualLogisticRegression类,包含sigmoid函数、模型训练和预测方法
  • 训练过程使用梯度下降算法优化参数(权重weights和偏置bias
  • 预测时通过sigmoid函数得到概率,再根据阈值(默认0.5)判断类别

代码实现如下:

# ----------------------
# 1. 手动实现逻辑回归
# ----------------------
class ManualLogisticRegression:
    def __init__(self, learning_rate=0.01, num_iterations=10000):
        self.learning_rate = learning_rate
        self.num_iterations = num_iterations
        self.weights = None
        self.bias = None
    
    # Sigmoid函数
    def sigmoid(self, z):
        return 1 / (1 + np.exp(-z))
    
    # 训练模型
    def fit(self, X, y):
        m, n = X.shape  # m是样本数,n是特征数
        
        # 初始化参数
        self.weights = np.zeros(n)
        self.bias = 0
        
        # 梯度下降
        for _ in range(self.num_iterations):
            # 计算线性输出和预测概率
            z = np.dot(X, self.weights) + self.bias
            y_pred = self.sigmoid(z)
            
            # 计算梯度
            dw = (1 / m) * np.dot(X.T, (y_pred - y))
            db = (1 / m) * np.sum(y_pred - y)
            
            # 更新参数
            self.weights -= self.learning_rate * dw
            self.bias -= self.learning_rate * db
    
    # 预测
    def predict(self, X, threshold=0.5):
        z = np.dot(X, self.weights) + self.bias
        y_pred_proba = self.sigmoid(z)
        return (y_pred_proba >= threshold).astype(int)

2.测试手动实现的逻辑回归

 # ----------------------
    # 测试手动实现的逻辑回归
    # ----------------------
    manual_model = ManualLogisticRegression(learning_rate=0.01, num_iterations=10000)
    manual_model.fit(X_train, y_train)
    manual_y_pred = manual_model.predict(X_test)
    
    print("手动实现的逻辑回归结果:")
    print(f"准确率: {accuracy_score(y_test, manual_y_pred):.4f}")
    print(classification_report(y_test, manual_y_pred))
    

三、测试scikit-learn的逻辑回归

  • 直接使用sklearn库中的LogisticRegression
  • 调用fit方法训练模型,predict方法进行预测
  • 便于实际应用,内部实现了更优化的求解算法
    # ----------------------
    # 测试scikit-learn的逻辑回归
    # ----------------------
    sk_model = LogisticRegression()
    sk_model.fit(X_train, y_train)
    sk_y_pred = sk_model.predict(X_test)

    print("\nscikit-learn的逻辑回归结果:")
    print(f"准确率: {accuracy_score(y_test, sk_y_pred):.4f}")
    print(classification_report(y_test, sk_y_pred))

四、可视化决策边界

  • 绘制了两个模型的决策边界,直观展示分类效果
  • 可以看到两种实现的决策边界非常接近,说明手动实现的正确性
 # ----------------------
 # 可视化决策边界
 # ----------------------
    def plot_decision_boundary(X, y, model, title):
        h = 0.02  # 网格步长
        x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
        y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
        xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                             np.arange(y_min, y_max, h))
        
        # 预测网格点类别
        Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
        Z = Z.reshape(xx.shape)
        
        # 绘制决策边界和散点图
        plt.contourf(xx, yy, Z, alpha=0.8)
        plt.scatter(X[:, 0], X[:, 1], c=y, edgecolors='k')
        plt.title(title)
        plt.xlabel('特征1')
        plt.ylabel('特征2')
    
    plt.figure(figsize=(12, 5))
    plt.subplot(121)
    plot_decision_boundary(X_test, y_test, manual_model, "手动实现的逻辑回归决策边界")
    plt.subplot(122)
    plot_decision_boundary(X_test, y_test, sk_model, "scikit-learn的逻辑回归决策边界")
    plt.tight_layout()
    plt.show()

在这里插入图片描述

在这里插入图片描述

五、运行结果说明

  • 代码会输出两种实现方式的准确率和分类报告(精确率、召回率、F1分数)
  • 绘制的决策边界图展示了模型如何将两个类别的样本分开
  • 对于简单的二分类问题,两种实现的效果基本一致

你可以通过调整learning_rate(学习率)和num_iterations(迭代次数)来优化手动实现的模型性能。


  1. Scikit-learn中的make_classification:是sklearn.datasets模块中的函数,用于生成随机的多类分类问题数据集。其函数签名为sklearn.datasets.make_classification(n_samples=100, n_features=20, n_informative=2, n_redundant=2, n_repeated=0, n_classes=2, n_clusters_per_class=2, weights=None, flip_y=0.01, class_sep=1.0, hypercube=True, shift=0.0, scale=1.0, shuffle=True, random_state=None)。各参数含义如下:

    • n_samples:生成样本数量,默认为100。
    • n_features:特征总数,包括有用特征、冗余特征等,默认为20。
    • n_informative:有用特征数量,默认为2。
    • n_redundant:冗余特征数量,是有用特征的随机线性组合,默认为2。
    • n_repeated:重复特征数量,从有用特征和冗余特征中随机抽取,默认为0。
    • n_classes:分类问题的类别数,默认为2。
    • n_clusters_per_class:每个类别的聚类数,默认为2。
    • weights:各类别样本比例,若为None,则类别平衡。
    • flip_y:随机交换类别的样本比例,默认为0.01。
    • class_sep:类别分离度,默认为1.0。
    • hypercube:若为True,聚类点位于超立方体顶点,否则位于随机多面体顶点,默认为True
    • shift:特征偏移量,默认为0.0。
    • scale:特征缩放因子,默认为1.0。
    • shuffle:是否打乱样本,默认为True
    • random_state:随机数种子,用于复现结果。
    ↩︎
  2. train_test_split是机器学习中用于将数据集划分为训练集和测试集的常用函数,在Python的Scikit-learn库中有所定义,其相关信息如下:
    函数签名sklearn.model_selection.train_test_split(*arrays, test_size=None, train_size=None, random_state=None, shuffle=True, stratify=None)
    参数含义

    • *arrays:要划分的输入数据,可以是列表、Numpy数组、Scipy稀疏矩阵或Pandas数据帧等,要求所有输入数据的长度或形状(第0维)相同。
    • test_size:指定测试集的大小。如果是浮点数,应在0.0到1.0之间,表示测试集占数据集的比例;如果是整数,表示测试集的样本数量。如果为None,则其值将设置为train_size的补集;若train_size也为None,默认值为0.25。
    • train_size:指定训练集的大小,用法与test_size类似,若为None,会根据test_size自动计算。
    • random_state:控制数据划分前的洗牌操作。传入一个整数可以确保多次调用函数时得到相同的划分结果,用于结果复现。
    • shuffle:布尔值,指示在划分数据之前是否对数据进行洗牌。如果为False,则stratify必须为None
    • stratify:如果不是None,则数据将以分层的方式进行划分,通常传入类别标签,以保证训练集和测试集中各类别的比例与原始数据一致,适用于处理不平衡数据集。
      返回值:返回一个长度为2倍输入数据数量的列表,包含划分后的训练集和测试集数据。例如,输入特征矩阵X和标签向量y,则返回[X_train, X_test, y_train, y_test]
      通过使用train_test_split,可以方便地将原始数据集划分为两部分,分别用于训练模型和评估模型性能,有助于判断模型在新数据上的泛化能力,避免模型过拟合。
    ↩︎
本文章已经生成可运行项目
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值