import numpy as np

# 定义sigmoid函数
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

# 定义损失函数
def loss(y, y_pred):
    return -np.mean(y * np.log(y_pred) + (1 - y) * np.log(1 - y_pred))

# 定义模型类
class LogisticRegression:
    def __init__(self, lr=0.01, num_iter=100000, fit_intercept=True, verbose=False):
        self.lr = lr  # 学习率
        self.num_iter = num_iter  # 迭代次数
        self.fit_intercept = fit_intercept  # 是否拟合截距
        self.verbose = verbose  # 是否输出迭代过程中的损失值
        self.theta = None  # 模型参数

    def add_intercept(self, X):
        intercept = np.ones((X.shape[0], 1))
        return np.concatenate((intercept, X), axis=1)

    def fit(self, X, y):
        if self.fit_intercept:
            X = self.add_intercept(X)

        # 初始化参数
        self.theta = np.zeros(X.shape[1])

        # 迭代更新参数
        for i in range(self.num_iter):
            z = np.dot(X, self.theta)
            y_pred = sigmoid(z)
            gradient = np.dot(X.T, (y_pred - y)) / y.size
            self.theta -= self.lr * gradient

            # 输出迭代过程中的损失值
            if self.verbose and i % 10000 == 0:
                print(f'Loss after iteration {i}: {loss(y, y_pred)}')

    def predict_prob(self, X):
        if self.fit_intercept:
            X = self.add_intercept(X)

        return sigmoid(np.dot(X, self.theta))

    def predict(self, X, threshold=0.5):
        return self.predict_prob(X) >= threshold

主要优化点:

  1. 将sigmoid函数和损失函数定义为独立的函数,使得代码更加清晰易懂。
  2. 使用numpy的向量化操作,避免了循环,大大提高了计算效率。
  3. 将模型参数的初始化和迭代更新分开,使得代码更加清晰易懂。
  4. 添加了可选的verbose参数,控制是否输出迭代过程中的损失值。
  5. 在预测时,添加了可选的threshold参数,控制分类的阈值。

原文地址: http://www.cveoy.top/t/topic/m5jI 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录