讲透金融风控建模全流程(附 Python 代码)

news2024/10/5 10:44:51

信贷风控是数据挖掘算法最成功的应用之一,这在于金融信贷行业的数据量很充足,需求场景清晰及丰富。

信贷风控简单来说就是判断一个人借了钱后面(如下个月的还款日)会不会按期还钱。更专业来说,信贷风控是还款能力及还款意愿的综合考量,根据这预先的判断为信任依据进行放贷,以此大大提高了金融业务效率。本文内容较长,喜欢记得收藏、点赞。
图片

与其他机器学习的工业场景不同,金融是极其厌恶风险的领域,其特殊性在于非常侧重模型的解释性及稳定性。业界通常的做法是基于挖掘多维度的特征建立一套可解释及效果稳定的规则及风控模型对每笔订单/用户/行为做出判断决策。

其中,对于(贷前)申请前的风控模型,也称为申请评分卡–A卡。A卡是风控的关键模型,业界共识是申请评分卡可以覆盖80%的信用风险。此外还有贷中行为评分卡B卡、催收评分卡C卡,以及反欺诈模型等等。

A卡(Application score card)。目的在于预测申请时(申请信用卡、申请贷款)对申请人进行量化评估。B卡(Behavior score card)。目的在于预测使用时点(获得贷款、信用卡的使用期间)未来一定时间内逾期的概率。C卡(Collection score card)。目的在于预测已经逾期并进入催收阶段后未来一定时间内还款的概率。图片

一个好的特征,对于模型和规则都是至关重要的。像申请评分卡–A卡,主要可以归到以下3方面特征:

  • 1、信贷历史类:信贷交易次数及额度、收入负债比、查询征信次数、信贷历史长度、新开信贷账户数、额度使用率、逾期次数及额度、信贷产品类型、被追偿信息。(信贷交易类的特征重要程度往往是最高的,少了这部分历史还款能力及意愿的信息,风控模型通常直接就废了。)

  • 2、基本资料及交易记录类:年龄、婚姻状况、学历、工作类型及年薪、工资收入、存款AUM、资产情况、公积金及缴税、非信贷交易流水等记录(这类主要是从还款能力上面综合考量的。还可以结合多方核验资料的真伪以及共用像手机号、身份证号等团伙欺诈信息,用来鉴别欺诈风险。需要注意的,像性别、肤色、地域、种族、宗教信仰等类型特征使用要谨慎,可能模型会有效果,但也会导致算法歧视问题。)

  • 3、公共负面记录类:如破产负债、民事判决、行政处罚、法院强制执行、涉赌涉诈黑名单等(这类特征不一定能拿得到数据,且通常缺失度比较高,对模型贡献一般,更多的是从还款意愿/欺诈维度的考虑)

文章目录

    • 一、技术提升
    • 二、申请评分卡(A卡)全流程
      • 2.1 模型定义
      • 2.2 读取数据及预处理
      • 2.3 lightgbm评分卡建模
      • 2.4 LR评分卡建模
        • 2.4.1 特征选择
      • 2.4.2 卡方分箱
        • 2.4.3 WOE编码
        • 2.4.4 训练LR
        • 2.4.5 评分卡应用

一、技术提升

本文由技术群粉丝分享,项目源码、数据、技术交流提升,均可加交流群获取,群友已超过2000人,添加时最好的备注方式为:来源+兴趣方向,方便找到志同道合的朋友

方式①、添加微信号:mlc2060,备注:来自CSDN +研究方向
方式②、微信搜索公众号:机器学习社区,后台回复:加群

二、申请评分卡(A卡)全流程

实战部分我们以经典的申请评分卡为例,使用的中原银行个人贷款违约预测比赛的数据集,使用信用评分python库–toad、树模型Lightgbm及逻辑回归LR做申请评分模型。(注:文中所涉及的一些金融术语,由于篇幅就不展开解释了,疑问之处 可以谷歌了解下哈。)

2.1 模型定义

申请评分模型定义主要是通过一系列的数据分析确定建模的样本及标签。

首先,补几个金融风控的术语的说明。概念模糊的话,可以回查再理解下:

逾期期数(M) :指实际还款日与应还款日之间的逾期天数,并按区间划分后的逾期状态。M取自Month on Book的第一个单词。(注:不同机构所定义的区间划分可能存在差异) M0:当前未逾期(或用C表示,取自Current) M1:逾期1-30日 M2:逾期31-60日 M3:逾期61-90日 M4:逾期91-120日 M5:逾期121-150日 M6:逾期151-180日 M7+:逾期180日以上

