当前位置:   article > 正文

机器学习-逻辑回归_python 负二项回归

python 负二项回归

机器学习-逻辑回归

本节简单介绍逻辑回归(Logistic Regression)的原理以及Python实现,包含以下内容,

  1. 概念
  2. Sigmoid函数
  3. 最大似然估计
  4. 梯度上升算法
  5. 梯度上升算法求解J(θ)的最大θ值
  6. Python实现
  7. 随机梯度上升算法
  8. 预测

部分内容引用自《Machine Learning in Action》


概念

逻辑回归(Logistic Regression)是一种用于解决二分类问题的机器学习算法,用于估计某种事物的可能性,即存在/不存在,是/不是等问题。比如某病人患有某种疾病的可能性,某个员工是否会离职,明天是否下雨等等。 注意,这里用的是“可能性”不是数学上的“概率”,逻辑回归的结果并非数学定义中的概率值,不可以直接当做概率值来用。

逻辑回归假设数据服从伯努利分布(0-1分布),其通过最大似然估计的方法,运用梯度上升算法来求解参数,最终达到数据二分类的目的。

逻辑回归的两个假设:

1)假设数据服从伯努利分布
2)假设模型的输出值是样本为正的概率。

逻辑回归与多重线性回归实际上有很多相同之处,最大的区别就在于它们的因变量不同,其他的基本都差不多。正是因为如此,这两种回归可以归于同一个家族,即广义线性模型(generalizedlinear model)。

这一家族中的模型形式基本上都差不多,不同的就是因变量不同。

  • 如果是连续的,就是多重线性回归
  • 如果是二项分布,就是Logistic回归
  • 如果是Poisson分布,就是Poisson回归
  • 如果是负二项分布,就是负二项回归

逻辑回归的主要用途:

  • 寻找危险因素:寻找某一疾病的危险因素等
  • 预测:根据模型,预测在不同的自变量情况下,发生某病或某种情况的可能性
  • 判别:实际上跟预测有些类似,也是根据模型,判断某人属于某病或属于某种情况的概率有多大,也就是看一下这个人有多大的可能性是属于某病

逻辑回归主要在流行病学中应用较多,比较常用的情形是探索某疾病的危险因素,根据危险因素预测某疾病发生的概率,等等。例如,想探讨胃癌发生的危险因素,可以选择两组人群,一组是胃癌组,一组是非胃癌组,两组人群肯定有不同的体征和生活方式等。这里的因变量就是是否胃癌,即“是”或“否”,自变量就可以包括很多了,例如年龄、性别、饮食习惯、幽门螺杆菌感染等。自变量既可以是连续的,也可以是分类的。

Sigmoid函数

Sigmoid函数又叫激活函数,其函数表达式如下:

函数图像:

可知其定义域为全体实数,值域为(0, 1),Sigmoid函数的作用是将任何实数映射到(0, 1)。

逻辑回归的假设函数如下:

即,

其中,x是输入,即特征值,θ是待求的回归系数。(使用此激活函数来拟合样本空间中的样本点,即,样本空间中的样本点都有一个真实的类别,通过寻找一个激活函数,该激活函数能够很好的计算(拟合)样本空间中的样本值。)

因为Sigmoid函数的值域是(0,1],所以其在二分类问题上很适用。

逻辑回归要求我们根据一系列的学习样本(即上面公式中的x,多维矩阵)得到一个θ向量,然后来预测新的元素分类。

最大似然估计

逻辑回归采用最大似然估计来作为其损失函数(这部分参考自:Logistic回归基础篇之梯度上升算法):

注:如果采用常见的误差平方和来当做损失函数,即如下函数,

这是一个非凸函数,这就意味着损失函数有着许多的局部最小值,不利于求解(参考:逻辑回归与最大似然估计推导_逻辑回归极大似然估计推导-CSDN博客)。所以,逻辑回归中使用的是最大最大似然估计来作为其损失函数。

根据sigmoid函数的特性,我们可以做出如下的假设:

Image

上式即为在已知样本x和参数θ的情况下,样本x属性正样本(y=1)和负样本(y=0)的条件概率。理想状态下,根据上述公式,求出各个点的概率均为1,也就是完全分类都正确。但是考虑到实际情况,样本点的概率越接近于1,其分类效果越好。比如一个样本属于正样本的概率为0.51,那么我们就可以说明这个样本属于正样本。另一个样本属于正样本的概率为0.99,那么我们也可以说明这个样本属于正样本。但是显然,第二个样本概率更高,更具说服力。我们可以把上述两个概率公式合二为一:

Image

合并出来的Cost,我们称之为代价函数(Cost Function)。当y等于1时,(1-y)项(第二项)为0;当y等于0时,y项(第一项)为0。为了简化问题,我们对整个表达式求对数,(将指数问题对数化是处理数学问题常见的方法):

