Logistic回归——银行违约情况分析

news2024/11/25 0:32:00

文章目录

  • 一、Logistic回归原理
    • 1、Sigmoid函数作用
    • 2、用梯度下降法求解参数
  • 二、利用Logistic回归分类
    • 1、数据预处理
    • 2、利用梯度上升计算回归系数
    • 3、训练和验证
  • 总结

一、Logistic回归原理

1、Sigmoid函数作用

Logistic回归的原理是用逻辑函数把线性回归的结果(-∞,+∞)映射到(0,1),下面介绍线性回归函数和逻辑函数。

  • 线性回归函数
    线性回归函数的数学表达式:
    y = θ 0 + θ 1 x 1 + θ 2 x 2 , + … + θ n x n = θ T x y=\theta _{0} +\theta _{1}x _{1}+\theta _{2}x _{2},+…+\theta _{n}x _{n} = \theta^{T} x y=θ0+θ1x1+θ2x2,++θnxn=θTx
    其中xi是自变量,y是因变量,y的值域为(-∞,+∞) θ 0 \theta _{0} θ0是常数项, θ i \theta _{i} θi是待求系数,不同的权重 θ i \theta _{i} θi反映了自变量对因变量不同的贡献程度。
    对于一元一次方程: y=a+bx,这种只包括一个自变量和一个因变量的回归分析称为一元线性回归分析。
    对于二元一次方程: y= a+b1x1+b2x2,三元一次方程: y = a+b1x1+b2x2+b3x3,这种回归分析中包括两个或两个以上自变量的回归分析,称为多元线性回归分析。
    不管是一元线性回归分析还是多元线性回归分析,都是线性回归分析。

  • Sigmoid函数
    函数表达式:
    g ( z ) = 1 1 + e − z g(z)=\frac{1}{1+e^{-z} } g(z)=1+ez1
    函数图像:
    在这里插入图片描述
    从图像中可以看出,当z趋于-∞g(z)趋于0,当z趋于+∞g(z)趋于1,且函数的值阈为(0,1)。原理是当z趋于-∞ e − z e^{-z} ez趋于∞,g(z)趋于0,当z趋于+∞ e − z e^{-z} ez趋于0,g(z)趋于1。
    同时可以发现当z趋于5时,g(z)的值已经到0.99附近,z越大,g(z)越趋于1。所以这个函数很好描述我们日常生活中,平时碰到的概率。我们可能认为明天下雨的概率为0.3,天晴的概率为0.7。抛一枚硬币正面的概率为0.5,反面的概率也为0.5。概率也是介于0到1之间的一些数,很自然我们可以把sigmod函数的值域和概率联系起来。

2、用梯度下降法求解参数

梯度下降过程类似一个人下山过程:

  • step1:明确自己现在所处的位置;
  • step2:找到现在所处位置下降最快的方向;
  • step3:沿着第二步找到的方向走一个步长,到达新的位置,且新位置低于刚才的位置;
  • step4:判断是否下山,如果还没有到最低点继续步骤—,如果已经到最低点,则停止。

从上面的分析知,用梯度下降法求解参数最重要的是找到下降最快的方向和确定要走的步长。
那么什么是函数下降最快的方向?
如果学过一元函数的导数,应该知道导数的几何意义是某点切线的斜率。除此之外导数还可以表示函数在该点的变化率,导数越大,表示函数在该点的变化越大。
在这里插入图片描述
从图中可以发现p2点的斜率大于p1点的斜率,即p2点的导数大于p1点的导数。对于多维向量
x = ( x 1 , x 2 , . . . , x n ) x= (x_{1},x_{2},...,x_{n} ) x=(x1,x2,...,xn)
它的导数叫做梯度(偏导数),当求某个变量的导数时,把其它变量视为常量,对整个函数求导,也就是分别对于它的每个分量求导数,即
x ′ = ( x 1 ′ , x 2 ′ , . . . , x n ′ ) x^{'} = (x_{1}^{'},x_{2}^{'},...,x_{n}^{'} ) x=(x1,x2,...,xn)
对于函数的某个特定点,它的梯度就表示从该点出发,函数值变化最为迅猛的方向。至此梯度下降法求解参数的方向已经找到,那就是函数的梯度方向。

