机器学习——线性回归

雨点打透心脏的1/2处 2023-07-03 02:46 82阅读 0赞

参考:
https://cuijiahua.com/blog/2017/11/ml\_6\_logistic\_1.html
https://cuijiahua.com/blog/2017/11/ml\_7\_logistic\_2.html

一、线性回归前置简介

1.1、Sigmoid函数

在这里插入图片描述
在这里插入图片描述
优点

  1. Sigmoid函数的输出映射在(0,1)之间,单调连续,输出范围有限,优化稳定,可以用作输出层。
  2. 求导容易。

缺点

  1. 由于其软饱和性,容易产生梯度消失,导致训练出现问题。
  2. 其输出并不是以0为中心的。

这 Sigmoid 函数作为激活函数,x 可以代表很多参数,例如:单个数字、矩阵
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
则 Sigmoid 函数就如下图所示:
在这里插入图片描述
其中:z是一个矩阵,θ是参数列向量(要求解的),x是样本列向量(给定的数据集)。θ^T表示θ的转置。

1.2、损失函数

根据sigmoid函数的特性,我们可以做出如下的假设:
在这里插入图片描述
在已知样本x和参数θ的情况下,样本x属性正样本(y=1)和负样本(y=0)的条件概率。理想状态下,根据上述公式,求出各个点的概率均为1,也就是完全分类都正确。

但是考虑到实际情况,样本点的概率越接近于1,其分类效果越好。比如一个样本属于正样本的概率为0.51,那么我们就可以说明这个样本属于正样本。另一个样本属于正样本的概率为0.99,那么我们也可以说明这个样本属于正样本。但是显然,第二个样本概率更高,更具说服力。我们可以把上述两个概率公式合二为一:
在这里插入图片描述
合并出来的Loss,我们称之为损失函数(Loss Function)。当y等于1时,(1-y)项(第二项)为0;当y等于0时,y项(第一项)为0。

为s了简化问题,我们对整个表达式求对数,(将指数问题对数化是处理数学问题常见的方法):
在这里插入图片描述
这个损失函数,是对于一个样本而言的。给定一个样本,我们就可以通过这个损失函数求出,样本所属类别的概率,而这个概率越大越好,所以也就是求解这个损失函数的最大值。既然概率出来了,那么最大似然估计也该出场了。假定样本与样本之间相互独立,那么整个样本集生成的概率即为所有样本生成概率的乘积,再将公式对数化,便可得到如下公式:
在这里插入图片描述
其中,m为样本的总数,y(i)表示第i个样本的类别,x(i)表示第i个样本,需要注意的是θ是多维向量,x(i)也是多维向量。

1.3、梯度上升算法

在这里插入图片描述

在我们用数学求解时,自然使用到求导 f’(x)=-2x+4,然后使其等于0,我们就可以得到最大值时的 x=2

但是真实环境中的函数不会像上面这么简单,就算求出了函数的导数,也很难精确计算出函数的极值。此时我们就可以用迭代的方法来做。就像爬坡一样,一点一点逼近极值。这种寻找最佳拟合参数的方法,就是最优化算法。爬坡这个动作用数学公式表达即为:
在这里插入图片描述
在这里插入图片描述编程实现:

  1. # !/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. # @Time : 2020/1/6 16:26
  4. # @Author : ljf
  5. # @File : LOG_test1.py
  6. def f_prime(x_old): # f(x)的导数
  7. return -2 * x_old + 4
  8. def Gradient_Ascent_test():
  9. """
  10. 函数说明:梯度上升算法测试函数
  11. 求函数f(x) = -x^2 + 4x的极大值
  12. Returns:
  13. """
  14. x_old = -1 # 初始值,给一个小于x_new的值
  15. x_new = 0 # 梯度上升算法初始值,即从(0,0)开始
  16. alpha = 0.01 # 步长,也就是学习速率,控制更新的幅度
  17. presision = 0.00000001 # 精度,也就是更新阈值
  18. while abs(x_new - x_old) > presision:
  19. x_old = x_new
  20. x_new = x_old + alpha * f_prime(x_old) # 上面提到的公式
  21. print(x_new) # 打印最终求解的极值近似值
  22. if __name__ == '__main__':
  23. Gradient_Ascent_test()

