机器学习——Logistic回归

目录

简介

Logistic回归

什么是Logistic回归

基于Logistic回归和Sigmoid函数的分类 

基于最优化方法的最佳回归系数确定

梯度上升法

普通梯度上升算法实现

随机梯度上升算法实现

完整代码

总结


简介

机器学习的回归(Regression)和分类(Classification)是两种常见的预测任务,它们在目标和方法上有一些关键区别:

回归和分类是机器学习中的两种主要任务,它们的主要区别在于预测的目标不同。

回归(Regression)通常处理的是数值预测问题,目标是最小化预测值和实际观测值之间的平方差。例如,房价预测就是一个回归问题,目标是通过考虑多种影响房价的因素(如房屋面积、位置、装修等),预测房价。回归的目标是找到一个模型,使得这个模型能够最好地预测数值变量(如房价)的变化。

另一方面,分类(Classification)则是将输入数据分为预定义的类别。例如,垃圾邮件检测就是一个分类问题,目标是训练一个模型,使得模型能够根据邮件的内容自动判断出哪些邮件是垃圾邮件,哪些不是。分类的目标是找到一个模型,使得这个模型能够将输入数据(在这种情况下是邮件)映射到预定义的类别(在这种情况下是垃圾邮件或非垃圾邮件)。

因此,回归和分类的主要区别在于,回归任务中目标变量是连续的数值,而分类任务中目标变量则是离散的类别。这两种任务都需要通过机器学习算法来从输入数据中学习到有用的模式,并利用这些模式来做出预测或决策。但是,不同类型的算法在处理不同任务时可能表现得更好,所以理解回归和分类之间的差异是很重要的。

Logistic回归

什么是Logistic回归

Logistic回归是一种用于分类问题的机器学习算法,它的主要优势在于可以同时处理多个预测变量(称为特征)和类别标签。这种方法使用线性回归模型,通过逻辑函数将预测变量的线性组合转换为预测样本属于某个类别的概率。在应用Logistic回归时,我们通常会将每个特征与类别标签之间的对应关系建模为模型参数,这样当新的数据输入模型时,它就能基于这些参数计算出预测样本属于每个类别的概率。

具体来说,在Logistic回归中,每个特征都在模型的权重向量中被加权并求和。对于输入的每个特征向量x和类别向量y,模型的输出可以表示为逻辑函数的输入:模型参数经过输入的特征向量,最后返回一个概率值(在[0, 1]范围内),该概率表示输入数据属于类别y的概率。这个概率值的输出方式有助于更有效地将多个预测变量和类别之间的对应关系联系起来。

由于Logistic回归可以通过调整模型参数来最大化预测的准确性,因此在解决二分类问题时,它通常是一个非常有效的工具。此外,如果需要对多个类别进行分类,Logistic回归也可以轻松扩展到多分类问题中。不过,由于Logistic回归将原始数据的分类标签映射到概率值上,这可能会导致某些数据的稀疏性问题,即某些类别中的样本数量较少。为了解决这个问题,可以使用一些预处理技术或正则化方法来增强模型的性能。

基于Logistic回归和Sigmoid函数的分类 

基于Logistic回归和Sigmoid函数的分类是一种常见的机器学习方法,特别适用于处理二分类问题。在这种方法中,Logistic回归模型使用Sigmoid函数(也称为逻辑函数)来将线性组合的特征转换为介于0和1之间的概率值,从而进行分类预测。

具体来说,Logistic回归模型通过将输入特征的加权和传递给Sigmoid函数,得到一个在0到1之间的输出,表示输入数据属于正类别的概率。如果输出概率大于0.5,则模型将预测为正类别;如果输出概率小于等于0.5,则模型将预测为负类别。这种方式使得Logistic回归能够灵活地处理分类问题,并且输出的概率值可以提供对分类结果的置信度估计。

通过训练Logistic回归模型的参数,可以最大化分类的准确性,使得模型能够更好地预测新的未见数据。在实际应用中,可以使用梯度下降等优化算法来调整模型参数,以使模型在训练数据上达到最佳拟合。

总的来说,基于Logistic回归和Sigmoid函数的分类方法是一种简单而有效的分类技术,特别适用于处理二分类问题,并且在许多实际应用中都取得了良好的效果。

基于最优化方法的最佳回归系数确定

梯度上升法

梯度上升法基于的思想是:要找到某函数的最大值,最好的方法是沿着该函数的梯度方向探寻。

如果梯度记为▽,则函数f(x,y)的梯度由下式表示:

\triangledown f(x,y)=\begin{pmatrix} \frac{\partial f(x,y)}{\partial x} \\ \\\frac{\partial f(x,y)}{\partial y} \end{pmatrix}

这个梯度意味着要沿x的方向移动 \frac{\partial f(x,y)}{\partial x},沿y的方向移动\frac{\partial f(x,y)}{\partial y}

普通梯度上升算法实现

def gradAscent(dataMatIn, classLabels):
    dataMatrix = np.mat(dataMatIn) #转换成numpy的mat
    labelMat = np.mat(classLabels).transpose() #转换成numpy的mat,并进行转置
    m, n = np.shape(dataMatrix)   #返回dataMatrix的大小。m为行数,n为列数。
    alpha = 0.01   #移动步长,也就是学习速率,控制更新的幅度。
    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(),weights_array #将矩阵转换为数组,返回权重数组