二、利用Logistic回归分类

1、数据预处理

  1. 获取数据集
    我的数据集是获取用户个人信息(年龄、教育情况、工龄、地址、收入、负债率、银行卡负债等情况),利用这些信息,最后判断用户是否违约。
    在这里插入图片描述
    预处理时,先将用户信息存入一个二维数组中,其返回值data_arr 为数据特征,label_arr是每个数据对应标签 :
def load_data_set(fileName):
    data_arr = []
    label_arr = []
    f = open(fileName, 'r')
    for line in f.readlines():
        line_arr = line.strip().split()
        data_arr.append([np.float(line_arr[0]), 
                            np.float(line_arr[1]),
                            np.float(line_arr[2]),
                            np.float(line_arr[3]),
                            np.float(line_arr[4]),
                            np.float(line_arr[5]),
                            np.float(line_arr[6]),
                            np.float(line_arr[7])])
        label_arr.append(int(line_arr[8]))
    data_arr = maxminnorm(data_arr)
    return data_arr, label_arr
data_arr, class_labels = load_data_set()

在预处理时要注意如果有的数据太大,要将数据归一化,如果不归一化会导致数据溢出。根据sigmoid函数
g ( z ) = 1 1 + e − z g(z)=\frac{1}{1+e^{-z} } g(z)=1+ez1当z过大时, e − z e^{-z} ez数值是很大的,所以要将器归一化处理,根据归一化公式: x i = x i − m i n ( x ) m a x ( x ) − m i n ( x ) x_{i}=\frac{x_{i} -min(x)}{max(x)-min(x)} xi=max(x)min(x)ximin(x)根据公式可以将数据全部保证在0-1之间,并且不丢失数据代表的特征。带入到sigmoid函数后,就不会有数据溢出的异常了。

def maxminnorm(array):
    array = np.array(array)
    maxcols=array.max(axis=0)
    mincols=array.min(axis=0)
    data_shape = array.shape
    data_rows = data_shape[0]
    data_cols = data_shape[1]
    t=np.empty((data_rows,data_cols))
    for i in range(data_cols):
        t[:,i]=(array[:,i]-mincols[i])/(maxcols[i]-mincols[i])
    return t

2、利用梯度上升计算回归系数

  • 梯度上升模型
    梯度上升法,其实就是因为使用了极大似然估计,传入的就是一个普通的数组param data_arr,当然你传入一个二维的ndarray也行。class_labels 是类别标签,它是一个的行向量。为了便于矩阵计算,需要将该行向量转换为列向量,做法是将原向量转置,再将它赋值给label_mat。
def grad_ascent(data_arr, class_labels):
    data_mat = np.mat(data_arr)
    # 变成矩阵之后进行转置
    label_mat = np.mat(class_labels).transpose()
    # m->数据量,样本数 n->特征数
    m, n = np.shape(data_mat)
    # 学习率,learning rate
    alpha = 0.001
    # 最大迭代次数
    max_cycles = 500
    # 生成一个长度和特征数相同的矩阵
    # weights 代表回归系数, 此处的 ones((n,1)) 创建一个长度和特征数相同的矩阵,其中的数全部都是 1
    weights = np.ones((n, 1))
    for k in range(max_cycles):
        h = sigmoid(data_mat * weights)
        error = label_mat - h
        weights = weights + alpha * data_mat.transpose() * error
    return weights
  • 随机梯度上升算法:
    梯度上升算法在更新回归系数是都要遍历整个数据集,如果处理的样本数和标签数太多,那计算的复杂度就太大了。如果一次只用一个样本点来更新回归系数,这种方法叫做随机梯度上升算法。随机梯度上升算法和梯度上升算法区别有:(1)后者的变量和误差都是向量,而前者全是数值;(2)前者没有矩阵转换过程,所有变量都是numpy数组。