观察点:样本层面的时间窗口。 用于构建样本集的时间点(如2010年10月申请贷款的用户),不同环节定义不同,比较抽象,这里举例说明:如果是申请模型,观察点定义为用户申贷时间,取19年1-12月所有的申贷订单作为构建样本集;如果是贷中行为模型,观察点定义为某个具体日期,如取19年6月15日在贷、没有发生逾期的申贷订单构建样本集。

观察期:特征层面的时间窗口。构造特征的相对时间窗口,例如用户申请贷款订前12个月内(2009年10月截至到2010年10月申请贷款前的数据都可以用, 可以有用户平均消费金额、次数、贷款次数等数据特征)。设定观察期是为了每个样本的特征对齐,长度一般根据数据决定。一个需要注意的点是,只能用此次_申请前_的特征数据,不然就会数据泄露(时间穿越,用未来预测过去的现象)。

表现期:标签层面的时间窗口。定义好坏标签Y的时间窗口,信贷风险具有天然的滞后性,因为用户借款后一个月(第一期)才开始还钱,有得可能还了好几期才发生逾期。

图片

对于现成的比赛数据,数据特征的时间跨度(观察期)、数据样本、标签定义都是已经提前分析确定下来的。但对于实际的业务来说,数据样本及模型定义其实也是申请评分卡的关键之处。毕竟实际场景里面可能没有人扔给你现成的数据及标签(好坏定义,有些公司的业务会提前分析好给建模人员),然后只是跑个分类模型那么简单。

确定建模的样本量及标签,也就是模型从多少的数据样本中学习如何分辨其中的好、坏标签样本。如果样本量稀少、标签定义有问题,那学习的结果可想而知也会是差的。

对于建模样本量的确定,经验上肯定是满足建模条件的样本越多越好,一个类别最好有几千以上的样本数。但对于标签的定义,可能我们直观感觉是比较简单,比如“好用户就是没有逾期的用户, 坏用户就是在逾期的用户”,但具体做量化起来会发现并不简单,有两个方面的主要因素需要考量:

  • 【坏的定义】逾期多少天算是坏客户。比如:只逾期2天算是建模的坏客户?

根据巴塞尔协议的指导,一般逾期超过90天(M4+)的客户,即定义为坏客户。更为通用的,可以使用“滚动率”分析方法(Roll Rate Analysis)确定多少天算是“坏”,基本方法是统计分析出逾期M期的客户多大概率会逾期M+1期(同样的,我们不太可能等着所有客户都逾期一年才最终确定他就是坏客户。一来时间成本太高,二来这数据样本会少的可怜)。如下示例,我们通过滚动率分析各期逾期的变坏概率。当前未逾期(M0)下个月保持未逾期的概率99.71%;当前逾期M1,下个月继续逾期概率为54.34%;当前M2下个月继续逾期概率就高达*90.04%*。我们可以看出M2是个比较明显的变坏拐点,可以以M2+作为坏样本的定义。图片

  • 【表现期】借贷申请的时间点(即:观察点)之后要在多久的时间暴露表现下,才能比较彻底的确定客户是否逾期。比如:借贷后观察了一个客户借贷后60天的那几个分期的表现都是按时还款,就可以判断他是好/坏客户?

这也就是确定表现期,常用的分析方法是Vintage分析(Vintage在信贷领域不仅可以用它来评估客户好坏充分暴露所需的时间,即成熟期,还可以用它分析不同时期风控策略的差异等),通过分析历史累计坏用户暴露增加的趋势,来确定至少要多少期可以比较全面的暴露出大部分的坏客户。如下示例的坏定义是M4+,我们可以看出各期的M4+坏客户经过9或者10个月左右的表现,基本上可以都暴露出来,后面坏客户的总量就比较平稳了。这里我们就可以将表现期定位9或者10个月~图片

确定了坏的定义以及需要的表现期,我们就可以确定样本的标签,最终划定的建模样本:

  • 好用户:表现期(如9个月)内无逾期的用户样本。

  • 坏用户:表现期(如9个月)内逾期(如M2+)的用户样本。

  • 灰用户:表现期内有过逾期行为,但不到坏定义(如M2+)的样本。注:实践中经常会把只逾期3天内的用户也归为好用户。

比如现在的时间是2022-10月底,表现期9个月的话,就可以取2022-01月份及之前申请的样本(这也称为 观察点),打上好坏标签,建模。

