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

2024-02-26 1129阅读

温馨提示:这篇文章已超过402天没有更新,请注意相关的内容是否还可用!

文章目录

  • 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()
          

          运行结果如下图所示

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

          图中,类别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)
          

          输出结果为

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

          预测样本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回归可以更好地捕捉到数据中的非线性关系,从而能够更好地分类非线性可分的数据。需要注意的是,在引入非线性特征时,可能需要进行正则化或其他模型调优技巧,以避免过拟合问题。

VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]