def stoc_grad_ascent0(data_mat, class_labels):
    m, n = np.shape(data_mat)
    alpha = 0.01
    weights = np.ones(n)
    for i in range(m):
        # sum(data_mat[i]*weights)为了求 f(x)的值, f(x)=a1*x1+b2*x2+..+nn*xn,
        # 此处求出的 h 是一个具体的数值,而不是一个矩阵
        h = sigmoid(sum(data_mat[i] * weights))
        error = class_labels[i] - h
        weights = weights + alpha * error * data_mat[i]
    return weights
  • 改进随机梯度上升算法:
    相对于随机梯度上升算法,这个算法改进了几个方面:(1)aplha在每次迭代的时候都会调整,这会缓解数据波动。另外,虽然aplha会随着迭代次数不断减少,但永远不会减少到0;(2)通过随机选取样本更新回归系数,这种方法减少波动;(3)可以修改默认的迭代次数,第三个参数可以将迭代次数传入,没有默认为150次。
def stoc_grad_ascent1(data_mat, class_labels, num_iter=150):
    m, n = np.shape(data_mat)
    weights = np.ones(n)
    for j in range(num_iter):
        # 这里必须要用list,不然后面的del没法使用
        data_index = list(range(m))
        for i in range(m):
            # i和j的不断增大,导致alpha的值不断减少,但是不为0
            alpha = 4 / (1.0 + j + i) + 0.01
            # 随机产生一个 0~len()之间的一个值
            # random.uniform(x, y) 方法将随机生成下一个实数,它在[x,y]范围内,x是这个范围内的最小值,y是这个范围内的最大值。
            rand_index = int(np.random.uniform(0, len(data_index)))
            h = sigmoid(np.sum(data_mat[data_index[rand_index]] * weights))
            error = class_labels[data_index[rand_index]] - h
            weights = weights + alpha * error * data_mat[data_index[rand_index]]
            del(data_index[rand_index])
    return weights

3、训练和验证

  • 最终分类函数
    根据回归系数和特征向量来计算 Sigmoid 的值,大于0.5函数返回1,否则返回0
def classify_vector(in_x, weights):
    # print(np.sum(in_x * weights))
    prob = sigmoid(np.sum(in_x * weights))
    if prob > 0.5:
        return 1.0
    return 0.0
  • 训练模型
def colic_test():
    f_train = open('data/loandata.txt', 'r')
    f_test = open('data/loandata_test.txt', 'r')
    training_set = []
    training_labels = []
    # trainingSet 中存储训练数据集的特征,trainingLabels 存储训练数据集的样本对应的分类标签
    for line in f_train.readlines():
        curr_line = line.strip().split('\t')
        if len(curr_line) == 1:
            continue    # 这里如果就一个空的元素,则跳过本次循环
        line_arr = [float(curr_line[i]) for i in range(8)]
        training_set.append(line_arr)
        training_labels.append(float(curr_line[8]))
    # 使用 改进后的 随机梯度下降算法 求得在此数据集上的最佳回归系数 trainWeights
    train_weights0 = grad_ascent(np.array(training_set), training_labels)
    train_weights1 = stoc_grad_ascent0(np.array(training_set), training_labels)
    train_weights2 = stoc_grad_ascent1(np.array(training_set), training_labels)
    error_count0 = 0
    error_count1 = 0
    error_count2 = 0
    num_test_vec = 0.0
    # 读取 测试数据集 进行测试,计算分类错误的样本条数和最终的错误率
    for line in f_test.readlines():
        num_test_vec += 1
        curr_line = line.strip().split('\t')
        if len(curr_line) == 1: 
            continue    # 这里如果就一个空的元素,则跳过本次循环
        line_arr = [float(curr_line[i]) for i in range(8)]
        if int(classify_vector(np.array(line_arr), train_weights0)) != int(curr_line[8]):
            error_count0 += 1
        if int(classify_vector(np.array(line_arr), train_weights1)) != int(curr_line[8]):
            error_count1 += 1
        if int(classify_vector(np.array(line_arr), train_weights2)) != int(curr_line[8]):
            error_count2 += 1
    right_rate = 1 - (error_count0 / num_test_vec)
    print('梯度下降法正确率:{}'.format(right_rate))
    right_rate = 1 - (error_count1 / num_test_vec)
    print('随机梯度下降法正确率:{}'.format(right_rate))
    right_rate = 1 - (error_count2 / num_test_vec)
    print('改进随机梯度下降法正确率:{}'.format(right_rate))
    return 