1.4、J(θ)的求导

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

最后就是梯度上升迭代公式。

二、示例

示例就是把两种点用直线分类,求这条直线。
在这里插入图片描述

1、数据准备

https://github.com/Jack-Cherish/Machine-Learning/blob/master/Logistic/testSet.txt

2、步骤

把数据文件下载下来。

  1. 加载数据,并初步处理
  2. 利用梯度上升迭代公式计算出每一列的权重
  3. 根据每列权重画出直线

3、改进

因为这个梯度上升迭代公式,每次修改权重时,必须每次全部遍历,这样就会耗费很多时间和资源。
所以有了改进,每次修改随机挑取一个向量进行计算。

4、代码

  1. # !/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. # @Time : 2020/1/6 21:17
  4. # @Author : ljf
  5. # @File : LOG_test5.py
  6. from matplotlib.font_manager import FontProperties
  7. import matplotlib.pyplot as plt
  8. import numpy as np
  9. import random
  10. def loadDataSet():
  11. """
  12. 函数说明:加载数据
  13. Returns:
  14. dataMat: 数据列表
  15. labelMat: 标签列表
  16. """
  17. dataMat = [] # 创建数据列表
  18. labelMat = [] # 创建标签列表
  19. fr = open('testSet.txt') # 打开文件
  20. for line in fr.readlines(): # 逐行读取
  21. lineArr = line.strip().split() # 去回车,放入列表
  22. dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])]) # 添加数据
  23. labelMat.append(int(lineArr[2])) # 添加标签
  24. fr.close() # 关闭文件
  25. return dataMat, labelMat # 返回
  26. def sigmoid(inX):
  27. """
  28. 函数说明:sigmoid函数
  29. Args:
  30. inX: 数据
  31. Returns:
  32. sigmoid函数
  33. """
  34. return 1.0 / (1 + np.exp(-inX))
  35. def gradAscent(dataMatIn, classLabels):
  36. """
  37. 函数说明:梯度上升算法
  38. Args:
  39. dataMatIn: 数据集
  40. classLabels: 数据标签
  41. Returns:
  42. weights.getA(): 求得的权重数组(最优参数)
  43. """
  44. dataMatrix = np.mat(dataMatIn) # 转换成numpy的mat
  45. labelMat = np.mat(classLabels).transpose() # 转换成numpy的mat,并进行转置
  46. m, n = np.shape(dataMatrix) # 返回dataMatrix的大小。m为行数,n为列数。
  47. alpha = 0.001 # 移动步长,也就是学习速率,控制更新的幅度。
  48. maxCycles = 500 # 最大迭代次数
  49. weights = np.ones((n, 1))
  50. for k in range(maxCycles):
  51. h = sigmoid(dataMatrix * weights) # 梯度上升矢量化公式
  52. error = labelMat - h
  53. weights = weights + alpha * dataMatrix.transpose() * error
  54. return weights.getA() # 将矩阵转换为数组,返回权重数组
  55. def plotBestFit(weights):
  56. """
  57. 函数说明:绘制数据集
  58. Args:
  59. weights: 权重参数数组
  60. Returns:
  61. """
  62. dataMat, labelMat = loadDataSet() # 加载数据集
  63. dataArr = np.array(dataMat) # 转换成numpy的array数组
  64. n = np.shape(dataMat)[0] # 数据个数
  65. xcord1 = []
  66. ycord1 = [] # 正样本
  67. xcord2 = []
  68. ycord2 = [] # 负样本
  69. for i in range(n): # 根据数据集标签进行分类
  70. if int(labelMat[i]) == 1:
  71. xcord1.append(dataArr[i, 1])
  72. ycord1.append(dataArr[i, 2]) # 1为正样本
  73. else:
  74. xcord2.append(dataArr[i, 1])
  75. ycord2.append(dataArr[i, 2]) # 0为负样本
  76. fig = plt.figure()
  77. ax = fig.add_subplot(111) # 添加subplot
  78. ax.scatter(xcord1, ycord1, s=20, c='red', marker='s', alpha=.5) # 绘制正样本
  79. ax.scatter(xcord2, ycord2, s=20, c='green', alpha=.5) # 绘制负样本
  80. x = np.arange(-3.0, 3.0, 0.1)
  81. y = (-weights[0] - weights[1] * x) / weights[2]
  82. ax.plot(x, y)
  83. plt.title('BestFit') # 绘制title
  84. plt.xlabel('X1')
  85. plt.ylabel('X2') # 绘制label
  86. plt.show()
  87. def stocGradAscent1(dataMatrix, classLabels, numIter=150):
  88. """
  89. 函数说明:改进的随机梯度上升算法
  90. Args:
  91. dataMatrix: 数据数组
  92. classLabels: 数据标签
  93. numIter: 迭代次数
  94. Returns:
  95. weights: 求得的回归系数数组(最优参数)
  96. """
  97. m, n = np.shape(dataMatrix) # 返回dataMatrix的大小。m为行数,n为列数。
  98. weights = np.ones(n) # 参数初始化
  99. for j in range(numIter):
  100. dataIndex = list(range(m))
  101. for i in range(m):
  102. alpha = 4 / (1.0 + j + i) + 0.01 # 降低alpha的大小,每次减小1/(j+i)。
  103. randIndex = int(random.uniform(0, len(dataIndex))) # 随机选取样本
  104. h = sigmoid(sum(dataMatrix[dataIndex[randIndex]] * weights)) # 选择随机选取的一个样本,计算h
  105. error = classLabels[dataIndex[randIndex]] - h # 计算误差
  106. weights = weights + alpha * error * dataMatrix[dataIndex[randIndex]] # 更新回归系数
  107. del (dataIndex[randIndex]) # 删除已经使用的样本
  108. return weights # 返回
  109. if __name__ == '__main__':
  110. dataMat, labelMat = loadDataSet()
  111. weights = stocGradAscent1(np.array(dataMat), labelMat)
  112. print(weights)
  113. plotBestFit(weights)

