Logistic回归(逻辑回归)及python代码实现

文章目录

  • Logistic(Logistic Regression,LR)回归
    • 原理讲解
    • 参数计算
  • python代码实现
    • 生成数据集
    • 不使用其他库实现
      • 定义激活函数(标准Logistic函数即Sigmoid函数)
      • 定义LogisticRegression类
      • 调用LogisticRegression类解决分类问题
    • 使用sklearn库
  • 拓展

Logistic(Logistic Regression,LR)回归

原理讲解

在模式识别问题中,所关心的量是分类,比如是否会患有某种疾病,这时就不能用简单的线性回归来完成这个问题了。为了解决次问题,我们引入了非线性激活函数

g

:

R

D

(

0

,

1

)

g:{\mathbb R}^D\to(0,1)

g:RD→(0,1)来预测类别标签的后验概率

p

(

y

=

1

x

)

p(y=1|\bf x)

p(y=1∣x),其中

y

{

0

,

1

}

y\in\{0,1\}

y∈{0,1},函数

g

g

g的作用是把线性函数的值域从实数区间挤压到0和1之间

在Logistic回归中,激活函数的表达式为:

σ

(

x

)

=

1

1

+

e

x

\sigma(x)=\frac{1}{1+e^{-x}}

σ(x)=1+e−x1​

标签

y

=

1

y=1

y=1的后验概率为

p

(

y

=

1

x

)

=

σ

(

w

T

x

)

=

1

1

+

e

w

T

x

(

1

)

p(y=1|{\bf x})=\sigma({\bf w}^{\rm T}{\bf {x}})=\frac{1}{1+e^{-{\bf w}^{\rm T}{\bf {x}}}}\cdots(1)

p(y=1∣x)=σ(wTx)=1+e−wTx1​⋯(1)

这里,

x

=

[

x

1

,


,

x

D

,

1

]

T

{\bf x}=[x_1,\cdots,x_D,1]^{\rm T}

x=[x1​,⋯,xD​,1]T和

w

=

[

w

1

,


,

w

D

,

b

]

T

{\bf w}=[w_1,\cdots,w_D,b]^{\rm T}

w=[w1​,⋯,wD​,b]T分别为D+1维的增广特征向量与增广权重向量

标签

y

=

0

y=0

y=0的后验概率为

p

(

y

=

0

x

)

=

1

p

(

y

=

1

x

)

=

e

w

T

x

1

+

e

w

T

x

p(y=0|{\bf x})=1-p(y=1|{\bf x})=\frac{e^{-{\bf w}^{\rm T}{\bf {x}}}}{1+e^{-{\bf w}^{\rm T}{\bf {x}}}}

p(y=0∣x)=1−p(y=1∣x)=1+e−wTxe−wTx​

对式(1)进行变换后得到

w

T

x

=

log

p

(

y

=

1

x

)

1

p

(

y

=

1

x

)

=

log

p

(

y

=

1

x

)

p

(

y

=

0

x

)

{\bf w}^{\rm T}{\bf {x}}=\log \frac{p(y=1|{\bf x})}{1-p(y=1|{\bf x})}=\log \frac{p(y=1|{\bf x})}{p(y=0|{\bf x})}

wTx=log1−p(y=1∣x)p(y=1∣x)​=logp(y=0∣x)p(y=1∣x)​上式左边为线性函数,右边为正反后验概率比值(几率)取对数,因此Logistic回归也称为对数几率回归

参数计算

LR采用交叉熵作为损失函数,使用梯度下降进行优化

假设存在N个训练样本

{

(

x

(

n

)

,

y

(

n

)

)

}

n

=

1

N

\{({\bf x}^{(n)},y^{(n)})\}_{n=1}^N

{(x(n),y(n))}n=1N​,采用LR回归模型对每个样本

x

(

n

)

{\bf x}^{(n)}

x(n)进行预测,输出其标签为1的后验概率,记为

y

^

(

n

)

{\hat y}^{(n)}

y^​(n),即

y

^

(

n

)

=

σ

(

w

T

x

(

n

)

)

,

1

n

N

{\hat y}^{(n)}=\sigma({\bf w}^{\rm T}{\bf {x}}^{(n)}),1\leq n\leq N

y^​(n)=σ(wTx(n)),1≤n≤N

由于

y

(

n

)

{

0

,

1

}

y^{(n)}\in\{0,1\}

y(n)∈{0,1},样本

