算法模型离线评估方案

  • 1 引言
  • 2需求背景
  • 3特征评估
    • 3.1特征表维护
    • 3.2样本频率分布直方图概览
    • 3.3Pearson相关系数计算
    • 3.4缺失率计算
  • 4模型评估
    • 4.1模型离线AUC评估
      • 4.1.1什么是AUC
      • 4.1.2AUC的优势:
    • 4.2TensorBoard可视化
      • 4.2.1项目中集成tensorboard
      • 4.2.2启动tensorboard命令
      • 4.2.3可视化效果
    • 4.3离线实验记录表
      • 4.3.1训练测试集切分代码
    • 4.4线上推理接口时间评估
    • 4.5HTTP接口并发测试
  • 5AB实验
    • 5.1线上AUC计算
    • 5.2实验收益统计
  • 6工业Tricks分享
    • 6.1AUC提升和业务指标不一致问题
    • 6.2经验汇总

引言

该文档阐述了算法从开始迭代到上线前的一些工作流程。

首先第一需求背景。我们需要清楚本次迭代的需求背景。

第二特征评估。抽取样本,进行特征评估,主要用单特征AUC和缺失率着两个指标进行评估,确保数据没有异常。

第三模型评估,包括多次实验,对模型的AUC和接口的耗时这两个指标进行评估

第四AB实验,主要通过AB实验来对比评估,用CTR进行评估。

Demo代码地址:http://172.29.28.203:8888/lab/tree/wangyongpeng/global_search_rank_ctr/model_eval.ipynb

需求背景

描述本次上线的改动点、背景。例如:

为了捕捉用户对物料的兴趣偏好,加入了用户对物料的点击率特征(user_item_ctr)

特征评估

特征评估有很多种方式,主要包括两大类,特征和特征直接的相关性分析,特征和标签之间的相关性分析,特征和标签的分析方法包括:单特征AUC评估、Pearson系数、GBDT训练得到特征重要性等方法。

特征表维护

需要维护一张模型用到的特征列表,包含四个信息(特征名,特征含义,单特征AUC,特征缺失率)。

这张表可以帮助我们在每次迭代的时候,发现数据问题。比如缺失率突然升高,说明我们数据关联发生问题。不容易漏掉特征。

实例如下:

特征名

含义

Pearson相关性系数

缺失率

是否上线

备注

age用户的年龄

-0.04009939333393429

100%N缺失率100%,不作为特征使用
sex性别

-0.039342348680731327

17.47%
Y
role角色

-0.033291028680731327

0.0%
Y
total_show展示次数

-0.02418875134961658

0.0%
Y
total_click物料总点击

-0.07942286768376286

0.0%
Y
total_vote物料总点赞

-0.04246059351624654

0.0%
Y
total_collection物料总收藏

-0.043361133083929235

0.0%
Y
total_comment物料总评论

-0.023291028680731327

0.0%
Y
total_share物料总分享

-0.04204700458418045

0.0%
Y

样本频率分布直方图概览

如果想看细节的一些具体数值,就可以用以下代码仔细的看。

1

2

3

4

5

%matplotlib inline

import matplotlib.pyplot as plt

import pandas as pd

num_train_data['total_share'].hist(bins=100)

可视化完的结果如下,因为样本异常差异太大,可视化出来不美观。其表示的是我们应该在后续的特征工程阶段,将这些异常值进行范围限定

Pearson相关系数计算

Pearson相关系数的范围是在[-1,1]之间,下面给出Pearson相关系数的应用理解:
假设有X,Y两个变量,那么有:
(1) 当相关系数为0时,X变量和Y变量不相关;
(2) 当X的值和Y值同增或同减,则这两个变量正相关,相关系数在0到1之间;
(3) 当X的值增大,而Y值减小,或者X值减小而Y值增大时两个变量为负相关,相关系数在-1到0之间。
注:相关系数的绝对值越大,相关性越强,相关系数越接近于1或-1,相关度越强,相关系数越接近于0,相关度越弱。通常情况下通过以下取值范围判断变量的相关强度:
0.8-1.0 极强相关
0.6-0.8 强相关
0.4-0.6 中等程度相关
0.2-0.4 弱相关
0.0-0.2 极弱相关或无相关

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

%matplotlib inline

import seaborn as sns

import matplotlib.pyplot as plt

from pyhive import hive

import pandas as pd

import numpy as np

conn = hive.Connection(host='172.30.2.60', port=10000, database='recsys')

train_sql = """select * from recsys.search_full_link_30d  where resource_type='VIDEO' limit 10000"""

train_data = pd.read_sql(train_sql, conn)

conn.close()