随机梯度上升算法实现

        普通梯度上升算法在每次更新回归数据时都需要遍历整个数据集,该方法处理100个左右的数据集尚可,但如果有数十亿的样本和成千上万的特征,那么该方法的复杂度就太高了。因此就引入了随机梯度算法。相较于普通的梯度上升算法来说,随机梯度算法一次仅用一个样本点来更新回归系数。

def gradAscent(dataMatIn, classLabels):
	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() #将矩阵转换为数组,返回权重数组

alpha在每次迭代的时候都会调整,并且,虽然alpha会随着迭代次数不断减小,但永远不会减小到0,因为这里还存在一个常数项。必须这样做的原因是为了保证在多次迭代之后新数据仍然具有一定的影响。如果需要处理的问题是动态变化的,那么可以适当加大上述常数项,来确保新的值获得更大的回归系数。另一点值得注意的是,在降低alpha的函数中,alpha每次减少1/(j+i),其中j是迭代次数,i是样本点的下标。第二个改进的地方在于跟新回归系数(最优参数)时,只使用一个样本点,并且选择的样本点是随机的,每次迭代不使用已经用过的样本点。这样的方法,就有效地减少了计算量,并保证了回归效果。

完整代码

import matplotlib.pyplot as plt
import numpy as np
"""
函数说明:梯度上升算法测试函数
求函数f(x) = -x^2 + 4x的极大值
"""
def Gradient_Ascent_test():
	def f_prime(x_old):	#f(x)的导数
		return -2 * x_old + 4
	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)#打印最终求解的极值近似值
"""
函数说明:加载数据
"""
def loadDataSet():
	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
"""
函数说明:sigmoid函数
"""
def sigmoid(inX):
	return 1.0 / (1 + np.exp(-inX))
"""
函数说明:梯度上升算法
"""
def gradAscent1(dataMatrix, classLabels, numIter=150):
    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[randIndex]*weights)) 
            error = classLabels[randIndex] - h  #计算误差
            weights = weights + alpha * error * dataMatrix[randIndex]#更新回归系数
            del(dataIndex[randIndex])  #删除已经使用的样本
    return weights 
"""
函数说明:绘制数据集
"""
def plotBestFit(weights):
	dataMat, labelMat = loadDataSet()									
	dataArr = np.array(dataMat)									
	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])
		else:
			xcord2.append(dataArr[i,1]); ycord2.append(dataArr[i,2])
	fig = plt.figure()
	ax = fig.add_subplot(111)										
	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.xlabel('X1'); plt.ylabel('X2')
	plt.show()		
 
if __name__ == '__main__':
	dataMat, labelMat = loadDataSet()	
	weights = gradAscent(np.array(dataMat), labelMat)
	plotBestFit(weights)
import matplotlib.pyplot as plt
import numpy as np
"""
函数说明:梯度上升算法测试函数
求函数f(x) = -x^2 + 4x的极大值
"""
def Gradient_Ascent_test():
	def f_prime(x_old):	#f(x)的导数
		return -2 * x_old + 4
	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)#打印最终求解的极值近似值
"""
函数说明:加载数据
"""
def loadDataSet():
	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
"""
函数说明:sigmoid函数
"""
def sigmoid(inX):
	return 1.0 / (1 + np.exp(-inX))
"""
函数说明:梯度上升算法
"""
def gradAscent1(dataMatrix, classLabels, numIter=150):
    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[randIndex]*weights)) 
            error = classLabels[randIndex] - h  #计算误差
            weights = weights + alpha * error * dataMatrix[randIndex]#更新回归系数
            del(dataIndex[randIndex])  #删除已经使用的样本
    return weights 
"""
函数说明:绘制数据集
"""
def plotBestFit(weights):
	dataMat, labelMat = loadDataSet()									
	dataArr = np.array(dataMat)									
	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])
		else:
			xcord2.append(dataArr[i,1]); ycord2.append(dataArr[i,2])
	fig = plt.figure()
	ax = fig.add_subplot(111)										
	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.xlabel('X1'); plt.ylabel('X2')
	plt.show()		
 
if __name__ == '__main__':
	dataMat, labelMat = loadDataSet()	
	weights = gradAscent(np.array(dataMat), labelMat)
	plotBestFit(weights)

总结

Logistic回归是一种常用的机器学习算法,主要用于解决分类问题。它通过将线性回归模型的输出映射到介于0和1之间的概率值,来预测输入数据属于某个类别的概率。在Logistic回归中,使用逻辑函数(Sigmoid函数)来进行这种映射。通过调整模型的参数,可以最大化预测的准确性。Logistic回归通常用于二分类问题,但也可以扩展到多分类问题。

Logistic回归的优势在于能够同时处理多个特征和类别标签,通过线性组合特征并应用逻辑函数来进行分类预测。每个特征在模型的权重向量中被加权并求和,最终输出一个概率值表示输入数据属于某个类别的概率。这种输出方式有助于更有效地建立特征与类别之间的关系。

通过调整模型参数,Logistic回归可以最大化分类准确性,使模型能够更好地预测新数据。在实际应用中,可以使用梯度下降等优化算法来训练模型。总的来说,Logistic回归是一种简单而有效的分类技术,特别适用于二分类问题,并在许多领域取得了良好的效果。

  • 56
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值