第6章 逻辑斯谛回归(LogisticRegression)代码实现

本文深入探讨了逻辑回归算法的原理及其实现过程,通过使用Python的sklearn库和从零开始编写代码两种方式,详细解释了逻辑回归在鸢尾花数据集上的应用。同时,文章对比了自定义逻辑回归模型与sklearn内置模型的性能,展示了模型的训练、预测及评估过程。

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

=============================== 【回到目录】===============================

第6章 逻辑斯谛回归(LogisticRegression)代码实现

LogisticRegression
from math import exp
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

# data
def create_data():
    iris = load_iris()
    X, y = np.array(iris.data), np.array(iris.target)
    return X[:100, 0:2], y[:100]

X, y = create_data()
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)


class LogisticRegressionClassifier:
    def __init__(self, max_iter=200, learning_rate=0.01):
        self.max_iter = max_iter
        self.learning_rate = learning_rate

    def sigmoid(self, x):
        return 1 / (1 + exp(-x))

    def data_matrix(self, X):
        data_mat = []
        for d in X:
            data_mat.append([1.0, *d])
        return data_mat

    def fit(self, X, y):
        # label = np.mat(y)
        data_mat = self.data_matrix(X)  # m*n
        self.weights = np.zeros((len(data_mat[0]), 1), dtype=np.float32)

        for iter_ in range(self.max_iter):
            for i in range(len(X)):
                result = self.sigmoid(np.dot(data_mat[i], self.weights))
                error = y[i] - result
                self.weights += self.learning_rate * error * np.transpose([data_mat[i]]) #注意这里的[data_mat[i]]

        print('LogisticRegression Model(learning_rate={},max_iter={})'.format(self.learning_rate, self.max_iter))

    # def f(self, x):
    #     return -(self.weights[0] + self.weights[1] * x) / self.weights[2]

    def score(self, X_test, y_test):
        right = 0
        X_test = self.data_matrix(X_test)
        for x, y in zip(X_test, y_test):
            result = np.dot(x, self.weights)
            if (result > 0 and y == 1) or (result < 0 and y == 0):
                right += 1
        return right / len(X_test)

lr_clf = LogisticRegressionClassifier()
lr_clf.fit(X_train, y_train)
lr_clf.score(X_test, y_test)


x_ponits = np.arange(4, 8)
y_ = -(lr_clf.weights[1]*x_ponits + lr_clf.weights[0])/lr_clf.weights[2]
plt.plot(x_ponits, y_)

#lr_clf.show_graph()
plt.scatter(X[:50,0],X[:50,1], label='0')
plt.scatter(X[50:,0],X[50:,1], label='1')
plt.legend()
plt.show()

output:

在这里插入图片描述


最大熵模型 IIS
import math
from copy import deepcopy


