《机器学习实战》斧头书——第五章—Logistic回归和梯度下降法(1)——使用Logistic回归根据病马的表现特征来预测病马的死亡率

《机器学习实战》斧头书——Logistic回归和梯度下降法

一、对文章的说明

1.1 对本文有几点说明如下

1.1.1 我是一个刚学没多久的小白,所以代码可能也会有错误,欢迎各位大佬提出我的问题,感谢;
1.1.2 对于python版本 ,斧头书《机器学习实战》是用的2.x,本文使用的是3.x,然后代码的话,有的是参考书上的和网上的,还有部分是自己写的;
1.1.3 用的参考书是下面这本,封面拿了个斧头的人,这本书没有调库,都是用python写的底层代码,感觉对理解算法原理会更深入一点;
1.1.4 编写代码的地方,先是在Jupyter notebook上编写和部分代码的测试,最后在PyCharm上集成和封装。

二、项目背景

2.1 背景1

本节将使用Logistic回归来预测患有疝病的马的存活问题。这里的数据
包含368个样本和28个特征。从一些文献中了解到,疝病是描述马胃肠痛的术语。然而,这种病不一定源自马的胃肠问题,其他问题也可能引发马疝病。该数据集中包含了医院检测马疝病的一些指标,有的指标比较主观,有的指标难以测量,例如马的疼痛级别。

2.2 背景2

数据源于http://archive.ics.uci.edu/ml/datasets/Horse+Colic,现在有作者处理好的训练集和测试集数据,但是我还是去下载下来自己预处理了一下。
原数据有28个特征,剔除了6列无用的特征,这些特征的解释在前面的网站上有。剩下了22个特征,最后1个是标签列,1代表马是存活的,0代表马是没有存活下来的。

2.3 任务

先对数据做预处理,再编写梯度下降法,最后用 Logistic 回归进行分类,然后计算准确率。

2.4 梯度下降法

由于极大似然函数无法直接求解,所以在机器学习算法中,在最小化损失函数时,可以通过梯度下降法来一步步的迭代求解,得到最小化的损失函数和模型参数值。
这个方法经常用于求使得损失函数得到最小值时,某些参数的大小。
梯度的矩阵表示方法如下:
在这里插入图片描述
求出梯度后,对参数θ的更新公式如下,这会使得θ越来越接近于使得损失函数得到最小值的一个值。
在这里插入图片描述

2.4.1 批量梯度下降法——BGD

顾名思义,每次更新参数需要用到所有样本来进行求导得到梯度,比如本训练集有300个样本,我们可以迭代1000轮,每轮都用到了300个样本。

2.4.2 随机梯度下降法——SGD

与BGD不同的是,每次更新参数只选取1个样本来更新参数,而且是随机选取。比如本训练集有300个样本,我们可以随机选取迭代1000轮来更新参数,每轮都只用到1个样本。

2.4.2 小批量梯度下降法——MBGD

这是结合了前2个的优点产生的算法,BGD优点是可以获得全局最优解,缺点是如果数据太大,会计算很久很久,效率太低了;SGD优点是可以绕过那些比全局最优解还大的局部最优解,速度也更快,缺点是由于具有随机性,最后可能会来回震荡,而且没有BGD稳定,可能获得不了全局最优解。
而MBGD呢,每次送1个小批量batch进去更新参数,然后迭代多次。

2.5 Logistic回归

Logistic回归的公式如下,比较简单,z是输入,左边的是输出。
在这里插入图片描述
Logistic回归的图(这是输入的范围-5到5的图)如下所示:
在这里插入图片描述

Logistic回归的图(这是输入的范围-50到50的图)如下所示:
很接近于阶跃函数了,深度学习里也会用它做激活函数,相比于阶跃函数,它具有处处可导性。在这里插入图片描述
对于Logistic回归,当输出大于0.5时,将其分类为1,反之分类为0。

三、代码

3.1 马的特征预处理的代码

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

train2 = pd.read_table('horse_colic_train.txt',names=range(300),delimiter=' ',header=None,engine='python')
train2 = train2.iloc[:,:28]
train2.to_excel('train.xlsx')#读取下载好的原数据,并输出成Excel,方便观察数据
train_deal = pd.read_excel('train.xlsx',header=None)
train_deal.drop([0],inplace=True)
train_deal.drop([0,3,24,25,26,27,28],axis=1,inplace=True) #删除没用的数据

m,n = train_deal.shape
train_deal.index=range(m)   #重新定义行的index
train_deal.columns=range(n) #重新定义列的columns
train_deal.replace('?',0,inplace=True) #数据预处理,用0替换缺失值
# print(train2.describe())
train_deal.iloc[:,-1].replace('2',0,inplace=True) #把最后一列标签列,非1的替换成0
train_deal.iloc[:,-1].replace('3',0,inplace=True) #把最后一列标签列,非1的替换成0
# 结果
# -这匹马最终发生了什么?
# -可能的值:
# 1 =有效
# 2 =死亡
# 3 =被安乐死
for i in range(m):
    for j in range(n):
        train_deal.iloc[i,j] = float(train_deal.iloc[i,j])
        train_deal.iloc[i,j] = int(train_deal.iloc[i,j])#不这样的话会报错

