欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

机器学习——线性回归

程序员文章站 2022-05-02 14:03:27
...

参考:
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

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

# !/usr/bin/python
# -*- coding: utf-8 -*- 
# @Time : 2020/1/6 16:26 
# @Author : ljf
# @File : LOG_test1.py


def f_prime(x_old):  # f(x)的导数
    return -2 * x_old + 4


def Gradient_Ascent_test():
    """
    函数说明:梯度上升算法测试函数
    求函数f(x) = -x^2 + 4x的极大值
    Returns:
        无
    """
    x_old = -1  # 初始值,给一个小于x_new的值
    x_new = 0  # 梯度上升算法初始值,即从(0,0)开始
    alpha = 0.01  # 步长,也就是学习速率,控制更新的幅度
    presision = 0.00000001  # 精度,也就是更新阈值
    while abs(x_new - x_old) > presision:
        x_old = x_new
        x_new = x_old + alpha * f_prime(x_old)  # 上面提到的公式
    print(x_new)  # 打印最终求解的极值近似值


if __name__ == '__main__':
    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、代码

# !/usr/bin/python
# -*- coding: utf-8 -*- 
# @Time : 2020/1/6 21:17 
# @Author : ljf
# @File : LOG_test5.py
from matplotlib.font_manager import FontProperties
import matplotlib.pyplot as plt
import numpy as np
import random


def loadDataSet():
    """
    函数说明:加载数据
    Returns:
        dataMat:    数据列表
        labelMat:   标签列表
    """
    dataMat = []  # 创建数据列表
    labelMat = []  # 创建标签列表
    fr = open('testSet.txt')  # 打开文件
    for line in fr.readlines():  # 逐行读取
        lineArr = line.strip().split()  # 去回车,放入列表
        dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])  # 添加数据
        labelMat.append(int(lineArr[2]))  # 添加标签
    fr.close()  # 关闭文件
    return dataMat, labelMat  # 返回


def sigmoid(inX):
    """
    函数说明:sigmoid函数
    Args:
        inX: 数据
    Returns:
        sigmoid函数
    """
    return 1.0 / (1 + np.exp(-inX))


def gradAscent(dataMatIn, classLabels):
    """
    函数说明:梯度上升算法
    Args:
        dataMatIn:      数据集
        classLabels:    数据标签
    Returns:
        weights.getA(): 求得的权重数组(最优参数)
    """
    dataMatrix = np.mat(dataMatIn)  # 转换成numpy的mat
    labelMat = np.mat(classLabels).transpose()  # 转换成numpy的mat,并进行转置
    m, n = np.shape(dataMatrix)  # 返回dataMatrix的大小。m为行数,n为列数。
    alpha = 0.001  # 移动步长,也就是学习速率,控制更新的幅度。
    maxCycles = 500  # 最大迭代次数
    weights = np.ones((n, 1))
    for k in range(maxCycles):
        h = sigmoid(dataMatrix * weights)  # 梯度上升矢量化公式
        error = labelMat - h
        weights = weights + alpha * dataMatrix.transpose() * error
    return weights.getA()  # 将矩阵转换为数组,返回权重数组


def plotBestFit(weights):
    """
    函数说明:绘制数据集
    Args:
        weights:    权重参数数组
    Returns:
        无
    """
    dataMat, labelMat = loadDataSet()  # 加载数据集
    dataArr = np.array(dataMat)  # 转换成numpy的array数组
    n = np.shape(dataMat)[0]  # 数据个数
    xcord1 = []
    ycord1 = []  # 正样本
    xcord2 = []
    ycord2 = []  # 负样本
    for i in range(n):  # 根据数据集标签进行分类
        if int(labelMat[i]) == 1:
            xcord1.append(dataArr[i, 1])
            ycord1.append(dataArr[i, 2])  # 1为正样本
        else:
            xcord2.append(dataArr[i, 1])
            ycord2.append(dataArr[i, 2])  # 0为负样本
    fig = plt.figure()
    ax = fig.add_subplot(111)  # 添加subplot
    ax.scatter(xcord1, ycord1, s=20, c='red', marker='s', alpha=.5)  # 绘制正样本
    ax.scatter(xcord2, ycord2, s=20, c='green', alpha=.5)  # 绘制负样本
    x = np.arange(-3.0, 3.0, 0.1)
    y = (-weights[0] - weights[1] * x) / weights[2]
    ax.plot(x, y)
    plt.title('BestFit')  # 绘制title
    plt.xlabel('X1')
    plt.ylabel('X2')  # 绘制label
    plt.show()


def stocGradAscent1(dataMatrix, classLabels, numIter=150):
    """
    函数说明:改进的随机梯度上升算法
    Args:
        dataMatrix:     数据数组
        classLabels:    数据标签
        numIter:        迭代次数
    Returns:
        weights:        求得的回归系数数组(最优参数)
    """
    m, n = np.shape(dataMatrix)  # 返回dataMatrix的大小。m为行数,n为列数。
    weights = np.ones(n)  # 参数初始化
    for j in range(numIter):
        dataIndex = list(range(m))
        for i in range(m):
            alpha = 4 / (1.0 + j + i) + 0.01  # 降低alpha的大小,每次减小1/(j+i)。
            randIndex = int(random.uniform(0, len(dataIndex)))  # 随机选取样本
            h = sigmoid(sum(dataMatrix[dataIndex[randIndex]] * weights))  # 选择随机选取的一个样本,计算h
            error = classLabels[dataIndex[randIndex]] - h  # 计算误差
            weights = weights + alpha * error * dataMatrix[dataIndex[randIndex]]  # 更新回归系数
            del (dataIndex[randIndex])  # 删除已经使用的样本
    return weights  # 返回


if __name__ == '__main__':
    dataMat, labelMat = loadDataSet()
    weights = stocGradAscent1(np.array(dataMat), labelMat)
    print(weights)
    plotBestFit(weights)

三、总结

3.1、Logistic回归的一般过程

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

3.2、重要

梯度上升迭代公式

相关标签: 机器学习