(

x

(

n

)

,

y

(

n

)

)

({\bf x}^{(n)},y^{(n)})

(x(n),y(n))的真实条件概率可以表示为

p

r

(

y

(

n

)

=

1

x

(

n

)

)

=

y

(

n

)

,

p_r(y^{(n)}=1|{\bf x}^{(n)})=y^{(n)},

pr​(y(n)=1∣x(n))=y(n),

p

r

(

y

(

n

)

=

0

x

(

n

)

)

=

1

y

(

n

)

p_r(y^{(n)}=0|{\bf x}^{(n)})=1-y^{(n)}

pr​(y(n)=0∣x(n))=1−y(n)

采用交叉熵损失函数,其风险函数为

R

(

w

)

=

1

N

n

=

1

N

(

p

r

(

y

(

n

)

=

1

x

(

n

)

)

log

y

^

(

n

)

+

p

r

(

y

(

n

)

=

0

x

(

n

)

)

log

(

1

y

^

(

n

)

)

)

=

1

N

n

=

1

N

(

y

(

n

)

log

y

^

(

n

)

+

(

1

y

(

n

)

)

log

(

1

y

^

(

n

)

)

)

{\mathcal R}({\bf w})=-\frac{1}{N}\sum_{n=1}^N \left(p_r(y^{(n)}=1|{\bf x}^{(n)})\log {\hat y}^{(n)}+p_r(y^{(n)}=0|{\bf x}^{(n)})\log (1-{\hat y}^{(n)})\right) \\ =-\frac{1}{N}\sum_{n=1}^N\left(y^{(n)}\log {\hat y}^{(n)}+(1-y^{(n)})\log (1-{\hat y}^{(n)}) \right)

R(w)=−N1​n=1∑N​(pr​(y(n)=1∣x(n))logy^​(n)+pr​(y(n)=0∣x(n))log(1−y^​(n)))=−N1​n=1∑N​(y(n)logy^​(n)+(1−y(n))log(1−y^​(n)))

风险函数关于参数

w

\bf w

w的偏导数为

R

(

w

)

w

=

1

N

n

=

1

N

(

y

(

n

)

y

^

(

n

)

(

1

y

^

(

n

)

)

y

^

(

n

)

x

(

n

)

(

1

y

(

n

)

)

y

^

(

n

)

(

1

y

^

(

n

)

)

1

y

^

(

n

)

x

(

n

)

)

=

1

N

n

=

1

N

(

y

(

n

)

(

1

y

^

(

n

)

)

x

(

n

)

(

1

y

(

n

)

)

y

^

(

n

)

x

(

n

)

)

=

1

N

n

=

1

N

x

(

n

)

(

y

(

n

)

y

^

(

n

)

)

\frac{\partial {\mathcal R}({\bf w})}{\partial {\bf w}}=-\frac{1}{N}\sum_{n=1}^N\left(y^{(n)}\frac{{\hat y}^{(n)}(1-{\hat y}^{(n)})}{{\hat y}^{(n)}}{\bf x}^{(n)}-(1-y^{(n)})\frac{{\hat y}^{(n)}(1-{\hat y}^{(n)})}{1-{\hat y}^{(n)}}{\bf x}^{(n)} \right) \\ =-\frac{1}{N}\sum_{n=1}^N\left(y^{(n)}(1-{\hat y}^{(n)}){\bf x}^{(n)}-(1-y^{(n)}){\hat y}^{(n)}{\bf x}^{(n)} \right) \\ =-\frac{1}{N}\sum_{n=1}^N{\bf x}^{(n)}(y^{(n)}-{\hat y}^{(n)})

∂w∂R(w)​=−N1​n=1∑N​(y(n)y^​(n)y^​(n)(1−y^​(n))​x(n)−(1−y(n))1−y^​(n)y^​(n)(1−y^​(n))​x(n))=−N1​n=1∑N​(y(n)(1−y^​(n))x(n)−(1−y(n))y^​(n)x(n))=−N1​n=1∑N​x(n)(y(n)−y^​(n))

由此我们可以采用梯度下降法更新参数最终得到合适的参数

w

\bf w

w

python代码实现

生成数据集

我们通过下面的代码自行生成一个样本数量为100的数据集

import numpy as np
import matplotlib.pyplot as plt

# 设置随机种子,以便结果可复现
np.random.seed(42)