test2 = pd.read_table('horse_colic_test.txt',names=range(68),delimiter=' ',header=None,engine='python')
test2 = test2.iloc[:,:28]
test2.to_excel('test.xlsx')#读取下载好的原数据,并输出成Excel,方便观察数据

test_deal = pd.read_excel('test.xlsx',header=None)
test_deal.drop([0],inplace=True)
test_deal.drop([0,3,24,25,26,27,28],axis=1,inplace=True) #删除没用的数据

m2,n2 = test_deal.shape
test_deal.index=range(m2)   #重新定义行的index
test_deal.columns=range(n2) #重新定义列的columns
test_deal.replace('?',0,inplace=True) #数据预处理,用0替换缺失值
# print(train2.describe())
test_deal.iloc[:,-1].replace('2',0,inplace=True) #把最后一列标签列,非1的替换成0
test_deal.iloc[:,-1].replace('3',0,inplace=True) #把最后一列标签列,非1的替换成0
# 结果
# -这匹马最终发生了什么?
# -可能的值:
# 1 =有效
# 2 =死亡
# 3 =被安乐死
for i in range(m2):
    for j in range(n2):
        test_deal.iloc[i,j] = float(test_deal.iloc[i,j])
        test_deal.iloc[i,j] = int(test_deal.iloc[i,j])

3.2 用Logistic回归根据病马的特征来预测病马的死亡率的代码


def regulize(xmat):
    inMat = xmat.copy()
    xmean = np.mean(xmat,axis=0)
    xstd  = np.std(xmat,axis=0)
    xmat = (inMat-xmean)/xstd
    return xmat
#BGD批量梯度下降算法的实现
def bgd_lzh(dataset,alpha=0.001,runs=5000):#批量梯度下降法
    m,n = dataset.shape
    xmat = np.mat(dataset.iloc[:,:-1])
    ymat = np.mat(dataset.iloc[:,-1]).T
    xmat = regulize(xmat)
    weights = np.zeros((n-1,1))
    for i in range(runs):
        gradiant = xmat.T*(xmat*weights-ymat)/m
        weights = weights - alpha*gradiant
    return weights
def sgd_lzh(dataset,alpha=0.03,runs=500):#随机梯度下降法
#     import random
    dataset = dataset.sample(runs, replace=True)#随机打乱
    dataset.index = range(dataset.shape[0])#重新排序0-499
    m,n = dataset.shape
    weights = np.zeros((n-1,1))
    xmat = np.mat(dataset.iloc[:,:-1])
    ymat = np.mat(dataset.iloc[:,-1]).T
    xmat = regulize(xmat) #标准化
    for i in range(runs):
        gradiant = xmat[i].T*(xmat[i]*weights-ymat[i])
        weights = weights - alpha*gradiant
    return weights
##逻辑回归  输入  大于0就是1  小于0就是0
def sigmoid(data):
    sig = 1/(1+np.exp(-data))
    return sig
def classify_lr(data):
    data = regulize(data)#一定记得要标准化,不然准确率会大大降低,没标准化是52%左右,标准化后是70%左右
    data = np.array(data)
    m,n = data.shape
    for i in range(m):
        if sigmoid(data[i])>0.5:
            data[i] = 1
        else:
            data[i] =0
    return data

def testing_bgd():
    weights2 = bgd_lzh(test_deal,alpha=0.3,runs=5000) #.shape (21, 1)
    # 学习率alpha不能太大,否则会发散
    inmat2 = np.mat(test_deal.iloc[:,:-1])
    ylabel2 = np.mat(test_deal.iloc[:,-1]).T
    # ylabel = np.array(ylabel)
    accuracy = (classify_lr(inmat2*weights2)==ylabel2).mean()
    return accuracy

def testing_sgd():
    weights2 = sgd_lzh(test_deal,alpha=0.003,runs=1000) #.shape (21, 1)
    # 学习率alpha不能太大,否则会发散
    # print(weights2)
    inmat2 = np.mat(test_deal.iloc[:,:-1])
    ylabel2 = np.mat(test_deal.iloc[:,-1]).T
    # ylabel = np.array(ylabel)
    accuracy = (classify_lr(inmat2*weights2)==ylabel2).mean()
    return accuracy
print('using BGD:',testing_bgd())
print('using SGD:',testing_sgd())

3.3 看一下判断的准确率

在这里插入图片描述

四、总结

4.1 Logistic回归算法简单,但是要先用梯度下降法算好权重。学习率alpha不能太大,否则会发散。矩阵相乘一定要注意X,Y,W的维度。
4.2 一定记得要对输入的矩阵数据进行标准化,不然准确率会大大降低,没标准化是52%左右,标准化后是73%左右。没有标准化的话,还会使得收敛速度大大降低。因为比如说下图,没有标准化的是个椭圆,标准化后是个正圆。
在这里插入图片描述

4.3 train2.to_excel(‘train.xlsx’)#读取下载好的原数据,并输出成Excel,方便观察数据。
4.4 test_deal.replace(’?’,0,inplace=True) #数据预处理,用0替换缺失值的函数。
4.5 多写几个子函数,更方便点。
4.6 其实一开始是在Jupyter notebook上写的,那个方便看结果,全部写好后,再去PyCharm上封装起来,方便以后的使用。
4.7 谢谢阅读,我是刚学不久的小白,有错误的话欢迎各位大佬提出来,共同进步,多谢多谢。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值