《机器学习》西瓜书课后习题3.3——python实现对率回归

《机器学习》西瓜书课后习题3.3——python实现对率回归(梯度下降法)

《机器学习》西瓜书P69:

3.3 编程实现对率回归,并给出西瓜数据集3.0a上的结果

首先我们回归一下什么的是对率回归?
对数几率回归模型,是一个典型的二分类任务学习模型

书接上回,我们可以对一个数据集得到它的回归方程

我们是这样去解读回归方程的:在相关属性下对样例的某一特征的度量

我们根据回归方程得到的特征度量是一个连续值,我们可以根据这个度量值进行分类

例如:大学的绩点计算,当我们的绩点大于等于2.0才能拿到学位,否则拿不到学位,我们可以认为当度量值达到多少时将样例视为一类,而没达到的样例分为另一类。

但是问题就在于:

  1. 训练数据集中需要预测的特征是分类的标签(0, 1),而不是其度量值
  2. 若训练集给出了需要预测的特征的分类标签(0, 1)和度量值,但是我们无法知道两个分类的度量值的界限

根据我们的需求,提出以下假设:
我们的线性方程为:在这里插入图片描述
设有一个函数g(x):
在这里插入图片描述
将我们的线性方程和这个g(x)合并可得
在这里插入图片描述
这样我们就可利用这个函数模型来对数据分类了。使用最多的就是对数几率函数,其标准形式为在这里插入图片描述
我们将我们的线性回归方程与对数几率函数合并,得到我们的新模型如下:

在这里插入图片描述

我们依然使用差值来度量它的预测准确度,则我们的优化目标函数(代价函数)如下:

img

我们可以使用梯度下降算法来计算上述优化目标。

