迁移学习和冷启动(迁移和启发区别)
ztj100 2024-11-10 13:13 13 浏览 0 评论
? 本文是《智能风控原理、算法和工程实践》第3章学习笔记。算法推导部分较难,就没有列出来,因为我也看不懂。
冷启动
? 冷启动是指在没有或只有很少量数据的情况下,从0到1建立业务模型的过程。在风控业务中,早期缺乏数据积累,迁移学习和异常检测技术都可以用来处理部分冷启动问题。
应用场景
- 新开了某个业务,只有少量样本,需要用其他场景的数据来建模。此时其他场景为源域,新业务场景为目标域。
- 业务被迫停止3个月后重启,大部分训练样本比较老旧。大部分旧样本为源域,新的少量训练样本为目标域。
- 在某个国家开展类似国内的业务。国内业务积累的数据为源域,新国家场景为目标域。
? 概括起来,源域样本和目标域样本分布有区别,目标域样本量又不够。
概念介绍
? 迁移学习是一种通过调用不同场景中的数据来建立模型的方法。通过迁移学习可以将知识从源域迁移到目标域。
? 一个简单的例子,假如现在有大量英短银渐层和少量英短高地的图片,期望训练一个能够识别当前的猫是不是英短高地的学习器。这时可以用英短银渐层图片来训练一个卷积神经网络,并将这个网络的中间结点取出来作为目标模型的前半部分,然后在少量英短高地的样本上再继续训练学习后面的几层网络。
? 卷积神经网络前几层学习的是轮廓和局部形状等猫的共性特征,通过前面网络的学习模型就掌握了猫的共性,再通过后续网络对英短高地学习。
常见迁移学习算法
- TrAdaBoost。
? 赋予源域中的样本某种权重,使其分布靠近目标域。 - 联合分布适配方法(JDA)。
? 寻找一个低维子空间,使源域和目标域的数据样本在映射到该子空间后服从相同或相近的分布。 - 迁移极限学习机(DTELM)。
? 利用低秩矩阵重构数据点,实现域之间的鲁棒自适应。
? 第一种算法因为不在特征空间上做任何扭曲变化,可以很好地保留模型的解释性,所以应该更为广泛。第二、第三种算法在解释性上有一定不足,但不需要在目标场景有真实的样本标签,对于初期的业务支持度更好。
TrAdaBoost模型
? 将不同分布的训练集放在一起训练,这种方法也叫作基于实例的迁移学习方法。 ? TraAdaBoost是有AdaBoost演变而来。在一个包含源域训练数据和目标域样本的训练集中,TrAdaBoost会对训练样本进行权重调整。
- 对目标域样本,如果被误分类,根据目标域样本的分类错误率进行调整,增加其权重,使得下次训练时更关注错分的目标域样本。
- 对源域样本,如果被误分类,则会认为它们是与目标数据不同分布的,会降低其权重。
跨场景迁移模型
? 在新场景下开展小额现金贷产品,积累了1200条有标签的样本,尝试对原有大额产品的存量客户进行迁移。有4个在旧业务上表现较好的特征,保证原有场景和目标场景都有这个特征且含义一致。
import pandas as pd
from sklearn.metrics import roc_auc_score,roc_curve,auc
from sklearn.model_selection import train_test_split
from sklearn import metrics
from sklearn.linear_model import LogisticRegression
from sklearn.svm import LinearSVC
import numpy as np
import random
import math
from sklearn.calibration import CalibratedClassifierCV
data = pd.read_excel('./data/tra_sample.xlsx')
data.head()
? type的三种标签分别代表着目标域、源域和时间外样本集。根据标签划分样本集。
feature_lst = ['zx_score','msg_cnt','phone_num_cnt','register_days']
train = data[data.type == 'target'].reset_index().copy()
diff = data[data.type == 'origin'].reset_index().copy()
val = data[data.type == 'offtime'].reset_index().copy()
#trans_S, trans_A, label_S, label_A, test
train = train.loc[:1200]
trans_S = train[feature_lst].copy()
label_S = train['bad_ind'].copy()
trans_A = diff[feature_lst].copy()
label_A = diff['bad_ind'].copy()
val_x = val[feature_lst].copy()
val_y = val['bad_ind'].copy()
test = val_x.copy()
? 对目标域的少量样本进行拟合,结果如下:
? 训练集和时间外样本集KS相差超过10%,远高于行业要求的5%。且ROC曲线不稳定,意味着模型的泛化能力较差。
? 将源域数据和目标域数据整合到一起拟合,注意一下整合时用到的函数,结果如下:
trans_data = np.concatenate((trans_A, trans_S), axis=0)
trans_label = np.concatenate((label_A, label_S), axis=0)
? 下面使用TrAdaBoost算法,将源域数据中与目标域分布差别较大的数据设置一个很小的值,来弱化两个数据集的分布差异。 算法比较复杂,代码无法看懂,等用到的时候再回来研究。
import numpy as np
from sklearn import tree
#逻辑回归的学习率、权重的大小,影响整体收敛的快慢
#初始权重很重要
# H 测试样本分类结果
# TrainS 目标域样本
# TrainA 源域样本
# LabelS 目标域标签
# LabelA 源域标签
# Test 测试样本
# N 迭代次数
#计算weight
def calculate_P(weights, label):
total = np.sum(weights)
return np.asarray(weights / total, order='C')
#用逻辑回归作为基分类器,输出概率
def train_classify(trans_data, trans_label, test_data, P):
clf = LogisticRegression(C=0.3,class_weight = 'balanced',solver='liblinear')
clf.fit(trans_data, trans_label, sample_weight=P[:, 0])
return clf.predict_proba(test_data)[:,1],clf
#计算在目标域上面的错误率
def calculate_error_rate(label_R, label_H, weight):
total = np.sum(weight)
return np.sum(weight[:, 0] / total * np.abs(label_R - label_H))
#根据逻辑回归输出的score的得到标签,注意这里不能用predict直接输出标签
def put_label(score_H,thred):
new_label_H = []
for i in score_H:
if i <= thred:
new_label_H.append(0)
else:
new_label_H.append(1)
return new_label_H
#指定迭代次数,相当于集成模型中基模型的数量
N=500
trans_data = np.concatenate((trans_A, trans_S), axis=0)
trans_label = np.concatenate((label_A, label_S), axis=0)
row_A = trans_A.shape[0]
row_S = trans_S.shape[0]
row_T = test.shape[0]
test_data = np.concatenate((trans_data, test), axis=0)
# 初始化权重
weights_A = np.ones([row_A, 1])/row_A
weights_S = np.ones([row_S, 1])/row_S*2
weights = np.concatenate((weights_A, weights_S), axis=0)
bata = 1 / (1 + np.sqrt(2 * np.log(row_A / N)))
# 存储每次迭代的标签和bata值?
bata_T = np.zeros([1, N]) # 存每一次迭代的 error_rate / (1 - error_rate)
result_label = np.ones([row_A + row_S + row_T, N])
predict = np.zeros([row_T])
trans_data = np.asarray(trans_data, order='C')
trans_label = np.asarray(trans_label, order='C')
test_data = np.asarray(test_data, order='C')
best_ks = -1 #最优KS
best_round = -1 #最优基模型数量
best_model = -1 #最优模型
# 初始化结束
for i in range(N):
P = calculate_P(weights, trans_label)
result_label[:, i],model = train_classify(trans_data, trans_label,
test_data, P)
score_H = result_label[row_A:row_A + row_S, i]
pctg = np.sum(data.bad_ind)/len(data.bad_ind)
thred = pd.DataFrame(score_H).quantile(1-pctg)[0]
label_H = put_label(score_H,thred)
error_rate = calculate_error_rate(label_S, label_H,
weights[row_A:row_A + row_S, :])
if error_rate > 0.5:
error_rate = 0.5
if error_rate == 0:
N = i
break # 防止过拟合
# error_rate = 0.001
bata_T[0, i] = error_rate / (1 - error_rate)
# 调整目标域样本权重
for j in range(row_S):
weights[row_A + j] = weights[row_A + j] * np.power(bata_T[0, i],
(-np.abs(result_label[row_A + j, i] - label_S[j])))
# 调整源域样本权重
for j in range(row_A):
weights[j] = weights[j] * np.power(bata, np.abs(result_label[j, i] - label_A[j]))
y_pred = result_label[(row_A + row_S):,i]
fpr_lr_train,tpr_lr_train,_ = roc_curve(val_y,y_pred)
train_ks = abs(fpr_lr_train - tpr_lr_train).max()
print('test_ks : ',train_ks,'当前第',i+1,'轮')
if train_ks > best_ks :
best_ks = train_ks
best_round = i
best_model = model
? 训练结束后,用最优的逻辑回归模型对样本进行测试,结果如下:
? 该方案只使用训练过程中表现最好的学习器进行决策,因此保留了单个逻辑回归模型的解释性,对于模型上线部署没有影响。但是这也增大了过拟合的风险,在实际使用中需要权衡迭代次数。
【作者】:Labryant
【原创公众号】:风控猎人
【简介】:某创业公司策略分析师,积极上进,努力提升。乾坤未定,你我都是黑马。
【转载说明】:转载请说明出处,谢谢合作!~
相关推荐
- Vue 技术栈(全家桶)(vue technology)
-
Vue技术栈(全家桶)尚硅谷前端研究院第1章:Vue核心Vue简介官网英文官网:https://vuejs.org/中文官网:https://cn.vuejs.org/...
- vue 基础- nextTick 的使用场景(vue的nexttick这个方法有什么用)
-
前言《vue基础》系列是再次回炉vue记的笔记,除了官网那部分知识点外,还会加入自己的一些理解。(里面会有部分和官网相同的文案,有经验的同学择感兴趣的阅读)在开发时,是不是遇到过这样的场景,响应...
- vue3 组件初始化流程(vue组件初始化顺序)
-
学习完成响应式系统后,咋们来看看vue3组件的初始化流程既然是看vue组件的初始化流程,咋们先来创建基本的代码,跑跑流程(在app.vue中写入以下内容,来跑流程)...
- vue3优雅的设置element-plus的table自动滚动到底部
-
场景我是需要在table最后添加一行数据,然后把滚动条滚动到最后。查网上的解决方案都是读取html结构,暴力的去获取,虽能解决问题,但是不喜欢这种打补丁的解决方案,我想着官方应该有相关的定义,于是就去...
- Vue3为什么推荐使用ref而不是reactive
-
为什么推荐使用ref而不是reactivereactive本身具有很大局限性导致使用过程需要额外注意,如果忽视这些问题将对开发造成不小的麻烦;ref更像是vue2时代optionapi的data的替...
- 9、echarts 在 vue 中怎么引用?(必会)
-
首先我们初始化一个vue项目,执行vueinitwebpackechart,接着我们进入初始化的项目下。安装echarts,npminstallecharts-S//或...
- 无所不能,将 Vue 渲染到嵌入式液晶屏
-
该文章转载自公众号@前端时刻,https://mp.weixin.qq.com/s/WDHW36zhfNFVFVv4jO2vrA前言...
- vue-element-admin 增删改查(五)(vue-element-admin怎么用)
-
此篇幅比较长,涉及到的小知识点也比较多,一定要耐心看完,记住学东西没有耐心可不行!!!一、添加和修改注:添加和编辑用到了同一个组件,也就是此篇文章你能学会如何封装组件及引用组件;第二能学会async和...
- 最全的 Vue 面试题+详解答案(vue面试题知识点大全)
-
前言本文整理了...
- 基于 vue3.0 桌面端朋友圈/登录验证+60s倒计时
-
今天给大家分享的是Vue3聊天实例中的朋友圈的实现及登录验证和倒计时操作。先上效果图这个是最新开发的vue3.x网页端聊天项目中的朋友圈模块。用到了ElementPlus...
- 不来看看这些 VUE 的生命周期钩子函数?| 原力计划
-
作者|huangfuyk责编|王晓曼出品|CSDN博客VUE的生命周期钩子函数:就是指在一个组件从创建到销毁的过程自动执行的函数,包含组件的变化。可以分为:创建、挂载、更新、销毁四个模块...
- Vue3.5正式上线,父传子props用法更丝滑简洁
-
前言Vue3.5在2024-09-03正式上线,目前在Vue官网显最新版本已经是Vue3.5,其中主要包含了几个小改动,我留意到日常最常用的改动就是props了,肯定是用Vue3的人必用的,所以针对性...
- Vue 3 生命周期完整指南(vue生命周期及使用)
-
Vue2和Vue3中的生命周期钩子的工作方式非常相似,我们仍然可以访问相同的钩子,也希望将它们能用于相同的场景。...
- 救命!这 10 个 Vue3 技巧藏太深了!性能翻倍 + 摸鱼神器全揭秘
-
前端打工人集合!是不是经常遇到这些崩溃瞬间:Vue3项目越写越卡,组件通信像走迷宫,复杂逻辑写得脑壳疼?别慌!作为在一线摸爬滚打多年的老前端,今天直接甩出10个超实用的Vue3实战技巧,手把...
- 怎么在 vue 中使用 form 清除校验状态?
-
在Vue中使用表单验证时,经常需要清除表单的校验状态。下面我将介绍一些方法来清除表单的校验状态。1.使用this.$refs...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- Vue 技术栈(全家桶)(vue technology)
- vue 基础- nextTick 的使用场景(vue的nexttick这个方法有什么用)
- vue3 组件初始化流程(vue组件初始化顺序)
- vue3优雅的设置element-plus的table自动滚动到底部
- Vue3为什么推荐使用ref而不是reactive
- 9、echarts 在 vue 中怎么引用?(必会)
- 无所不能,将 Vue 渲染到嵌入式液晶屏
- vue-element-admin 增删改查(五)(vue-element-admin怎么用)
- 最全的 Vue 面试题+详解答案(vue面试题知识点大全)
- 基于 vue3.0 桌面端朋友圈/登录验证+60s倒计时
- 标签列表
-
- idea eval reset (50)
- vue dispatch (70)
- update canceled (42)
- order by asc (53)
- spring gateway (67)
- 简单代码编程 贪吃蛇 (40)
- transforms.resize (33)
- redisson trylock (35)
- 卸载node (35)
- np.reshape (33)
- torch.arange (34)
- node卸载 (33)
- npm 源 (35)
- vue3 deep (35)
- win10 ssh (35)
- exceptionininitializererror (33)
- vue foreach (34)
- idea设置编码为utf8 (35)
- vue 数组添加元素 (34)
- std find (34)
- tablefield注解用途 (35)
- python str转json (34)
- java websocket客户端 (34)
- tensor.view (34)
- java jackson (34)