通过上面信用评分的介绍,很明显的好用户通常远大于坏用户的,这是一个类别极不均衡的典型场景,不均衡处理方法下文会谈到。图片

2.2 读取数据及预处理

本数据集的数据字典文档、比赛介绍及本文代码,可以文末获取获取图片
该数据集为中原银行的个人贷款违约预测数据集,个别字段有做了脱敏(金融的数据大都涉及机密)。主要的特征字段有个人基本信息、经济能力、贷款历史信息等等图片数据有10000条样本,38维原始特征,其中isDefault为标签,是否逾期违约。

图片

import pandas as pd
pd.set_option("display.max_columns",50)

train_bank = pd.read_csv('./train_public.csv')

print(train_bank.shape)
train_bank.head()

数据预处理主要是对日期信息、噪音数据做下处理,并划分下类别、数值类型的特征。

# 日期类型:issueDate 转换为pandas中的日期类型,加工出数值特征
train_bank['issue_date'] = pd.to_datetime(train_bank['issue_date'])
# 提取多尺度特征
train_bank['issue_date_y'] = train_bank['issue_date'].dt.year
train_bank['issue_date_m'] = train_bank['issue_date'].dt.month
# 提取时间diff # 转换为天为单位
base_time = datetime.datetime.strptime('2000-01-01', '%Y-%m-%d')   # 随机设置初始的基准时间
train_bank['issue_date_diff'] = train_bank['issue_date'].apply(lambda x: x-base_time).dt.days
# 可以发现earlies_credit_mon应该是年份-月的格式,这里简单提取年份
train_bank['earlies_credit_mon'] = train_bank['earlies_credit_mon'].map(lambda x:int(sorted(x.split('-'))[0]))
train_bank.head()


# 工作年限处理
train_bank['work_year'].fillna('10+ years', inplace=True)

work_year_map = {'10+ years': 10, '2 years': 2, '< 1 year': 0, '3 years': 3, '1 year': 1,
     '5 years': 5, '4 years': 4, '6 years': 6, '8 years': 8, '7 years': 7, '9 years': 9}
train_bank['work_year']  = train_bank['work_year'].map(work_year_map)