运行结果:
在这里插入图片描述

总结

  • 在进行数据预处理时注意归一化
    数据集中,如果有相当一部分数据值太大,经过sigmoid函数计算导致溢出。归一化处理后,所有数据都在0与1之间,并且能够保留数据代表的特征。不进行归一化处理,对sigmoid函数优化也能解决这个问题。
  • 梯度下降算法优势
    在机器学习中的无约束优化算法,除了梯度下降以外,还有前面提到的最小二乘法,此外还有牛顿法和拟牛顿法。梯度下降法和最小二乘法相比,梯度下降法需要选择步长,而最小二乘法不需要。梯度下降法是迭代求解,最小二乘法是计算解析解。如果样本量不算很大,且存在解析解,最小二乘法比起梯度下降法要有优势,计算速度很快。但是如果样本量很大,用最小二乘法由于需要求一个超级大的逆矩阵,这时就很难或者很慢才能求解解析解了,使用迭代的梯度下降法比较有优势。
  • 改进的随机梯度上升算法
    相对于随机梯度上升算法,这个算法改进了几个方面:(1)aplha在每次迭代的时候都会调整,这会缓解数据波动。另外,虽然aplha会随着迭代次数不断减少,但永远不会减少到0;(2)通过随机选取样本更新回归系数,这种方法减少波动;(3)可以修改默认的迭代次数,第三个参数可以将迭代次数传入,没有默认为150次。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/58176.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【408篇】C语言笔记-第十章(线性表)

文章目录第一节:线性表的顺序表示线性表1. 定义2. 特点线性表的顺序表示1. 顺序表2. 优缺点比较3. 插入操作4. 删除操作5. 动态分配代码示例第二节:线性表的链式表示单链表优缺点对比插入操作删除操作代码示例第一节:线性表的顺序表示 线性表…

python中的序列(列表、元组、字符串)的切片操作

目录 一.序列 二. 序列常用操作——切片 注意 演示 一.序列 序列是指:内容连续、有序,可使用下标索引的一类数据容器 列表、元组、字符串,均可以可以视为序列。 二. 序列常用操作——切片 序列支持切片,即:列表、元组、字符串&#xf…

看卡塔尔世界杯,diff一下足球比赛与软件开发

diff一下足球比赛与软件开发吐槽世界杯E组!类比软件开发与足球比赛教练与架构师的作用新技术——半自动越位技术世界杯冠军吐槽世界杯E组! 最近博主看了多场世界杯比赛,看的我心力交瘁,欲哭无泪。 从日本与哥斯达黎加那场比赛开始…

算法刷题打卡第34天:有效的井字游戏

有效的井字游戏 难度:中等 给你一个字符串数组 boardboardboard 表示井字游戏的棋盘。当且仅当在井字游戏过程中,棋盘有可能达到 boardboardboard 所显示的状态时,才返回 truetruetrue 。 井字游戏的棋盘是一个 3 x 3 数组,由字…

MYSQL 中连接的使用