class MaxEntropy:
    def __init__(self, EPS=0.005):
        self._samples = []
        self._Y = set()  # 标签集合,相当去去重后的y
        self._numXY = {}  # key为(x,y),value为出现次数
        self._N = 0  # 样本数
        self._Ep_ = []   # 样本分布的特征期望值
        self._xyID = {}   # key记录(x,y),value记录id号
        self._n = 0  # 特征键值(x,y)的个数
        self._C = 0   # 最大特征数
        self._IDxy = {}    # key为(x,y),value为对应的id号
        self._w = []
        self._EPS = EPS   # 收敛条件
        self._lastw = []    # 上一次w参数值

    def loadData(self, dataset):
        self._samples = deepcopy(dataset)
        for items in self._samples:
                y = items[0]
                X = items[1:]
                self._Y.add(y)  # 集合中y若已存在则会自动忽略
                for x in X:
                    if (x, y) in self._numXY:
                        self._numXY[(x, y)] += 1
                    else:
                        self._numXY[(x, y)] = 1

        self._N = len(self._samples)
        self._n = len(self._numXY)
        self._C = max([len(sample)-1 for sample in self._samples])
        self._w = [0]*self._n
        self._lastw = self._w[:]

        self._Ep_ = [0] * self._n
        for i, xy in enumerate(self._numXY):   # 计算特征函数fi关于经验分布的期望
            self._Ep_[i] = self._numXY[xy]/self._N
            self._xyID[xy] = i
            self._IDxy[i] = xy

    def _Zx(self, X):    # 计算每个Z(x)值
        zx = 0
        for y in self._Y:
            ss = 0
            for x in X:
                if (x, y) in self._numXY:
                    ss += self._w[self._xyID[(x, y)]]
            zx += math.exp(ss)
        return zx

    def _model_pyx(self, y, X):   # 计算每个P(y|x)
        zx = self._Zx(X)
        ss = 0
        for x in X:
            if (x, y) in self._numXY:
                ss += self._w[self._xyID[(x, y)]]
        pyx = math.exp(ss)/zx
        return pyx

    def _model_ep(self, index):   # 计算特征函数fi关于模型的期望
        x, y = self._IDxy[index]
        ep = 0
        for sample in self._samples:
            if x not in sample:
                continue
            pyx = self._model_pyx(y, sample)
            ep += pyx/self._N
        return ep

    def _convergence(self):  # 判断是否全部收敛
        for last, now in zip(self._lastw, self._w):
            if abs(last - now) >= self._EPS:
                return False
        return True

    def predict(self, X):   # 计算预测概率
        Z = self._Zx(X)
        result = {}

        for y in self._Y:
            ss = 0
            for x in X:
                if (x, y) in self._numXY:
                    ss += self._w[self._xyID[(x, y)]]
            pyx = math.exp(ss)/Z
            result[y] = pyx

        #或者写
        # for y in self._Y:
        #     result[y] = self._model_pyx(y, X)

        return result

    def train(self, maxiter=1000):   # 训练数据
        for loop in range(maxiter):  # 最大训练次数
            print("iter:%d" % loop)
            self._lastw = self._w[:]
            for i in range(self._n):
                ep = self._model_ep(i)    # 计算第i个特征的模型期望
                self._w[i] += math.log(self._Ep_[i]/ep)/self._C   # 更新参数
            print("w:", self._w)
            if self._convergence():  # 判断是否收敛
                break


dataset = [['no', 'sunny', 'hot', 'high', 'FALSE'],
           ['no', 'sunny', 'hot', 'high', 'TRUE'],
           ['yes', 'overcast', 'hot', 'high', 'FALSE'],
           ['yes', 'rainy', 'mild', 'high', 'FALSE'],
           ['yes', 'rainy', 'cool', 'normal', 'FALSE'],
           ['no', 'rainy', 'cool', 'normal', 'TRUE'],
           ['yes', 'overcast', 'cool', 'normal', 'TRUE'],
           ['no', 'sunny', 'mild', 'high', 'FALSE'],
           ['yes', 'sunny', 'cool', 'normal', 'FALSE'],
           ['yes', 'rainy', 'mild', 'normal', 'FALSE'],
           ['yes', 'sunny', 'mild', 'normal', 'TRUE'],
           ['yes', 'overcast', 'mild', 'high', 'TRUE'],
           ['yes', 'overcast', 'hot', 'normal', 'FALSE'],
           ['no', 'rainy', 'mild', 'high', 'TRUE']]

maxent = MaxEntropy()
x = ['overcast', 'mild', 'high', 'FALSE']
maxent.loadData(dataset)
maxent.train()
print('predict:', maxent.predict(x))

output:

predict: {'no': 2.8765395547617257e-06, 'yes': 0.9999971234604452}

sklearn LogisticRegression
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression

clf = LogisticRegression(max_iter=200)
clf.fit(X_train, y_train)
clf.score(X_test, y_test)
print(clf.coef_, clf.intercept_)
x_ponits = np.arange(4, 8)
y_ = -(clf.coef_[0][0]*x_ponits + clf.intercept_)/clf.coef_[0][1]
plt.plot(x_ponits, y_)

plt.plot(X[:50, 0], X[:50, 1], 'bo', color='blue', label='0')
plt.plot(X[50:, 0], X[50:, 1], 'bo', color='orange', label='1')
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()
plt.show()

output:

在这里插入图片描述

