目录
4.利用matplotlib绘制图像,并利用最小二乘法来拟合数据点
一.logistic回归
1.什么是logistic回归
Logistic回归是一种在机器学习和统计学中广泛使用的分类算法,主要用于二分类问题。尽管它的名字中包含“回归”,但实际上它是一种分类方法,因为它预测的是输入数据实例属于某个类别的概率。下面将详细介绍Logistic回归的基本原理和关键概念
2.基本原理
Logistic回归通过计算输入数据的线性组合(即加权和),然后应用一个逻辑函数将结果转换为0到1之间的概率值。这个概率值表示输入数据实例属于某个类别的可能性。通常情况下用于二分类问题,若输出的概率值在0到0.5之间,则将输入的数据实例分为0类;若输出的概率值在0.5到1之间,则将输入的数据实例分1类
3.逻辑函数(Sigmoid函数)
在不同坐标尺度下的sigmoid函数的两天曲线图:
其中,( z ) 是输入数据的线性组合(即加权和)。sigmoid将任何实数映射到0到1之间的值,这使得它可以用于预测概率。本次logistc回归就是利用sigmoid函数作为逻辑函数将结果转换到0-1之间,从而实现对输入的数据实例进行分类
4.线性组合
对于sigmoid函数的输入数据z,其线性组合可以表示为:
其中的向量x是分类器的输入数据,向量w也就是我们要找到的最佳参数(系数),从而使得分类器尽可能地精确
5.回归的概念
假设现在有一些数据点,我们用一条直线对这些点进行拟合(该线称为最佳拟合曲线),这个拟合的过程就称作回归(如下图中的蓝色直线就为最佳拟合曲线)
6.优缺点
优点:(1)解释性强:结果易于解释,因为它直接给出了每个特征对结果的影响程度
(2)计算效率高 (3)适用于二分类问题
(4)稳健性:Logistic回归对数据的分布没有严格的要求,只要数据满足线性可分
缺点:(1)对非线性问题的处理能力有限
(2)容易过拟合:当数据中存在较多特征且特征之间存在高度相关性时,Logistic回归模型容易出现过拟合现象
(3)对缺失值和异常值敏感 (4)多分类问题处理困难
二.例子
1.引例
1> 小明当银行行长赚了很多米,于是成立了一个电子竞技俱乐部,小明的战队有一个非常神奇的特性,就是选手十分慢热,前期超鬼,后期超神。十分钟之内,队员简直就是一碰就碎,全都在自闭草丛里面排队,只能和对面0、10开或者1、9开。但是到了游戏中期之后,队员们总能找到手感和对面势均力敌,能够达到五五开的程度,而到了35分钟之后,队员们神挡杀神,佛挡杀佛,河道随便下凡,能够达到9、1开或者10、0开。因为中期的局势太过扑朔迷离,小明十分想知道在第二十六分钟的时候能和对面几几开(要解决的问题)(下图表示蓝色和橙色战队胜利的份额)
2>这里补充几个关键的概念
事件发生的几率:是指事件发生的概率和该事件不发生的概率的比值(在此题目中表示赢下对局和输掉对局可能性的比值)
即:
3>由上图,可以罗列出蓝色战队胜利的几率(转化为小数)如下图:
4>将结果映射到数轴上如下图:
当蓝色战队十分可能输掉比赛时,概率会趋向于0,而战队十分可能获得比赛的胜利时,概率会趋向于正无穷。这就使得概率的分布在正半轴分布十分不均匀,不太好分析问题。所以使用几率的对数来分析数据(事件发生几率的对数)
即:
5>重新计算结果并将结果映射到数轴上:
6>以对数几率为y轴,比赛时间为x轴,将数据映射到xy平面上。此时,通过每一个数据点到直线的距离差,通过最小二乘法优化,从而得到最佳拟合曲线来拟合这些数据,如下图:
此时就可以通过查询x轴对应的时间就可以得出赢下这场比赛的可能性了,但有许多数据点的y值是±∞,无法用来计算数据和直线,所以需要将这条直线重现映射回概率空间(即将概率p写成y的函数)
2.logistic回归函数推导
1>我们是以对数几率为y轴,所以:
2>等式两边做一个自然对数的幂:
3>等式两边同乘以1-p并将括号展开得:
4>移项,提取公因式后并化简即可得到p关于y的函数:
5>将直线的表达式代入到公式中,就可以得到概率空间的表达式:
所以,可以这样理解:概率空间的logistic回归就是对数几率空间内的线性回归
3.极大似然估计
1>对于概率空间,我们可以使用概率论中的极大似然估计来得到最好的logistic曲线,对于时间x赢下比赛的几率为p,输掉比赛的几率为1-p(y=1表示赢下比赛,y=0表示输掉比赛)所以任意样本xi的概率:
2>似然值为样本概率的乘积:
3>结果带入:
4>等式两边同取对数:
5>括号展开化简得:
6>等式右侧的对数几率可以替换成线性回归中的直线方程,pi可以替换成logistic函数,得:
7>使用优化方法得到最好的w和b这两个参数:
从而得到最好的最好的logistc函数,并将26分钟或者是输入的数据带入该函数,从而得到相应的概率(该例子中为小明战队获胜的概率),从而实现相应的分类问题,这也就是logistic回归
三.梯度上升算法求解回归系数
1.首先通过相应的文本文件获取数据集以及所要用到的测试集
def loaddataset():
testset = [[-3.141592,2.343434],[7.12121,3.232323],[-1.222222,3.2323232],[2.794747,-4.67890]]
datamat = [] ; labelmat = []
fr = open("D:\\University_Second_down------\\机器学习data\\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]))
return datamat , labelmat , testset
1>文本文件的内容大致如下图:
2>其中第一列表示该数据的横坐标,第二列表示数据的纵坐标,第三列表示该数据点的所属于的标签的类别,为0类或者是1类
2.定义sigmoid函数并利用梯度上升法计算权值
def sigmoid(intx):
return 1.0/(1+exp(-intx))
def gradascent(datamatin, classlabels):
datamatrix = mat(datamatin) #将datamatrix转化为矩阵
labelmat = mat(classlabels).transpose() #将labelmat转化为矩阵同时转置
m , n = shape(datamatrix) #m为矩阵的行数,n为矩阵的列数
alpha = 0.001 #学习率(梯度上升的步长)
maxcycles = 500 #最大迭代次数
weights = ones((n,1)) #权重矩阵(n,1)的列向量
for k in range(maxcycles): #梯度上升循环
h = sigmoid(datamatrix*weights) #使用当前权重和输入数据计算每个数据点的预测概率
error = (labelmat - h) #计算预测概率和真实标签的误差
weights = weights + alpha * datamatrix.transpose()*error
return weights #datamatrix.transpose()*error为梯度,再利用梯度*学习率来更新权值
3.对测试集进行分类
1>代码:通过线性回归计算出z,再将该数据输入sigmoid函数,转化为某个概率值,从而实现相应的测试集的分类
def coutresult(weights , testset):
list = weights.tolist() #将矩阵转化为列表
w0 = list[0]; w1 = list[1]; w2 = list[2] #获取列表中的每一个元素
count = 0
for sample in testset:
count += 1 #用来记录当前的测试集
z = w0[0]*1 + w1[0]*sample[0] + w2[0]*sample[1]
result = sigmoid(z)
print(f"第{count}个测试集计算的概率结果为:{result}")
if result>0.5:
print(f"第{count}个测试集通过概率结果被预测的类别为1类")
else:
print(f"第{count}个测试集通过概率结果被预测的类别为0类")
def main():
datamat, labelmat , testset= loaddataset()
weights = gradascent(datamat, labelmat)
print("训练得到的权重为:", weights.T)
coutresult(weights, testset)
2>运行结果:
4.利用matplotlib绘制图像,并利用最小二乘法来拟合数据点
1>代码:最小二乘法和图像绘制并显示,其中w和b的计算公式如下
def calwandb(dataset):
length = len(dataset)
xaverage = 0
xihef = 0
result = 0
for sample in dataset:
xaverage += sample[0]
xihef = xaverage*xaverage / length
xaverage /= length
wtop = 0
wunder = 0
for sample in dataset:
wtop += sample[1]*(sample[0]-xaverage)
wunder += sample[0]*sample[0]
wunder -= xihef
w = wtop / wunder
for sample in dataset:
result += sample[1] - w*sample[0]
b = result / length
print(f"w={w:.3f},b={b:.3f}")
return w, b
def plotDataSet():
dataMat, labelMat ,testset= 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为负样本
x_values = np.array([dataArr[:, 1].min() - 1, dataArr[:, 1].max() + 1])
y_values = 1.109 * x_values + 6.543 # 根据斜率和偏移量计算y值
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) # 绘制负样本
ax.plot(x_values, y_values, 'k-')
plt.title('DataSet') # 绘制title
plt.xlabel('x');
plt.ylabel('y') # 绘制label
plt.show()
2>运行结果:
四.总结
在本次机器学习实验课程中,我深入探索了逻辑回归(Logistic Regression)的应用。逻辑回归是一种广泛应用于分类问题的统计方法,特别是在二分类场景下。通过本次实验,我学习了如何构建逻辑回归模型,并使用训练数据来拟合模型参数。
实验中,我首先获取相应的数据集用以训练模型以及获得相应的测试集来测试模型的效果。随后,我使用梯度上升算法优化了模型的损失函数,从而得到了最优的参数解。然后利用线性回归来计算得到sigmoid函数的输入数据z,将该数据传入sigmoid函数中就可以得到0-1之间的概率,从而完成对相应的测试集的分类。
总之,通过这次实验,我不仅掌握了逻辑回归的基本原理和实现方法,还深刻理解了相关的最优化算法的重要性。这次实验为我今后在机器学习领域的学习和应用打下了坚实的基础。