当前位置:   article > 正文

ML——逻辑回归模型_ml模型

ml模型

Table of Contents

 

1 逻辑回归模型

1.1 逻辑斯谛分布

1.2  二项逻辑斯蒂回归模型

1.3 模型参数估计

2 优化算法

3 代码实现


本博客只用于自身学习,如有错误,虚心求教!!!

1 逻辑回归模型

1.1 逻辑斯谛分布

1.2  二项逻辑斯蒂回归模型

二项逻辑斯蒂回归模型是一种分类模型,由条件概率分布P(Y|X) 表示,X取值为实数,Y取值为 1 或 0

                                                 \large P(Y=1|x)=\tfrac{exp(w\cdot x+b)}{1+exp((w\cdot x+b)}

                                                 \large P(Y=0|x)=\tfrac{1}{1+exp((w\cdot x+b)}

最终,逻辑回归会计算两者的值,将实例x分到概率值较大的那一类。有时,会将 w 和 b 合并,变为如下:

                                               \large P(Y=1|x)=\tfrac{exp(w\cdot x)}{1+exp((w\cdot x)}

                                               \large P(Y=0|x)=\tfrac{1}{1+exp((w\cdot x)}

由6.1 的分布函数图也可以看出:w\cdot x 的值越接近正无穷,概率值越接近于1,w\cdot x 的值越接近于负无穷,概率值越接近于0

多项逻辑回归模型:

                                             \large P(Y=k|x)=\tfrac{exp(w_{k}\cdot x)}{1+\sum_{k=1}^{K-1}exp(w_{k}\cdot x)}, k=1,2,...,K-1

                                            \large P(Y=k|x)=\tfrac{1}{1+\sum_{k=1}^{K-1}exp(w_{k}\cdot x)}

 

1.3 模型参数估计

2 优化算法

逻辑斯蒂回归模型归结为以似然函数为目标函数的最优化问题,通常通过迭代算法求解,常用的有:梯度下降法,牛顿法,拟牛顿法等。

此处见其他几篇博客:

梯度下降法

牛顿法和拟牛顿法

常见的几种最优化方法(梯度下降法、牛顿法、拟牛顿法、共轭梯度法等)

3 代码实现

项目案例1: 使用 Logistic 回归在简单数据集上的分类

项目案例2: 从疝气病症预测病马的死亡率

具体详见《机器学习实战》

  1. from numpy import *
  2. import matplotlib.pyplot as plt
  3. # ---------------------------------------------------------------------------
  4. # 使用 Logistic 回归在简单数据集上的分类
  5. # 解析数据
  6. def loadDataSet(file_name):
  7. '''
  8. Desc:
  9. 加载并解析数据
  10. Args:
  11. file_name -- 文件名称,要解析的文件所在磁盘位置
  12. Returns:
  13. dataMat -- 原始数据的特征
  14. labelMat -- 原始数据的标签,也就是每条样本对应的类别
  15. '''
  16. # dataMat为原始数据, labelMat为原始数据的标签
  17. dataMat = []
  18. labelMat = []
  19. fr = open(file_name)
  20. for line in fr.readlines():
  21. lineArr = line.strip().split()
  22. if len(lineArr) == 1:
  23. continue # 这里如果就一个空的元素,则跳过本次循环
  24. # 为了方便计算,我们将 X0 的值设为 1.0 ,也就是在每一行的开头添加一个 1.0 作为 X0
  25. dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
  26. labelMat.append(int(lineArr[2]))
  27. return dataMat, labelMat
  28. # sigmoid跳跃函数
  29. def sigmoid(inX):
  30. # return 1.0 / (1 + exp(-inX))
  31. # Tanh是Sigmoid的变形,与 sigmoid 不同的是,tanh 是0均值的。因此,实际应用中,tanh 会比 sigmoid 更好。
  32. return 2 * 1.0/(1+exp(-2*inX)) - 1
  33. # 正常的处理方案
  34. # 两个参数:第一个参数==> dataMatIn 是一个2维NumPy数组,每列分别代表每个不同的特征,每行则代表每个训练样本。
  35. # 第二个参数==> classLabels 是类别标签,它是一个 1*100 的行向量。为了便于矩阵计算,需要将该行向量转换为列向量,做法是将原向量转置,再将它赋值给labelMat。
  36. def gradAscent(dataMatIn, classLabels):
  37. '''
  38. Desc:
  39. 正常的梯度上升法
  40. Args:
  41. dataMatIn -- 输入的 数据的特征 List
  42. classLabels -- 输入的数据的类别标签
  43. Returns:
  44. array(weights) -- 得到的最佳回归系数
  45. '''
  46. # 转化为矩阵[[1,1,2],[1,1,2]....]
  47. dataMatrix = mat(dataMatIn) # 转换为 NumPy 矩阵
  48. # 转化为矩阵[[0,1,0,1,0,1.....]],并转制[[0],[1],[0].....]
  49. # transpose() 行列转置函数
  50. # 将行向量转化为列向量 => 矩阵的转置
  51. labelMat = mat(classLabels).transpose() # 首先将数组转换为 NumPy 矩阵,然后再将行向量转置为列向量
  52. # m->数据量,样本数 n->特征数
  53. m, n = shape(dataMatrix)
  54. # print m, n, '__'*10, shape(dataMatrix.transpose()), '__'*100
  55. # alpha代表向目标移动的步长
  56. alpha = 0.001
  57. # 迭代次数
  58. maxCycles = 500
  59. # 生成一个长度和特征数相同的矩阵,此处n为3 -> [[1],[1],[1]]
  60. # weights 代表回归系数, 此处的 ones((n,1)) 创建一个长度和特征数相同的矩阵,其中的数全部都是 1
  61. weights = ones((n, 1))
  62. for k in range(maxCycles): # heavy on matrix operations
  63. # m*3 的矩阵 * 3*1 的单位矩阵 = m*1的矩阵
  64. # 那么乘上单位矩阵的意义,就代表:通过公式得到的理论值
  65. # 参考地址: 矩阵乘法的本质是什么? https://www.zhihu.com/question/21351965/answer/31050145
  66. # print 'dataMatrix====', dataMatrix
  67. # print 'weights====', weights
  68. # n*3 * 3*1 = n*1
  69. h = sigmoid(dataMatrix * weights) # 矩阵乘法
  70. # print 'hhhhhhh====', h
  71. # labelMat是实际值
  72. error = (labelMat - h) # 向量相减
  73. # 0.001* (3*m)*(m*1) 表示在每一个列上的一个误差情况,最后得出 x1,x2,xn的系数的偏移量
  74. weights = weights + alpha * dataMatrix.transpose() * error # 矩阵乘法,最后得到回归系数
  75. return array(weights)
  76. # 随机梯度下降
  77. # 梯度下降优化算法在每次更新数据集时都需要遍历整个数据集,计算复杂都较高
  78. # 随机梯度下降一次只用一个样本点来更新回归系数
  79. def stocGradAscent0(dataMatrix, classLabels):
  80. '''
  81. Desc:
  82. 随机梯度下降,只使用一个样本点来更新回归系数
  83. Args:
  84. dataMatrix -- 输入数据的数据特征(除去最后一列)
  85. classLabels -- 输入数据的类别标签(最后一列数据)
  86. Returns:
  87. weights -- 得到的最佳回归系数
  88. '''
  89. m, n = shape(dataMatrix)
  90. alpha = 0.01
  91. # n*1的矩阵
  92. # 函数ones创建一个全1的数组
  93. weights = ones(n) # 初始化长度为n的数组,元素全部为 1
  94. for i in range(m):
  95. # sum(dataMatrix[i]*weights)为了求 f(x)的值, f(x)=a1*x1+b2*x2+..+nn*xn,此处求出的 h 是一个具体的数值,而不是一个矩阵
  96. h = sigmoid(sum(dataMatrix[i] * weights))
  97. # print 'dataMatrix[i]===', dataMatrix[i]
  98. # 计算真实类别与预测类别之间的差值,然后按照该差值调整回归系数
  99. error = classLabels[i] - h
  100. # 0.01*(1*1)*(1*n)
  101. # print weights, "*" * 10, dataMatrix[i], "*" * 10, error
  102. weights = weights + alpha * error * dataMatrix[i]
  103. return weights
  104. # 随机梯度下降算法(随机化)
  105. def stocGradAscent1(dataMatrix, classLabels, numIter=150):
  106. '''
  107. Desc:
  108. 改进版的随机梯度下降,使用随机的一个样本来更新回归系数
  109. Args:
  110. dataMatrix -- 输入数据的数据特征(除去最后一列数据)
  111. classLabels -- 输入数据的类别标签(最后一列数据)
  112. numIter=150 -- 迭代次数
  113. Returns:
  114. weights -- 得到的最佳回归系数
  115. '''
  116. m, n = shape(dataMatrix)
  117. weights = ones(n) # 创建与列数相同的矩阵的系数矩阵,所有的元素都是1
  118. # 随机梯度, 循环150,观察是否收敛
  119. for j in range(numIter):
  120. # [0, 1, 2 .. m-1]
  121. dataIndex = range(m)
  122. for i in range(m):
  123. # i和j的不断增大,导致alpha的值不断减少,但是不为0
  124. alpha = 4 / (
  125. 1.0 + j + i
  126. ) + 0.0001 # alpha 会随着迭代不断减小,但永远不会减小到0,因为后边还有一个常数项0.0001
  127. # 随机产生一个 0~len()之间的一个值
  128. # random.uniform(x, y) 方法将随机生成下一个实数,它在[x,y]范围内,x是这个范围内的最小值,y是这个范围内的最大值。
  129. randIndex = int(random.uniform(0, len(dataIndex)))
  130. # sum(dataMatrix[i]*weights)为了求 f(x)的值, f(x)=a1*x1+b2*x2+..+nn*xn
  131. h = sigmoid(sum(dataMatrix[dataIndex[randIndex]] * weights))
  132. error = classLabels[dataIndex[randIndex]] - h
  133. # print weights, '__h=%s' % h, '__'*20, alpha, '__'*20, error, '__'*20, dataMatrix[randIndex]
  134. weights = weights + alpha * error * dataMatrix[dataIndex[randIndex]]
  135. del (dataIndex[randIndex])
  136. return weights
  137. # 可视化展示
  138. def plotBestFit(dataArr, labelMat, weights):
  139. '''
  140. Desc:
  141. 将我们得到的数据可视化展示出来
  142. Args:
  143. dataArr:样本数据的特征
  144. labelMat:样本数据的类别标签,即目标变量
  145. weights:回归系数
  146. Returns:
  147. None
  148. '''
  149. n = shape(dataArr)[0]
  150. xcord1 = []
  151. ycord1 = []
  152. xcord2 = []
  153. ycord2 = []
  154. for i in range(n):
  155. if int(labelMat[i]) == 1:
  156. xcord1.append(dataArr[i, 1])
  157. ycord1.append(dataArr[i, 2])
  158. else:
  159. xcord2.append(dataArr[i, 1])
  160. ycord2.append(dataArr[i, 2])
  161. fig = plt.figure()
  162. ax = fig.add_subplot(111)
  163. ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')
  164. ax.scatter(xcord2, ycord2, s=30, c='green')
  165. x = arange(-3.0, 3.0, 0.1)
  166. """
  167. y的由来,卧槽,是不是没看懂?
  168. 首先理论上是这个样子的。
  169. dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
  170. w0*x0+w1*x1+w2*x2=f(x)
  171. x0最开始就设置为1叻, x2就是我们画图的y值,而f(x)被我们磨合误差给算到w0,w1,w2身上去了
  172. 所以: w0+w1*x+w2*y=0 => y = (-w0-w1*x)/w2
  173. """
  174. y = (-weights[0] - weights[1] * x) / weights[2]
  175. ax.plot(x, y)
  176. plt.xlabel('X')
  177. plt.ylabel('Y')
  178. plt.show()
  179. def simpleTest():
  180. # 1.收集并准备数据
  181. dataMat, labelMat = loadDataSet("data/5.Logistic/TestSet.txt")
  182. # print dataMat, '---\n', labelMat
  183. # 2.训练模型, f(x)=a1*x1+b2*x2+..+nn*xn中 (a1,b2, .., nn).T的矩阵值
  184. # 因为数组没有是复制n份, array的乘法就是乘法
  185. dataArr = array(dataMat)
  186. # print dataArr
  187. # weights = gradAscent(dataArr, labelMat)
  188. # weights = stocGradAscent0(dataArr, labelMat)
  189. weights = stocGradAscent1(dataArr, labelMat)
  190. # print '*'*30, weights
  191. # 数据可视化
  192. plotBestFit(dataArr, labelMat, weights)
  193. # --------------------------------------------------------------------------------
  194. # 从疝气病症预测病马的死亡率
  195. # 分类函数,根据回归系数和特征向量来计算 Sigmoid的值
  196. def classifyVector(inX, weights):
  197. '''
  198. Desc:
  199. 最终的分类函数,根据回归系数和特征向量来计算 Sigmoid 的值,大于0.5函数返回1,否则返回0
  200. Args:
  201. inX -- 特征向量,features
  202. weights -- 根据梯度下降/随机梯度下降 计算得到的回归系数
  203. Returns:
  204. 如果 prob 计算大于 0.5 函数返回 1
  205. 否则返回 0
  206. '''
  207. prob = sigmoid(sum(inX * weights))
  208. if prob > 0.5: return 1.0
  209. else: return 0.0
  210. # 打开测试集和训练集,并对数据进行格式化处理
  211. def colicTest():
  212. '''
  213. Desc:
  214. 打开测试集和训练集,并对数据进行格式化处理
  215. Args:
  216. None
  217. Returns:
  218. errorRate -- 分类错误率
  219. '''
  220. frTrain = open('data/5.Logistic/horseColicTraining.txt')
  221. frTest = open('data/5.Logistic/horseColicTest.txt')
  222. trainingSet = []
  223. trainingLabels = []
  224. # 解析训练数据集中的数据特征和Labels
  225. # trainingSet 中存储训练数据集的特征,trainingLabels 存储训练数据集的样本对应的分类标签
  226. for line in frTrain.readlines():
  227. currLine = line.strip().split('\t')
  228. lineArr = []
  229. for i in range(21):
  230. lineArr.append(float(currLine[i]))
  231. trainingSet.append(lineArr)
  232. trainingLabels.append(float(currLine[21]))
  233. # 使用 改进后的 随机梯度下降算法 求得在此数据集上的最佳回归系数 trainWeights
  234. trainWeights = stocGradAscent1(array(trainingSet), trainingLabels, 500)
  235. # trainWeights = stocGradAscent0(array(trainingSet), trainingLabels)
  236. errorCount = 0
  237. numTestVec = 0.0
  238. # 读取 测试数据集 进行测试,计算分类错误的样本条数和最终的错误率
  239. for line in frTest.readlines():
  240. numTestVec += 1.0
  241. currLine = line.strip().split('\t')
  242. lineArr = []
  243. for i in range(21):
  244. lineArr.append(float(currLine[i]))
  245. if int(classifyVector(array(lineArr), trainWeights)) != int(
  246. currLine[21]):
  247. errorCount += 1
  248. errorRate = (float(errorCount) / numTestVec)
  249. print("the error rate of this test is: %f" % errorRate)
  250. return errorRate
  251. # 调用 colicTest() 10次并求结果的平均值
  252. def multiTest():
  253. numTests = 10
  254. errorSum = 0.0
  255. for k in range(numTests):
  256. errorSum += colicTest()
  257. print("after %d iterations the average error rate is: %f" % (numTests, errorSum / float(numTests)))
  258. if __name__ == "__main__":
  259. simpleTest()
  260. # multiTest()

参考:

《统计学习方法》

《机器学习实战》

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号