### 回答1: 逻辑回归(logistic regression)是一种用于分类问题的统计学习方法,属于监督学习中的一种。它的基本思想是通过建立模型去学习不同特征之间的关系,然后使用这个模型去对未知数据进行分类。逻辑回归是一种线性模型,可用于进行二分类或多分类问题。在统计学习方面,逻辑回归是一种经典的机器学习方法。 ### 回答2: 逻辑回归是一种用于二分类问题的机器学习算法。其基本思想是将输入变量与一个sigmoid函数相乘,从而得到该分类的概率值。这个sigmoid函数将实数映射到[0,1]区间内,当概率趋近于0时,函数取到0,概率趋近于1时,函数取到1,当输入为0时,函数取到0.5。这个函数的形式为: $$\sigma(z)=\frac{1}{1+e^{-z}}=\frac{e^z}{1+e^z}$$ 其中z为线性回归模型的输出。逻辑回归通过最大似然估计来确定模型参数,目标是最大化似然函数。似然函数的形式为: $$L(w)=\prod_{i=1}^N[y_iP(y_i=1|x_i,w)+(1-y_i)P(y_i=0|x_i,w)]$$ 其中N为样本数,$y_i\in\{0,1\}$为样本i的类别,$y_i=1$表示正例,$y_i=0$表示反例。$P(y_i=1|x_i,w)$和$P(y_i=0|x_i,w)$分别表示当输入变量为$x_i$时,样本i的正例概率和反例概率。使用log函数对似然函数取负对数,然后对参数w求偏导,得到的结果为: $$\nabla L(w)=\sum_{i=1}^N[y_i-\sigma(w^Tx_i)]x_i$$ 使用梯度下降法来更新参数,得到迭代更新公式为: $$w^{(t+1)}=w^{(t)}+\eta\nabla L(w^{(t)})$$ 其中$\eta$为学习率,$w^{(t)}$表示t时刻的参数值。 逻辑回归可以扩展到多分类问题,称为softmax回归,也可以应用于不同的领域,例如医学诊断、金融风险评估等。 ### 回答3: 逻辑回归(Logistic Regression)是一种用于处理二分类问题的统计机器学习算法,其思想来源于逻辑学。在《统计学习方法》一书中,逻辑回归是目标函数为对数似然函数,利用梯度下降法或牛顿法估计参数的一类判别模型逻辑回归模型可以表示为$$h_{\boldsymbol{w}}(\boldsymbol{x})=\sigma(\boldsymbol{w}^{\rm T} \boldsymbol{x})$$其中,$h_{\boldsymbol{w}}(\boldsymbol{x})\in [0,1]$ 表示 $\boldsymbol{x}$ 属于正类的概率,$\sigma(z)=\dfrac{1}{1+\mathrm{e}^{-z}}$ 是 sigmoid 函数。逻辑回归的目标函数是对数似然函数$$L(\boldsymbol{w})=\sum_{i=1}^{N}[y_i \log h_{\boldsymbol{w}}(\boldsymbol{x_i})+(1-y_i)\log(1-h_{\boldsymbol{w}}(\boldsymbol{x_i}))]$$其中,$N$ 是样本数量,$y_i\in\{0,1\}$ 是样本 $\boldsymbol{x_i}$ 的真实标记。对数似然函数一般通过梯度下降法或牛顿法来求得最优参数 $\boldsymbol{w}$。梯度下降法的更新公式是$$\boldsymbol{w} \leftarrow \boldsymbol{w}+\alpha \sum_{i=1}^{N}(y_i-h_{\boldsymbol{w}}(\boldsymbol{x_i}))\boldsymbol{x_i}$$其中,$\alpha$ 是学习率,$\boldsymbol{w}$ 初始化为 0 或其它随机值,重复进行上述更新直到收敛。牛顿法是一种二阶优化方法,其参数更新公式是$$\boldsymbol{w} \leftarrow \boldsymbol{w}-\boldsymbol{H}^{-1}\nabla_{\boldsymbol{w}}L(\boldsymbol{w})$$其中,$\boldsymbol{H}$ 是 Hessian 矩阵。牛顿法比梯度下降法收敛速度更快,但计算量更大。 逻辑回归的优点是模型参数较少,计算速度较快,且可以得到样本属于正类的概率。缺点是对异常值比较敏感,对特征之间的相关性比较敏感,容易出现过拟合。在实际应用中,可以通过添加正则化项或使用 L1、L2 正则化等方式来避免过拟合。 总之,逻辑回归是一种用于处理二分类问题的有效算法,可以应用于回归和分类问题。它的思想简单,实现容易,是初学者入门的理想算法之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值