Image

这个代价函数,是对于一个样本而言的。给定一个样本,我们就可以通过这个代价函数求出,样本所属类别的概率,而这个概率越大越好,所以也就是求解这个代价函数的最大值。既然概率出来了,那么最大似然估计也该出场了。假定样本与样本之间相互独立,那么整个样本集生成的概率即为所有样本生成概率的乘积,再将公式对数化,便可得到如下代价函数公式:

Image

其中,m为样本的总数,y(i)表示第i个样本的类别,x(i)表示第i个样本,需要注意的是θ是多维向量,x(i)也是多维向量。

综上所述,满足J(θ)的最大的θ值即是我们需要求解的模型。(求解θ,使得该θ可以让样本空间中的样本点出现其真实类别的概率最大,后验概率。

怎么求解使J(θ)最大的θ值呢?因为是求最大值,所以我们需要使用梯度上升算法。如果面对的问题是求解使J(θ)最小的θ值,那么我们就需要使用梯度下降算法。面对我们这个问题,如果使J(θ) := -J(θ),那么问题就从求极大值转换成求极小值了,使用的算法就从梯度上升算法变成了梯度下降算法,它们的思想都是相同的,学会其一,就也会了另一个。本文使用梯度上升算法进行求解。

梯度上升算法

梯度上升算法用于求解函数的最大值,梯度下降算法用于求解函数的最小值,其原理都一样。因为逻辑回归中求解的是某个元素属于某个分类的最大可能性,求解的是最大值,因此需要使用梯度上升算法。公式:

其中,α是步长,f(Xi))Xi是梯度,也就是偏导数组成的向量,表示X应该沿此方向运动方能取到最大值。下面举一个实例,

求以下函数的最大值:

f(x)=x2+2x+2

函数图像:

可知,当x=1时取最大值为y=3

下面通过Python实现梯度上升算法,

  1. import math
  2. def f(x):
  3. return -x * x + 2 * x + 2
  4. def ff(x):
  5. return -2 * x + 2
  6. def gradient_ascent(x_0=1, steps=0.1):
  7. while True:
  8. x_1 = x_0 + ff(x_0) * steps
  9. if math.fabs(x_0 - x_1) <= 0.000001:
  10. return x_1
  11. x_0 = x_1
  12. x = gradient_ascent(-1)
  13. print("Max value x: %r" % x)
  14. print("Max value y: %r" % f(x))

 运行结果:

  1. D:\work\python_workspace\machine_learning\venv\Scripts\python.exe D:/work/python_workspace/machine_learning/logistic_regression/gradient_ascent.py
  2. Max value x: 0.9999961687611478
  3. Max value y: 2.9999999999853215
  4. Process finished with exit code 0

使用梯度上升算法求解J(θ)的最大θ值

由上小节可知J(θ)为:

Image

sigmoid函数为:

Image

那么,现在我只要求出J(θ)的偏导,就可以利用梯度上升算法,求解J(θ)的极大值了。

那么现在开始求解J(θ)对θ的偏导,求解如下(数学推导):

Image

Image

其中,\alpha是步长系数,可以是0.1,0.01,0.001等;y^{(i)}是原始样本的类别值,可以是0,1等,通过原始数据集直接得到;h_{\theta }(x^{(i)})表示通过Sigmoid函数在当前\theta场景下计算出来的估计值;xj(i)表示原始样本的特征值,通过原始数据集直接得到。

知道了,梯度上升迭代公式,我们就可以自己编写代码,计算最佳拟合参数了。

Python实现