train_bank['class'] = train_bank['class'].map({'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'G': 6})

# 缺失值处理
train_bank = train_bank.fillna('9999')

# 区分 数值 或类别特征

drop_list = ['isDefault','earlies_credit_mon','loan_id','user_id','issue_date']
num_feas = []
cate_feas = []

for col in train_bank.columns:
    if col not in drop_list:
        try:
            train_bank[col] = pd.to_numeric(train_bank[col]) # 转为数值
            num_feas.append(col)
        except:
            train_bank[col] = train_bank[col].astype('category')
            cate_feas.append(col)
            
print(cate_feas)
print(num_feas)

2.3 lightgbm评分卡建模

如果是用Lightgbm建模做违约预测,简单的数据处理,基本上代码就结束了。lgb树模型是集成学习的强模型,自带缺失、类别变量的处理,特征上面不用做很多处理,建模非常方便,模型效果通常不错,还可以输出特征的重要性。

(By the way,申请评分卡业界用逻辑回归LR会比较多,因为模型简单,解释性也比较好)。

def model_metrics(model, x, y):
    """ 评估 """
    yhat = model.predict(x)
    yprob = model.predict_proba(x)[:,1]
    fpr,tpr,_ = roc_curve(y, yprob,pos_label=1)
    metrics = {'AUC':auc(fpr, tpr),'KS':max(tpr-fpr),
               'f1':f1_score(y,yhat),'P':precision_score(y,yhat),'R':recall_score(y,yhat)}
    
    roc_auc = auc(fpr, tpr)

    plt.plot(fpr, tpr, 'k--', label='ROC (area = {0:.2f})'.format(roc_auc), lw=2)

    plt.xlim([-0.05, 1.05])  # 设置x、y轴的上下限,以免和边缘重合,更好的观察图像的整体
    plt.ylim([-0.05, 1.05])
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')  # 可以使用中文,但需要导入一些库即字体
    plt.title('ROC Curve')
    plt.legend(loc="lower right")


    return metrics
# 划分数据集:训练集和测试集
train_x, test_x, train_y, test_y = train_test_split(train_bank[num_feas + cate_feas], train_bank.isDefault,test_size=0.3, random_state=0)

# 训练模型
lgb=lightgbm.LGBMClassifier(n_estimators=5,leaves=5, class_weight= 'balanced',metric = 'AUC')
lgb.fit(train_x, train_y)
print('train ',model_metrics(lgb,train_x, train_y))
print('test ',model_metrics(lgb,test_x,test_y))

图片

from lightgbm import plot_importance
plot_importance(lgb)

图片

2.4 LR评分卡建模

LR即逻辑回归,是一种广义线性模型,因为其模型简单、解释性良好,在金融行业是最常用的。

也正因为LR过于简单,没有非线性能力,所以我们往往需要通过比较复杂的特征工程,如分箱WOE编码的方法,提高模型的非线性能力。

下面我们通过toad实现特征分析、特征选择、特征分箱及WOE编码

2.4.1 特征选择

# 数据EDA分析
toad.detector.detect(train_bank)

# 特征选择,根据相关性 缺失率、IV 等指标
train_selected, dropped = toad.selection.select(train_bank,target = 'isDefault', empty = 0.5, iv = 0.05, corr = 0.7, return_drop=True, exclude=['earlies_credit_mon','loan_id','user_id','issue_date'])
print(dropped)
print(train_selected.shape)

# 划分训练集 测试集
train_x, test_x, train_y, test_y = train_test_split(train_selected.drop(['loan_id','user_id','isDefault','issue_date','earlies_credit_mon'],axis=1), train_selected.isDefault,test_size=0.3, random_state=0)

2.4.2 卡方分箱

# 特征的卡方分箱
combiner = toad.transform.Combiner()

# 训练数据并指定分箱方法

combiner.fit(pd.concat([train_x,train_y], axis=1), y='isDefault',method= 'chi',min_samples = 0.05,exclude=[])

# 以字典形式保存分箱结果

bins = combiner.export()

bins 

通过特征分箱,每一个特征被离散化为各个分箱。图片

接下来就是LR特征工程的特色处理了–手动调整分箱的单调性。

这一步的意义更多在于特征的业务解释性的约束,对于模型的拟合效果影响不一定是正面的。这里我们主观认为大多数特征的不同分箱的坏账率badrate应该是满足某种单调关系的,而起起伏伏是不太好理解的。如征信查询次数这个特征,应该是分箱数值越高,坏账率越大。(注:如年龄特征可能就不满足这种单调关系)

我们可以查看下ebt_loan_ratio这个变量的分箱情况,根据bad_rate趋势图,并保证单个分箱的样本占比不低于0.05,去调整分箱,达到单调性。(其他的特征可以按照这个方法继续调整,单调性调整还是挺耗时的)

adj_var = 'scoring_low'
#调整前原来的分箱 [560.4545455, 621.8181818, 660.0, 690.9090909, 730.0, 775.0]
adj_bin = {adj_var: [ 660.0, 700.9090909, 730.0, 775.0]}

c2 = toad.transform.Combiner()
c2.set_rules(adj_bin)

data_ = pd.concat([train_x,train_y], axis=1)
data_['type'] = 'train'
temp_data = c2.transform(data_[[adj_var,'isDefault','type']], labels=True)

from toad.plot import badrate_plot, proportion_plot
# badrate_plot(temp_data, target = 'isDefault', x = 'type', by = adj_var)
# proportion_plot(temp_data[adj_var])
from toad.plot import  bin_plot,badrate_plot
bin_plot(temp_data, target = 'isDefault',x=adj_var)
  • 调整前图片

  • 调整后图片

# 更新调整后的分箱
combiner.set_rules(adj_bin)
combiner.export()

图片

2.4.3 WOE编码

接下来就是对各个特征的分箱做WOE编码,通过WOE编码给各个分箱不同的权重,提升LR模型的非线性。

#计算WOE,仅在训练集计算WOE,不然会标签泄露
transer = toad.transform.WOETransformer()
binned_data = combiner.transform(pd.concat([train_x,train_y], axis=1))

#对WOE的值进行转化,映射到原数据集上。对训练集用fit_transform,测试集用transform.
data_tr_woe = transer.fit_transform(binned_data, binned_data['isDefault'],  exclude=['isDefault'])
data_tr_woe.head()

## test woe

# 先分箱
binned_data = combiner.transform(test_x)
#对WOE的值进行转化,映射到原数据集上。测试集用transform.
data_test_woe = transer.transform(binned_data)
data_test_woe.head()

2.4.4 训练LR

使用woe编码后的train数据训练模型。对于金融风控这种极不平衡的数据集,比较常用的做法是做下极少类的正采样或者使用代价敏感学习class_weight=‘balanced’,以增加极少类的学习权重。

对于LR等弱模型,通常会发现训练集与测试集的指标差异(gap)是比较少的,即很少过拟合现象。图片

# 训练LR模型
from sklearn.linear_model import LogisticRegression

lr = LogisticRegression(class_weight='balanced')
lr.fit(data_tr_woe.drop(['isDefault'],axis=1), data_tr_woe['isDefault'])

print('train ',model_metrics(lr,data_tr_woe.drop(['isDefault'],axis=1), data_tr_woe['isDefault']))
print('test ',model_metrics(lr,data_test_woe,test_y))

2.4.5 评分卡应用

利用训练好的LR模型,输出(概率)分数分布表,结合误杀率、召回率以及业务需要可以确定一个合适分数阈值cutoff (注:在实际场景中,通常还会将概率非线性转化为更为直观的整数分score=A-B*ln(odds),方便评分卡更直观、统一的应用。)

train_prob = lr.predict_proba(data_tr_woe.drop(['isDefault'],axis=1))[:,1]
test_prob = lr.predict_proba(data_test_woe)[:,1]


# Group the predicted scores in bins with same number of samples in each (i.e. "quantile" binning)
toad.metrics.KS_bucket(train_prob, data_tr_woe['isDefault'], bucket=10, method = 'quantile')

当预测这用户的概率大于设定阈值,意味这个用户的违约概率很高,就可以拒绝他的贷款申请。图片

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

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

相关文章

SQL 汇总统计及GROUP BY

SQL 汇总统计1、汇总统计2、GROUT BY3、如何对分组统计的结果进行过滤&#xff1f; GROUP BY HAVING4、如何对分组统计的结果进行排序&#xff1f;GROUP BY ORDER BY5、介绍SELECT语句中各个子句的书写顺序6、备注&#xff1a; 上方用到的表1、汇总统计 介绍几个聚集函数 有…

电脑误删Path环境变量后前端如何重新配置所需变量

需求背景 &#xff1a; 当时公司需要我们安装一款软件 &#xff0c; 按照操作文档需要配置一下 Path 环境变量 &#xff0c; 但当时的云桌面操作系统是 window7系统 &#xff0c; 当时配置时并不知道新的变量配置时需要在前面一个的后面加 “ &#xff1b; ” 来间隔开来…

【目的:windows下VS2017/2022使用MSVC编译GLFW库】

目的&#xff1a;windows下VS2017/2022使用MSVC编译GLFW库 环境&#xff1a; 系统&#xff1a;Win10 环境&#xff1a;VS2017 64bit步骤&#xff1a; 1.下载GLFW源码 官网链接https://www.glfw.org/download.html&#xff0c; 下载glfw的源码&#xff0c;解压到本地&#x…

考研数据结构大题整合_组二(TJP组)

考研数据结构大题整合 目录考研数据结构大题整合二、TJP组TJP组一TJP组二TJP组三二、TJP组 TJP组一 四、画图/计算/证明/算法分析&#xff08;30分&#xff09; &#xff08;1&#xff09;证明题&#xff08;8分&#xff09; 如果一棵树有n1个度为1的结点&#xff0c;n2个度为…

(四)Vue之数据绑定

文章目录数据绑定单向数据绑定双向数据绑定Vue学习目录上一篇&#xff1a;&#xff08;三&#xff09;Vue之模板语法 数据绑定 Vue中有2种数据绑定的方式&#xff1a; 1.单向绑定&#xff1a;数据只能从data流向页面。2.双向绑定&#xff1a;数据不仅能从data流向页面&#…

著名书画家、中国书画院院士李适中

著名书画家、中国书画院院士李适中 李适中 著名书画家、中国书画院院士 版画艺术家 文物复制专家 中国文物学会会员单位创始人 文化部科技进步奖获得者 艺术简历 李适中&#xff0c;1943年生&#xff0c;安徽颍上人&#xff0c;著名书画家、中国书画院院士。李适中先生师从著名…

Vue3+nodejs全栈项目(资金管理系统)——前端篇

文章目录创建项目项目初始化使用element-plus设置Register和404组件搭建element注册表单验证表单和按钮加载动画和消息提醒路由守卫和token过期处理配置请求拦截和响应拦截解析token并存储到vuex中设计顶部导航设置首页和个人信息设置左侧导航栏展示资金管理页面添加按钮编辑和…

返回当前系统串口名称

主要针对当前的usb转串口进行了穷举。 方便判断串口对应哪个设备。 返回串口名称 类对象&#xff0c;&#xff08;包含了参考网址&#xff0c;以及对其进行了修改&#xff0c;防止出现蓝牙端口&#xff09; using System; using System.Collections.Generic; using System.L…

VMware-KVM安装

目录 VMware-KVM安装 一、kvm虚拟化平台 KVM 网络管理&#xff08;以NAT网卡为例[ens33]&#xff09; VMware-KVM安装 一台Centos7、一个winSCP上传文件工具&#xff1b; 搭建KVM平台 一、kvm虚拟化平台 1 cat /etc/hosts ##查看主机…

ecology修改Reisn的JDK目录

修改resin运行JDK&#xff1a; 用文本编辑器打开resin/bin/resin.sh文件&#xff0c;将JAVA_HOME改为要设置的JDK路径。

springboot(spring)整合redis(集群)、细节、底层配置讲解

文章目录一.springboot整合redis.1.引入依赖.2.添加配置.3.使用封装对象举例二.细节讲解出现问题,堆外内存溢出解决方案,切换客户端三.补充原理.一.springboot整合redis. 1.引入依赖. <dependency><groupId>org.springframework.boot</groupId><artifact…

Spring中过滤器(Filter)和拦截器(Interceptor)的区别和联系解析

在我们日常的开发中&#xff0c;我们经常会用到Filter和Interceptor。有时同一个功能。Filter可以做&#xff0c;Interceptor也可以做。有时就需要考虑使用哪一个比较好。这篇文章主要介绍一下&#xff0c;二者的区别和联系。希望给大家进行选择的时候&#xff0c;提供一些帮助…

DSP/BIOS的基本介绍

DSP/BIOS的基本介绍 DSP/BIOS是一个简易的实时嵌入式操作系统&#xff0c;主要面向实时调度与同步、主机/目标系统通信&#xff0c;以及实时监测等应用&#xff0c;具有实时操作系统的诸多功能&#xff0c;如任务的调度管理、任务间的同步和通信、内存管理、实时时钟管理、中断…

(十)再探反向传播和神经网络优化

文章目录1.背景介绍2.神经网络的模型3.神经网络中的参数更新初探3.1随机查找取最优3.2局部随机查找参数更新3.3 沿着梯度反方向更新4.链式法则与反向传播5.梯度方向的参数更新策略6.学习率退火6.1学习率衰减策略基础6.2 二阶优化方法6.3自适应学习率方法参考资料欢迎访问个人网…

Java基础之接口与抽象类区别

Java基础之接口与抽象类区别一、Java基础之接口与抽象类二、抽象类和最终类三、Java移位运算符四、局部变量为什么要初始化一、Java基础之接口与抽象类 一个子类只能继承一个抽象类, 但能实现多个接口抽象类可以有构造方法, 接口没有构造方法抽象类可以有普通成员变量, 接口没…

minikube helm 安装 jenkins

文章目录1. 准备条件2. 安装 helm3. 部署 jenkins3.1 创建 namespace jenkins3.2 创建存储卷 jenkins-volume3.3 创建 service account & RBAC3.4 定制 jenkins-values.yml3.5 安装 jenkins3.6 登陆 jenkins“Jenkins是一个著名的可扩展开源 CI/CD 工具&#xff0c;用于自动…

手写数字识别Mnist数据集和读取代码分享

数据集下载 链接&#xff1a; https://pan.baidu.com/s/1qpzrSFhmyrdGmbSScN_ZXg?pwdd1ws 提取码&#xff1a;d1ws 数据集读取 from pathlib import Path import requests ​ DATA_PATH Path("data") PATH DATA_PATH / "mnist" ​ PATH.mkdir(parent…

Android Navigation基本使用

目录1. Navigation概述2. Navigation组成3. 设置环境4. 使用方法4.1. 创建导航图4.1.1. 具体操作4.2. 向Activity添加NavHost4.2.1. 通过 XML 添加4.2.2. 使用布局编辑器添加4.3. 在导航图中创建目的地4.3.1. 具体操作4.4. 连接目的地4.4.1. 具体操作4.5. 目的地之间的导航4.5.…

认识3dmax 对象属性对话框

可以从右键或编辑菜单访问此对话框&#xff1b; 在此可以查看和编辑参数&#xff0c;以确定选定对象在视口和渲染过程中的行为&#xff1b; 包含3个面板&#xff1a;常规&#xff0c;高级照明&#xff0c;用户定义&#xff1b; 常规面板包含6个组&#xff1a;对象信息&#x…

[附源码]计算机毕业设计校园疫情管理系统Springboot程序

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