文章目录0 写在前面1 语法说明2 SQL准备3 举例说明3.1 内连接3.2 左连接3.3 右连接4 写在最后0 写在前面 实际业务中,查询数据库大多都是多表链接查询,所以MYSQL的连接的使用非常重要。 连接有三种: INNER JOIN(内连接,或等值连接&#xff0…

[附源码]计算机毕业设计疫情背景下社区互助服务系统Springboot程序

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

Git基本使用

目录 一、Git基础 1.Git与Github 2.注册Github账号并安装Git 二、Git的使用 1.本地仓库 进行全局配置: 创建仓库: Git常用操作指令: 版本回退: 2.远程仓库 两种常规使用方式: 分支管理: 冲突的产生…

python http模块快速搭建“简单”服务器笔记

极简运行 python -m http.sever或 # test.py import http.server import socketserverPORT 8000Handler http.server.SimpleHTTPRequestHandlerwith socketserver.TCPServer(("", PORT), Handler) as httpd:print("serving at port", PORT)httpd.serve…

m基于matlab的光通信的信道估计,均衡,抑制papr误码率仿真,对比ZF,RLS,MMSE三种算法

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 可见光通信的信道估计,均衡,抑制papr。 不考虑光信道,用传统的无线通信的OFDM的信道估计,均衡,抑制papr 信道估计,均衡最…

解决Windows RDP远程桌面连接同时多用户连接不互踢不干扰问题及rdp wrapper windows版本不受支持问题.

注意: 如果你当前正在通过RDP方式远程连接到你要更改设置的目标计算机,请在目标计算机上安装其他远程控制软件.防止RDP因在此过程中挂掉无法连接. 下载: 使用GitHub - stascorp/rdpwrap: RDP Wrapper Library开源软件 转到Release 最新版本的是1.6.2,原作者没有更新的了.好…

MySQL中count(*)和information_schema.tables中的table_rows值不相同

前两天我还在高高兴兴地写了一篇文章《一条SQL查询出MySQL数据库中所有表的数据量大小》,心想这也太方便了,只用一条SQL就能统计出所有表的数据量,但没想到,最终还是翻车了。。。 翻车过程如下: 有一张表&#xff0c…

【多目标进化优化】 MOEA 测试函数

声明 本文内容来源于 《多目标进化优化》 郑金华 邹娟著,非常感谢两位老师的知识分享,如有侵权,本人立即删除,同时在此表示,本文内容仅学习使用,禁止侵权,谢谢! 注:本文…

HTML+CSS制作简单的家乡网页 ——我的家乡介绍广东 web前端期末大作业

家乡旅游景点网页作业制作 网页代码运用了DIV盒子的使用方法,如盒子的嵌套、浮动、margin、border、background等属性的使用,外部大盒子设定居中,内部左中右布局,下方横向浮动排列,大学学习的前端知识点和布局方式都有…

基于STM32单片机的温度报警器(数码管)(Proteus仿真+程序)

编号:26 基于STM32单片机的温度报警器(数码管) 功能描述: 本设计由STM32F103单片机最小系统DS18B20温度传感器数码管显示模块声光报警模块独立按键组成。 1、主控制器是STM32F103单片机 2、DS18B20温度传感器测量温度 3、数码管显示温度值&…

数字化改革“1612”详解

背景 2021年2月18日,浙江省开始数字化改革建设,通过一年的建设,取得了光辉成绩。2022年2月28日,在省数字化改革推进大会,回顾一年来数字化改革的主要成效,研究部署2022年数字化改革目标任务,在…

Spring框架(六):SpringTransaction事务的底层原理、xml配置和注解配置

SpringTransaction事务的底层原理、xml配置和注解配置引子Spring事务入门搭建Test环境基于XML的方式配置事务Spring事务的隔离级别Spring事务的传播行为通过Annotation方式配置Spring的事务引子 痛定思痛,主要问题出现在自己雀氏不熟悉框架底层、一些面试题&#x…

【源码分析】Springboot启动流程源码分析

1.简介 springboot版本:2.7.2 SpringApplication类是用来执行Spring框架启动的引导类。 有两种方式可以进行启动引导: 通过静态方法SpringApplication.run启动。先创建SpringApplication实例,在调用的实例方法run进行启动。 无论是以上哪种…

资源管理管理

资源管理目录概述需求:设计思路实现思路分析1.PMI hr的理念2.双因素的理论3.马斯洛的需求层析理论4.延伸5.X,Y理论Z 理论期望理论:亚当斯公共理论边际福利,光环效应,额外待遇,皮的原理,KISS原理…

阿里P9大牛带你在简历上写精通Spring与Boot高级功能

前言 蓦然回首自己做开发已经十年了,这十年中我获得了很多,技术能力、培训、出国、大公司的经历,还有很多很好的朋友。但再仔细一想,这十年中我至少浪费了五年时间,这五年可以足够让自己成长为一个优秀的程序员&#…

QT - 模型与视图

经典MVC模式中,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。其中,View的定义比较清晰,就是用户界面。 MVC 不是一…