数据集文件:test_set.txt,

  1. -0.017612 14.053064 0
  2. -1.395634 4.662541 1
  3. -0.752157 6.538620 0
  4. -1.322371 7.152853 0
  5. 0.423363 11.054677 0
  6. 0.406704 7.067335 1
  7. 0.667394 12.741452 0
  8. -2.460150 6.866805 1
  9. 0.569411 9.548755 0
  10. -0.026632 10.427743 0
  11. 0.850433 6.920334 1
  12. 1.347183 13.175500 0
  13. 1.176813 3.167020 1
  14. -1.781871 9.097953 0
  15. -0.566606 5.749003 1
  16. 0.931635 1.589505 1
  17. -0.024205 6.151823 1
  18. -0.036453 2.690988 1
  19. -0.196949 0.444165 1
  20. 1.014459 5.754399 1
  21. 1.985298 3.230619 1
  22. -1.693453 -0.557540 1
  23. -0.576525 11.778922 0
  24. -0.346811 -1.678730 1
  25. -2.124484 2.672471 1
  26. 1.217916 9.597015 0
  27. -0.733928 9.098687 0
  28. -3.642001 -1.618087 1
  29. 0.315985 3.523953 1
  30. 1.416614 9.619232 0
  31. -0.386323 3.989286 1
  32. 0.556921 8.294984 1
  33. 1.224863 11.587360 0
  34. -1.347803 -2.406051 1
  35. 1.196604 4.951851 1
  36. 0.275221 9.543647 0
  37. 0.470575 9.332488 0
  38. -1.889567 9.542662 0
  39. -1.527893 12.150579 0
  40. -1.185247 11.309318 0
  41. -0.445678 3.297303 1
  42. 1.042222 6.105155 1
  43. -0.618787 10.320986 0
  44. 1.152083 0.548467 1
  45. 0.828534 2.676045 1
  46. -1.237728 10.549033 0
  47. -0.683565 -2.166125 1
  48. 0.229456 5.921938 1
  49. -0.959885 11.555336 0
  50. 0.492911 10.993324 0
  51. 0.184992 8.721488 0
  52. -0.355715 10.325976 0
  53. -0.397822 8.058397 0
  54. 0.824839 13.730343 0
  55. 1.507278 5.027866 1
  56. 0.099671 6.835839 1
  57. -0.344008 10.717485 0
  58. 1.785928 7.718645 1
  59. -0.918801 11.560217 0
  60. -0.364009 4.747300 1
  61. -0.841722 4.119083 1
  62. 0.490426 1.960539 1
  63. -0.007194 9.075792 0
  64. 0.356107 12.447863 0
  65. 0.342578 12.281162 0
  66. -0.810823 -1.466018 1
  67. 2.530777 6.476801 1
  68. 1.296683 11.607559 0
  69. 0.475487 12.040035 0
  70. -0.783277 11.009725 0
  71. 0.074798 11.023650 0
  72. -1.337472 0.468339 1
  73. -0.102781 13.763651 0
  74. -0.147324 2.874846 1
  75. 0.518389 9.887035 0
  76. 1.015399 7.571882 0
  77. -1.658086 -0.027255 1
  78. 1.319944 2.171228 1
  79. 2.056216 5.019981 1
  80. -0.851633 4.375691 1
  81. -1.510047 6.061992 0
  82. -1.076637 -3.181888 1
  83. 1.821096 10.283990 0
  84. 3.010150 8.401766 1
  85. -1.099458 1.688274 1
  86. -0.834872 -1.733869 1
  87. -0.846637 3.849075 1
  88. 1.400102 12.628781 0
  89. 1.752842 5.468166 1
  90. 0.078557 0.059736 1
  91. 0.089392 -0.715300 1
  92. 1.825662 12.693808 0
  93. 0.197445 9.744638 0
  94. 0.126117 0.922311 1
  95. -0.679797 1.220530 1
  96. 0.677983 2.556666 1
  97. 0.761349 10.693862 0
  98. -2.168791 0.143632 1
  99. 1.388610 9.341997 0
  100. 0.317029 14.739025 0

创建模块 log_regres.py,并输入以下代码:

  1. import numpy as np
  2. def load_data():
  3. data_mat = []
  4. label_mat = []
  5. with open('test_set.txt') as f:
  6. for line in f.readlines():
  7. line_array = line.strip().split()
  8. data_mat.append([1.0, float(line_array[0]), float(line_array[1])])
  9. label_mat.append(int(line_array[2]))
  10. return data_mat, label_mat
  11. def sigmoid(in_X):
  12. return 1.0 / (1 + np.exp(-in_X))
  13. def grad_ascent(data_mat_in, class_labels):
  14. data_matrix = np.mat(data_mat_in)
  15. label_mat = np.mat(class_labels).transpose()
  16. m, n = np.shape(data_matrix)
  17. alpha = 0.001
  18. max_cycles = 500
  19. weights = np.ones((n, 1))
  20. for k in range(max_cycles):
  21. h = sigmoid(data_matrix * weights)
  22. error = label_mat - h
  23. weights = weights + alpha * data_matrix.transpose() * error
  24. return weights
  25. if __name__ == '__main__':
  26. data, label = load_data()
  27. weight = grad_ascent(data, label)
  28. print(weight)

注意下面几行代码,就是通过梯度上升算法得到的公式的具体实现,

  1. h = sigmoid(data_matrix * weights)
  2. error = label_mat - h
  3. weights = weights + alpha * data_matrix.transpose() * error

输出结果:

  1. D:\work\python_workspace\machine_learning\venv\Scripts\python.exe D:/work/python_workspace/machine_learning/logistic_regression/log_regres.py
  2. [[ 4.12414349]
  3. [ 0.48007329]
  4. [-0.6168482 ]]
  5. Process finished with exit code 0

因此,该逻辑回归的决策函数为:

z=4.12414349+0.48007329x10.6168482x2