# 生成随机数据
# 两个特征的均值和方差
mean_1 = [2, 2]
cov_1 = [[2, 0], [0, 2]]
mean_2 = [-2, -2]
cov_2 = [[1, 0], [0, 1]]

# 生成类别1的样本
X1 = np.random.multivariate_normal(mean_1, cov_1, 50)
y1 = np.zeros(50)

# 生成类别2的样本
X2 = np.random.multivariate_normal(mean_2, cov_2, 50)
y2 = np.ones(50)

# 合并样本和标签
X = np.concatenate((X1, X2), axis=0)
y = np.concatenate((y1, y2))

# 绘制散点图
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Set1, edgecolor='k')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.title('Logistic Regression Dataset')
plt.show()

运行结果如下图所示

在这里插入图片描述

图中,类别1为右上部分,标签为0;类别2为左下部分,标签为1

不使用其他库实现

定义激活函数(标准Logistic函数即Sigmoid函数)

def sigmoid(x):
    if x>0:
        return 1.0/(1.0+np.exp(-x))
    else:
        return np.exp(x)/(1.0+np.exp(x))

定义LogisticRegression类

class LogisticRegression:
    def __init__(self, learning_rate=0.01, num_iterations=1000):
        self.learning_rate = learning_rate
        self.num_iterations = num_iterations
        self.weights = None
        self.bias = None

    def fit(self, X, y):
        num_samples, num_features = X.shape

        # 初始化权重和偏置
        self.weights = np.zeros(num_features)
        self.bias = 0

        # 梯度下降
        for _ in range(self.num_iterations):
            linear_model = np.dot(X, self.weights) + self.bias
            y_pred = sigmoid(linear_model)

            dw = (1 / num_samples) * np.dot(X.T, (y_pred - y))
            db = (1 / num_samples) * np.sum(y_pred - y)

            self.weights -= self.learning_rate * dw
            self.bias -= self.learning_rate * db

    def predict_prob(self, X):
        linear_model = np.dot(X, self.weights) + self.bias
        y_pred = sigmoid(linear_model)
        return y_pred

    def predict(self, X, threshold=0.5):
        y_pred_prob = self.predict_prob(X)
        y_pred = np.zeros_like(y_pred_prob)
        y_pred[y_pred_prob >= threshold] = 1
        return y_pred

调用LogisticRegression类解决分类问题

# 创建 Logistic 回归模型
    logreg = LogisticRegression()
    
    # 训练模型
    logreg.fit(X, y)
    
    # 预测样本
    X_new = np.array([[2.5, 2.5], [-6.0, -4.0]])
    y_pred_prob = logreg.predict_prob(X_new)
    y_pred = logreg.predict(X_new)
    
    print("Predicted Probabilities:", y_pred_prob)
    print("Predicted Labels:", y_pred)

输出结果为

在这里插入图片描述

预测样本1(2.5,2.5)位于右上部分属于类别1,真实标签为0;预测样本2(-6,-4)位于左下部分属于类别2,真实标签为1,对比输出结果可知,该分类器已训练得合适参数,可完成分类任务

使用sklearn库

我们可以通过使用sklearn库来简洁地实现LR

import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

#所使用数据集同上X,y

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建Logistic回归模型
logreg = LogisticRegression()

# 训练模型
logreg.fit(X_train, y_train)

# 预测测试集
y_pred = logreg.predict(X_test)

# 计算预测准确率
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy:", accuracy)

最终测试集上计算得到的准确率accuracy为1,可见该分类器的效果非常好

拓展

logistic回归可以用于分类非线性可分的数据。尽管logistic回归本身是一个线性分类器,但可以通过引入多项式特征、交互特征、组合特征等方法来扩展其能力,从而处理非线性的分类问题。

具体来说,可以通过特征工程的方式将原始特征进行变换,以引入非线性关系。例如,可以通过添加多项式特征,将原始特征的高阶项加入到模型中,例如原始特征的平方项、立方项等。还可以引入交互特征,将不同特征之间的乘积或分割点(例如,做差或做除)作为新的特征。

通过引入这些非线性特征,logistic回归可以更好地捕捉到数据中的非线性关系,从而能够更好地分类非线性可分的数据。需要注意的是,在引入非线性特征时,可能需要进行正则化或其他模型调优技巧,以避免过拟合问题。

本文来自网络,不代表协通编程立场,如若转载,请注明出处:https://net2asp.com/38fe320478.html