梯度下降法公式如下(梯度下降法的证明推导过程见https://blog.csdn.net/qq_41398808/article/details/90442685):

img

我们的优化目标函数的一阶导数为(计算过程参考:https://www.cnblogs.com/crackpotisback/p/5545708.html):

img

所以我们根据该公式对参数进行迭代,就可以得到我们想要的结果。


【数据集】

西瓜数据集3.0a.csv:

编号,密度,含糖率,好瓜
1,0.697,0.46,2,0.774,0.376,3,0.634,0.264,4,0.608,0.318,5,0.556,0.215,6,0.403,0.237,7,0.481,0.149,8,0.437,0.211,9,0.666,0.091,10,0.243,0.267,11,0.245,0.057,12,0.343,0.099,13,0.639,0.161,14,0.657,0.198,15,0.36,0.37,16,0.593,0.042,17,0.719,0.103,

【数据读取和预处理函数——loadDataset】

首先我们需要读取数据并进行预处理,将属性矩阵和标记矩阵分开存储,同时在属性矩阵的最后增加全为1的一列。我在这里直接将最后一列全替换为1,并根据标记存放到label数组里面。

#读取西瓜数据集中的数据并进行预处理
def loadDataset(filename):
    dataset=[]
    labelset=[]
    with open(filename,'r',encoding='utf-8') as csvfile:
        csv_reader=csv.reader(csvfile)
        header=next(csv_reader)
        for row in csv_reader:
            if row[3] == '是':
                labelset.append(1)
            elif row[3] == '否':
                labelset.append(0)
            row[3]=1
            dataset.append(row)
    data=[[float(x) for x in row]for row in dataset]
    return dataset,labelset

【对数几率函数——sigmoid】

接下来我们定义对数几率函数sigmoid

#定义sigmoid函数
def sigmoid(z):
	return 1.0 / (1 + np.exp(-z))

【迭代求w函数——training】

下面我们需要采用迭代的方式求w,根据上面的公式我们进行合并化简得到最终的梯度下降公式:

其中n为步长,最终我们得到的w是一个数组,每一个元素表示的是该属性前面的系数w,为了控制迭代次数,我们将”准确率高于90%“作为终止的条件;

#迭代求w
def training(dataset,labelset):
    # np.dot(a,b) a和b矩阵点乘
    # np.transpose()  转置
    # np.ones((m,n))  创建一个m行n列的多维数组
    data=np.mat(dataset).astype(float)
    label=np.mat(labelset).transpose()
    w = np.ones((len(dataset[0]),1))

    #步长
    n=0.0001

    # 每次迭代计算一次正确率(在测试集上的正确率)
    # 达到0.90的正确率,停止迭代
    rightrate=0.0
    while rightrate<0.90:
        c=sigmoid(np.dot(data,w))
        b=c-label
        change = np.dot(np.transpose(data),b)
        w=w-change*n
        #预测,更新准确率
        rightrate = test(dataset,labelset,w)

    return w

【计算准确率函数——test】

因此为了计算准确率我们定义了一个函数test,作用是将每次迭代取得的w作为参数代入公式在这里插入图片描述在这里插入图片描述

并判断y是否大于或小于0.5,得到预测值;并与实际标记值是否相等,若相等则判断正确的个数+1,最终返回准确率。

def test(dataset,labelset,w):
    data=np.mat(dataset).astype(float)

    y=sigmoid(np.dot(data,w))
    b,c=np.shape(y)#功能是查看矩阵或者数组的维数。
    rightcount=0

    for i in range(b):
        flag=-1
        if y[i,0]>0.5:
            flag=1
        elif y[i,0]<0.5:
            flag=0
        if labelset[i] == flag:
            rightcount+=1

    rightrate=rightcount/len(dataset)
    return rightrate

【完整源代码】

#读取本地数据
import csv
import numpy as np

#读取西瓜数据集中的数据并进行预处理
def loadDataset(filename):
    dataset=[]
    labelset=[]
    with open(filename,'r',encoding='utf-8') as csvfile:
        csv_reader=csv.reader(csvfile)
        header=next(csv_reader)
        for row in csv_reader:
            if row[3] == '是':
                labelset.append(1)
            elif row[3] == '否':
                labelset.append(0)
            row[3]=1
            dataset.append(row)
    data=[[float(x) for x in row]for row in dataset]
    return dataset,labelset

#定义sigmoid函数
def sigmoid(z):
	return 1.0 / (1 + np.exp(-z))

def test(dataset,labelset,w):
    data=np.mat(dataset).astype(float)

    y=sigmoid(np.dot(data,w))
    b,c=np.shape(y)#功能是查看矩阵或者数组的维数。
    rightcount=0

    for i in range(b):
        flag=-1
        if y[i,0]>0.5:
            flag=1
        elif y[i,0]<0.5:
            flag=0
        if labelset[i] == flag:
            rightcount+=1

    rightrate=rightcount/len(dataset)
    return rightrate

#迭代求w
def training(dataset,labelset):
    # np.dot(a,b) a和b矩阵点乘
    # np.transpose()  转置
    # np.ones((m,n))  创建一个m行n列的多维数组
    data=np.mat(dataset).astype(float)
    label=np.mat(labelset).transpose()
    w = np.ones((len(dataset[0]),1))

    #步长
    n=0.0001

    # 每次迭代计算一次正确率(在测试集上的正确率)
    # 达到0.90的正确率,停止迭代
    rightrate=0.0
    while rightrate<0.90:
        c=sigmoid(np.dot(data,w))
        b=c-label
        change = np.dot(np.transpose(data),b)
        w=w-change*n
        #预测,更新准确率
        rightrate = test(dataset,labelset,w)

    return w


dataset=[]
labelset=[]
filename = '西瓜数据集3.0a.csv'
dataset,labelset=loadDataset(filename)
w=training(dataset,labelset)
print("若使得准确率大于90%,则此时的w为:\n",w)
print("正确率:%f"%(test(dataset,labelset,w)*100)+"%")

【运算结果】

所以最终得到的西瓜模型为:
y = − 0.14505012 ∗ 编 号 + 0.95884929 ∗ 密 度 + 0.98789039 ∗ 含 糖 率 + 0.91625094 y=-0.14505012*编号+0.95884929*密度+0.98789039*含糖率+0.91625094 y=0.14505012+0.95884929+0.98789039+0.91625094

参考博文:
机器学习 对数几率回归模型(Python实现)

上述解题过程如有错误 还请及时留言联系

  • 49
    点赞
  • 324
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 35
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 35
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yozu_Roo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值