train_data.columns = [i.split('.')[1for in list(train_data.columns)]

# 输入特征列和标签列,输出列名对应的皮尔逊系数

# 分别计算每个特征与标签的相关系数

from scipy.stats import pearsonr

def calc_pearsonr(dataframe, col_name, label_name):

     

    = dataframe[col_name].values

    label = dataframe[label_name].values

    = pearsonr(x, label)[0]

    print("%s 和Label的系数 = %s"%(col_name, p))

train_data_fillna = train_data.fillna(0)

featureCols =['total_show''total_click''total_share''total_vote',

       'total_collection''total_comment']

for col in featureCols:

    calc_pearsonr(train_data_fillna, col, 'click_label')

# total_show 和Label的系数 = -0.02418875134961658

# total_click 和Label的系数 = -0.07942286768376286

# total_share 和Label的系数 = -0.04204700458418045

# total_vote 和Label的系数 = -0.04246059351624654

# total_collection 和Label的系数 = -0.043361133083929235

# total_comment 和Label的系数 = -0.023291028680731327

缺失率计算

计算样本中,某列值得缺少情况,可以判断样本中存在的问题

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

import pandas as pd

mHeader = ['age','city_id','hospital_id']

rowDF = pd.read_csv('./data/raw_data.csv', sep=',', skiprows=[0],names=mHeader)

  

# 传入列表头,输出特征的缺失率

def get_null_rate(featureCol, DF):

    # 统计每列的缺失率,获取总数

    totalRows = DF.shape[0]

    tempCount = 1-(DF[featureCol].where(DF[featureCol] != -1.0).count()/totalRows)

    return round(tempCount*1002)

  

featureCols = ['age','city_id','hospital_id']

  

for col in featureCols:

    print('{}={}%'.format(col, get_null_rate(col, rowDF)))

# 输出结果

# age=14.65%

# city_id=15.27%

# hospital_id=14.44%

模型评估

模型离线AUC评估

先简单介绍一些AUC的概念

什么是AUC

  • 其本身含义是正负样本之间预测的gap越大,auc越大.

  • 随机抽出一对样本(一个正样本,一个负样本),然后用训练得到的分类器来对这两个样本进行预测,预测得到正样本的概率大于负样本概率的概率。

AUC的优势:

AUC的计算方法同时考虑了分类器对于正例和负例的分类能力,在样本不平衡的情况下,依然能够对分类器作出合理的评价。且AUC对均匀正负样本采样不敏感。

以下代码是模型中设置评估指标的代码,metrics可以自己改动根据相应的场景进行设置。

1

2

3

4

5

6

model = DeepFM(linear_feature_columns,dnn_feature_columns,task='binary', dnn_hidden_units=(643216))

    model.compile("adam""binary_crossentropy",

                  metrics=['binary_crossentropy','AUC'], )

    history = model.fit(train_model_input, train['click_label'].values,

                        batch_size=32, epochs=10, verbose=2, validation_split=0.2, )

TensorBoard可视化

项目中集成tensorboard

下面代码是将模型训练的过程保存在"./tensorboard_logs"这个目录中。

1

2

3

4

5

6

7

model = DeepFM(linear_feature_columns,dnn_feature_columns,task='binary', dnn_hidden_units=(643216))

model.compile("adam""binary_crossentropy",

              metrics=['binary_crossentropy','AUC'], )

tf_callback = tf.keras.callbacks.TensorBoard(log_dir="./tensorboard_logs")

history = model.fit(train_model_input, train['click_label'].values,

                    batch_size=512, epochs=20, verbose=1, validation_split=0.1, callbacks=[tf_callback])

启动tensorboard命令

tensorboard --logdir tensorboard_logs/ --port 8081

可视化效果

下图显示的是在每次迭代中,AUC的变化曲线

离线实验记录表

这部分主要的目的就是新旧模型的PK,新增特征前后的PK,前提是在同一份测试集上。这部分可能会有很多次实验。在训练阶段,我们应该形成如下的记录,其中:

  • 训练集:54天的数据作为训练数据
  • 测试集:一周,7天的数据进行测试

训练测试集切分代码

如下代码是按照天数进行对数据进行切分,先获取数据集中的最大日期,然后7天前的作为训练集,7天后的作为测试集。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

# 切分时间的函数

def split_data_by_dt(dataframe):

    # 先获取最大的时间

    max_dt = dataframe['log_date'].max()

    # 得到分割时间

    dt = datetime.datetime.strptime(max_dt, "%Y-%m-%d")

    split_date = (dt + datetime.timedelta(days=-7)).strftime("%Y-%m-%d")

    # where条件区分训练测试集, 去空

    test = dataframe.where(dataframe['log_date'] > split_date)

    test = test.dropna(how='all')

    train = dataframe.where(dataframe['log_date'] <= split_date)

    train = train.dropna(how='all')

    # 返回训练测试集

    print("训练数据量 = " + str(train.shape))

    print("测试数据量 = " + str(test.shape))

    return train, test

实验

改动点

参数

样本数据

离线AUC

备注

Base组线上版本

hidden_units=[64, 32, 16]

epochs=20

batch_size=512

训练:20220906~2022-10-30

测试:2022-10-30~20221106

0.7323线上基础版本的情况
实验组增加特征

hidden_units=[64, 32, 16]

epochs=20

batch_size=512

训练:20220906~2022-10-30,(54天),302431条数据

测试:2022-10-30~20221106,(7天),37403条数据

0.7486AUC提升+0.0163,提升巨大,可以上线

线上推理接口时间评估

模型性能主要包括接口线上预测的响应时长。响应时长在200ms以内可接受。

该时间是指接口整体的响应时间,在测试环境中,响应时长是指五次请求的平均响应时间(不包含第一次请求)

记录响应时间的代码如下,通过time.time()方法实现:

1

2

3

4

5

6

7

8

9

10

11

@app.route("/citizen_search_rank_ctr", methods=["GET"])

def search_rank_ctr():

    total_start_time = time.time()

    aa = rank(user_id, resource_ids, resource_type)

    total_end_time = time.time()

    print("====================== total time = %s======================"%int((total_end_time-total_start_time)*1000))

    return aa

     

if __name__ == '__main__':

    # 模型部署

    app.run(host='0.0.0.0', threaded=True, port=5012)

响应时长在现有场景主要包含三部分:从redis获取特征、模型预测、其他三个方面的耗时。响应时长如下可以从控制台日志得到。

1

2

3

4

5

curl -G -d 'user_id=61110e6ce4b0fe63c65be1c2' -d 'resource_id_list=31662,31767,31672,33381,33742,31292,31706,33559,31613,31516,32569,24908,33731,33734,33774,33128,32546,31731,25866,33808' -d 'resource_type=VIDEO' http://172.16.68.209:6058/global_search_ranking

# ====================== get feature from redis time = 19======================

# ====================== pridict time = 12======================

# ====================== total time = 34======================

我们将上面的数据进行整理可以得到如下表格,可以从数据我们得到,模型在测试环境相应时间为34ms, 符合200ms要求,可以上线。

总耗时

redis获取特征

推理预测

其他

耗时34ms19ms12ms3ms

HTTP接口并发测试

压测我们采用ApacheBench,简称ab,压测命令如下,从压测结果看,我们的接口可以支持5000日活的没有压力,但是想更多,就需要更多的机器进行负载。

1

ab -n 10000 -c 5000 -r http://172.16.68.209:6058/global_search_ranking?user_id=61110e6ce4b0fe63c65be1c2&resource_id_list=31662,31767,31672,33381,33742,31292,31706,33559,31613,31516,32569,24908,33731,33734,33774,33128,32546,31731,25866,33808&resource_type=VIDEO

其中:

  • -n 后面的1000,表示总共发出1000 0个请求;
  • -c 后面的5000 ,表示采用5000个并发(模拟 5000个人同时访问)

测试完后会有如下评估报告:

指标

备注

Complete requests10000总请求数
Failed requests2失败次数(Connect: 0, Receive: 0, Length: 2, Exceptions: 0)
Time per request0.591 [ms]请求平均时长

AB实验

线上AUC计算

线上AUC计算,是全量之前重要的一步,线上AUC可以直接单向的反映模型上线后收益是正向还是负向。
计算方式是拿到线上点击标签,模型线上打分分数,根据predict分数和label来计算线上的AUC

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

import pandas as pd

import numpy as np

from sklearn.metrics import *

pd.set_option('display.max_columns'None)

pd.set_option('display.max_rows'None)

from sklearn.metrics import roc_auc_score

mHeader = ['label''score']

expDF = pd.read_csv('./data/exp2022-11-24.csv' , sep='\t', skiprows=[0,1], names=mHeader)

baseDF = pd.read_csv('./data/base2022-11-24.csv', sep='\t', skiprows=[0,1], names=mHeader)

# 删除空值和设置label

expDF = expDF.dropna()

baseDF = baseDF.dropna()

= expDF['label'].values

pred = expDF['score'].values.reshape(-1,1)

exp_auc = roc_auc_score(y, pred)

y_base = baseDF['label'].values

pred_base = baseDF['score'].values.reshape(-1,1)

base_auc = roc_auc_score(y_base, pred_base)

print("计算实验组合Base组的AUC : base_auc = %s, exp_auc = %s" %(base_auc, exp_auc))

实验收益统计

在全量上线之前,应该先小流量进行对比,先上50%流量进行统计计算,连续观察4天(上线当天不算),如果点击率高,实验正向,就可以上线全量。

日期AB组showUVclickCTR(click/show)
20221101Base3839045000049500.011205926
20221102Base3940504983743020.007636087
20221103Base3398763992030090.009983053
20221104Base3398744009233930.014564221
20221101Exp4998775670049500.010198509
20221102Exp498385098750980.080440628
20221103Exp599875098840090.099821628
20221104Exp3998744005259880.014974717
平均Base36442644962.253913.50.010847322
平均Exp499502.2549681.755261.250.011301451
预计全量后

点击率提升+4.19%

工业Tricks分享

AUC提升和业务指标不一致问题

在实际的工作中,常常是模型迭代的auc比较,即新模型比老模型auc高,代表新模型对正负样本的排序能力比老模型好。理论上,这个时候上线abtest,应该能看到ctr之类的线上指标增长。

但是经常会出现线下AUC提升明显,线上AUC或者业务指标负向的情况,这个时候可以排查线上线下一致性。

经验汇总

  1. learning_rate:学习率(learning_rate)越小,模型AUC越高,但是训练速度会变慢,我们需要取一个平衡。我会通常设置learning_rate=0.0007
  2. epoch:epoch是指对训练集反复训练多少次,一般理想情况下AUC随着迭代的次数而升高,我的经验值是epoch = 20
  3. 神经网络层的大小只会影响训练的时长,并不会影响线上预测的时长
  4. AUC的大小和正负样本的采样无关
  5. 数值型特征进行分桶,转化为类别型特征会更好一下,有利于模型分类

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

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

相关文章

SpringBoot SpringMVC (详解)

6. SpringBoot Spring 的诞⽣是为了简化 Java 程序的开发的&#xff0c;⽽ Spring Boot 是为了快速开发 Spring 程序开发而诞生的。 Spring Boot 的优点&#xff1a; 快速集成框架&#xff0c;Spring Boot 提供了启动添加依赖的功能&#xff0c;⽤于秒级集成各种框架。内置运⾏…

JAVA WEB 能够实现整个文件夹的上传下载吗?

导入项目&#xff1a; 导入到Eclipse&#xff1a;导入项目 导入到IDEA&#xff1a;导入项目 springboot统一配置&#xff1a;springboot-配置 下载示例&#xff1a; https://gitee.com/xproer/up6-jsp-eclipse/tree/6.5.40/ 工程 NOSQL NOSQL示例不需要任何配置&#xff0c;可…

【面试经典150 | 】最长递增子序列

文章目录 Tag题目来源解题思路方法一&#xff1a;动态规划 写在最后 Tag 【动态规划】【数组】 题目来源 300. 最长递增子序列 解题思路 方法一&#xff1a;动态规划 定义状态 dp[i] 表示以位置 i 对应整数为末尾的最长递增子序列的长度。 状态转移 我们从小到大计算 dp…

FASTAPI系列 16-其他响应类型

FASTAPI系列 16-其他响应类型 文章目录 FASTAPI系列 16-其他响应类型前言一、HTMLResponse 响应 HTML二、纯文本响应三、另外的JSON 响应四、FileResponse文件五、StreamingResponse六、RedirectResponse 重定向请求总结更多内容&#xff0c;请关注公众号, 发送666 更可以得到免…

解决配置文件中文乱码

一、问题 二、解决方法

HTML5+CSS3小实例:文字边框视觉错位

实例:文字边框视觉错位 技术栈:HTML+CSS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scal…

StringRedisTemplate与RedisTemplate详解【序列化的方式不同】

spring 封装了 RedisTemplate 对象来进行对redis的各种操作&#xff0c;它支持所有的 redis 原生的 api。在RedisTemplate中提供了几个常用的接口方法的使用&#xff0c;分别是: private ValueOperations<K, V> valueOps; private HashOperations<K, V> hashOps; …

TLSR8258 MTU、DLE(PDU)

本文基于泰凌微TLSR8258 M1S1 demo。 1.DLE&#xff1a;LE Data Packet Length Extension 中文全称&#xff1a;低功耗蓝牙数据包长度扩展。 这是一个在2014年12月2日正式发布的bluetooth for BLE添加的新特性&#xff0c;以支持在LL Data PDU更长的数据&#xff0c;最大支持…

自己编译SQLite或将SQLite移植到新的操作系统(六)

返回&#xff1a;SQLite—系列文章目录 上一篇:SQLite中的动态内存分配&#xff08;五&#xff09; 下一篇&#xff1a;SQLite—系列文章目录 1.0 引言 对于大多数应用程序&#xff0c;推荐的构建方法 SQLite是使用合并代码 文件 sqlite3.c 及其相应的头文件 sqlite3.…

刚刚,百度和苹果宣布联名

百度 Apple 就在刚刚&#xff0c;财联社报道&#xff0c;百度将为苹果今年发布的 iPhone16、Mac 系统和 iOS18 提供 AI 功能。 苹果曾与阿里以及另外一家国产大模型公司进行过洽谈&#xff0c;最后确定由百度提供这项服务&#xff0c;苹果预计采取 API 接口的方式计费。 苹果将…

Jenkins用户角色权限管理

Jenkins作为一款强大的自动化构建与持续集成工具&#xff0c;用户角色权限管理是其功能体系中不可或缺的一环。有效的权限管理能确保项目的安全稳定&#xff0c;避免敏感信息泄露。 1、安装插件&#xff1a;Role-based Authorization Strategy 系统管理 > 插件管理 > 可…

Docker 哲学 - Dockerfile 指令

Dockerfile 的 entrypoint 和 cmd 书写方式一样吗&#xff0c;分别用一个node项目的 demo来举例 Dockerfile 的 entrypoint 、cmd 有什么区别&#xff0c;分别举例他们同时出现的场景和 单独出现的场景 entrypoint 和 cmd 命令&#xff1a; 同时出现&#xff1a; 1、cmd 作为 e…

【教程】iOS如何抓取HTTP和HTTPS数据包经验分享

&#x1f4f1; 在日常的App开发和研发调研中&#xff0c;对各类App进行深入的研究分析时&#xff0c;我们需要借助专业的抓包应用来协助工作。本文将介绍如何使用iOS手机抓包工具来获取HTTP和HTTPS数据包&#xff0c;并推荐一款实用的抓包应用——克魔助手&#xff0c;希望能够…

快速上手Pytrch爬虫之爬取某应图片壁纸

一、前置知识 1 爬虫简介 网络爬虫&#xff08;又被称作网络蜘蛛、网络机器人&#xff0c;在某些社区中也经常被称为网页追逐者)可以按照指定的规则&#xff08;网络爬虫的算法&#xff09;自动浏览或抓取网络中的信息。 1.1 Web网页存在方式 表层网页指的是不需要提交表单&…

《数据结构学习笔记---第三篇》---单链表具体实现

目录 1.链表 1.1 链表的概念及结构 2.不带头单链表的实现 2.1创建头文件“SList.h” 2.2 创建具体接口实现文件SList.c 2.2.1打印 2.2.2申请链表结点 2.2.3创建一个长度为n的链表 2.2.4尾插尾删 2.2.5头插头删 2.2.6寻找x元素&#xff0c;返回pos 2.2.7插入和删除pos…

量子专家联合开展欧洲之星项目“SupremeQ”以实现光量子计算优势

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 编辑丨王珩 编译/排版丨浪味仙 沛贤 深度好文&#xff1a;1800字丨10分钟阅读 近日&#xff0c;英国全栈光量子计算系统公司 ORCA Computers、德国单光子探测器提供商 Pixel Photonics、丹麦量…

餐饮服务升级:微信小程序扫码点餐制作

餐饮体验的升级不仅体现在食物的质量和环境的营造上&#xff0c;更在于服务的便捷性和智能化。扫码点餐小程序正是这一理念的体现&#xff0c;它通过简化点餐流程&#xff0c;为顾客和商家带来了双赢的局面。那么商家微信小程序扫码点餐制作的流程是怎么样呢&#xff1f;怎么快…

二叉树的遍历及线索二叉树试题解析

一、单项选择题 01.在下列关于二叉树遍历的说法中&#xff0c;正确的是( C ). A.若有一个结点是二叉树中某个子树的中序遍历结果序列的最后一个结点&#xff0c;则它一定是该子树的前序遍历结果序列的最后一个结点 B.若有一个结点是二叉树中某个子树的前序遍历结果序列的最后一…

安卓国内ip代理app,畅游网络

随着移动互联网的普及和快速发展&#xff0c;安卓手机已经成为我们日常生活和工作中不可或缺的一部分。然而&#xff0c;由于地理位置、网络限制或其他因素&#xff0c;我们有时需要改变或隐藏自己的IP地址。这时&#xff0c;安卓国内IP代理App便成为了一个重要的工具。虎观代理…

Chrome之解决:浏览器插件不能使用问题(十三)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…