三、总结

3.1、Logistic回归的一般过程

  • 收集数据:采用任意方法收集数据。
  • 准备数据:由于需要进行距离计算,因此要求数据类型为数值型。另外,结构化数据格式则最佳。
  • 分析数据:采用任意方法对数据进行分析。
  • 训练算法:大部分时间将用于训练,训练的目的是为了找到最佳的分类回归系数。
  • 测试算法:一旦训练步骤完成,分类将会很快。
  • 使用算法:首先,我们需要输入一些数据,并将其转换成对应的结构化数值;接着,基于训练好的回归系数,就可以对这些数值进行简单的回归计算,判定它们属于哪个类别;在这之后,我们就可以在输出的类别上做一些其他分析工作。

3.2、重要

梯度上升迭代公式

发表评论

表情:
评论列表 (有 0 条评论,82人围观)

还没有评论,来说两句吧...

相关阅读

    相关 机器学习 --- 线性回归

    线性回归是属于机器学习里面的监督学习,与分类问题不同的是,在回归问题中,其目标是通过对训练样本的学习,得到从样本特征到样本标签直接的映射,其中,在回归问题中,样本的标签是连续值

    相关 机器学习线性回归

    花了2天时间看了吴恩达老师的机器学习算法的第一章,收获很多,在网易云课堂上可看,虽然是英文版的,且偏向于理论,故在此记录下学习收获和代码实现。 1.y=kx+b的线性回归

    相关 机器学习线性回归

    单变量线性回归 说到机器学习的话,很多人首先会想到的是单变量的线性回归,好像大家高中的时候都学过。很多人不理解,这种线性回归的东西跟机器学习有什么关系。 其实单变量的话

    相关 机器学习_线性回归

    这学期打算把机器学习和深度学习 什么是回归算法 1. 回归算法是一种有监督算法(有一个x和y的对应关系) 2. 回归算法是一种比较常用的机器学习算法,用来建立“解释