下面我们根据该决策函数画出决策边界,创建模块 plot_best_fit.py,并输入以下代码:

  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. import logistic_regression.log_regres as lr
  4. def plot_best_fit(weights):
  5. data, label = lr.load_data()
  6. data_array = np.array(data)
  7. n = np.shape(data_array)[0]
  8. xcord1 = []
  9. ycord1 = []
  10. xcord2 = []
  11. ycord2 = []
  12. for i in range(n):
  13. if int(label[i]) == 1:
  14. xcord1.append(data_array[i, 1])
  15. ycord1.append(data_array[i, 2])
  16. else:
  17. xcord2.append(data_array[i, 1])
  18. ycord2.append(data_array[i, 2])
  19. fig = plt.figure()
  20. ax = fig.add_subplot(111)
  21. ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')
  22. ax.scatter(xcord2, ycord2, s=30, c='green')
  23. x = np.arange(-3.0, 3.0, 0.1)
  24. y = (-weights[0] - weights[1] * x) / weights[2]
  25. ax.plot(x, np.array(y)[0])
  26. plt.xlabel('X1')
  27. plt.ylabel('X2')
  28. plt.show()
  29. if __name__ == '__main__':
  30. data, label = lr.load_data()
  31. weights = lr.grad_ascent(data, label)
  32. plot_best_fit(weights)

运行结果:

注意,假设以0.5为决策阈值,通过Sigmoid可知z的值为0,可得到x1x2的以下关系式,

x2=4.12414349+0.48007329x10.6168482

这就是该示例的决策边界函数。

随机梯度上升算法

上面的梯度算法需要进行大量的计算,在样本点和特征值很多的情况下会有一定的性能问题,我们可以通过随机梯度算法进行优化。随机梯度算法和一般梯度算法类似,只是每次计算时是随机的从样本中选取一个样本点,而不是像一般梯度算法中每次迭代时把所有样本点都计算一次。且随机梯度算法每次迭代时都要逐渐减小步长。

创建模块 stoc_grad_ascent1.py,并输入以下代码:

  1. import numpy as np
  2. import random
  3. import matplotlib.pyplot as plt
  4. import logistic_regression.log_regres as lr
  5. import logistic_regression.plot_best_fit as pf
  6. def stoc_grad_ascent1(data_matrix, class_label, num_iter=150):
  7. m, n = np.shape(data_matrix)
  8. weights = np.ones(n)
  9. for j in range(num_iter):
  10. data_index = list(range(m))
  11. for i in range(m):
  12. alpha = 4 / (1.0 + j + i) + 0.01
  13. rand_index = int(random.uniform(0, len(data_index)))
  14. h = lr.sigmoid(np.sum(data_matrix[rand_index] * weights))
  15. error = class_label[rand_index] - h
  16. weights = weights + alpha * error * data_matrix[rand_index]
  17. del (data_index[rand_index])
  18. return weights
  19. def plot_best_fit(weights):
  20. data, label = lr.load_data()
  21. data_array = np.array(data)
  22. n = np.shape(data_array)[0]
  23. xcord1 = []
  24. ycord1 = []
  25. xcord2 = []
  26. ycord2 = []
  27. for i in range(n):
  28. if int(label[i]) == 1:
  29. xcord1.append(data_array[i, 1])
  30. ycord1.append(data_array[i, 2])
  31. else:
  32. xcord2.append(data_array[i, 1])
  33. ycord2.append(data_array[i, 2])
  34. fig = plt.figure()
  35. ax = fig.add_subplot(111)
  36. ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')
  37. ax.scatter(xcord2, ycord2, s=30, c='green')
  38. x = np.arange(-3.0, 3.0, 0.1)
  39. y = (-weights[0] - weights[1] * x) / weights[2]
  40. ax.plot(x, y)
  41. plt.xlabel('X1')
  42. plt.ylabel('X2')
  43. plt.show()
  44. if __name__ == '__main__':
  45. data_arr, label_mat = lr.load_data()
  46. weights = stoc_grad_ascent1(np.array(data_arr), label_mat)
  47. print(weights)
  48. plot_best_fit(weights)

运行结果:

  1. D:\work\python_workspace\machine_learning\venv\Scripts\python.exe D:/work/python_workspace/machine_learning/logistic_regression/stoc_grad_ascent1.py
  2. [13.66512034 0.9332941 -2.05701081]
  3. Process finished with exit code 0

图像:

预测

一旦得到θ向量,我们就可以得到逻辑回归的假设函数的准确表达式,

将目标变量的特征值带入到此表达式,得到hθ(x)的值,再通过设定阈值(比如0.5)的判断,即可得到目标变量所属的类别。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/475786
推荐阅读
相关标签
  

闽ICP备14008679号