一、机器学习&深度学习
一、数据预处理
1、常见分桶的方式
- 等距分桶。每个桶的宽度是固定的,即值域范围是固定的,比如是 0-99,100-199,200-299等;这种适合样本分布比较均匀的情况,避免出现有的桶的数量很少,而有的桶数量过多的情况;
- 等频分桶,也称为分位数分桶。也就是每个桶有一样多的样本,但可能出现数值相差太大的样本放在同个桶的情况;
- 模型分桶。使用模型找到最佳分桶,比如聚类,将特征分成多个类别,或者树模型,这种非线性模型天生具有对连续型特征切分的能力,利用特征分割点进行离散化。
2、分桶的优点
- 分桶后得到的稀疏向量,内积乘法运算速度更快,计算结果更方便存储;
- 对异常数据有很强的鲁棒性;
- 离散后特征可以进行特征交叉,提升表达能力,由 M+N 个变量编程 M*N 个变量,进一步引入非线形,提升了表达能力;
- 特征离散后模型更稳定,如用户年龄区间,不会因为用户年龄长了一岁就变化;
二、特征选择
三、特征重要度评估
四、排序模型
1、使用 deepFM 的时候是如何处理欠拟合和过拟合问题的
欠拟合:增加deep部分的层数,增加epoch的轮数,增加learningrate,减少正则 化力度
过拟合:在deep层直接增加dropout的率,减少epoch轮数,增加更多的数据,增 加正则化力度,shuffle 数据
待看:
FM瑞士军刀:FM:推荐算法中的瑞士军刀 - 知乎
2、LR中连续特征为什么要做离散化?
1、数据角度:离散化的特征对异常数据有很强的鲁棒性;离散化特征利于进行特征交叉。
2、模型角度:当数据增加/减少时,利于模型快速迭代;离散化相当于为模型引入非线性表达;离散化特征简化了模型输入,降低过拟合风险;LR中离散化特征很容易根据权重找出bad case。
3、计算角度:稀疏向量内积计算速度快。(在计算稀疏矩阵内积时,可以根据当前值是否为0来直接输出0值,这相对于乘法计算是快很多的。)
而离散化连续值特征后同样会带来一些缺点,如下:
1、不合理的区间划分容易降低模型表达能力,构造合理的区间划分同样比较困难(需要从区间数、区间分段大小、区间内样本分布进行权衡)。
2、如果连续特征x对y有着很强的先验知识(如强线性关系),离散化后会使x的信息表达能力损失。
五、其他算法常见问题
1、线上线下效果不一致的原因
1)首先对齐线上线下数据的预处理是否一致
2)数据分布不一致
3)是否存在数据穿越
4)离线评估的auc,所有user和所有item之间的关系,改成gauc
二、大数据基础
一、海量数据处理问题
1、海量日志数据,提取出某日访问百度次数最多的那个IP。
算法思想:分而治之+hashmap+排序
1.IP地址最多有2^32=4G种取值情况,所以不能完全加载到内存中处理;
2.可以考虑采用“分而治之”的思想,按照IP地址的Hash(IP)%1024值,把海量IP日志分别存储到1024个小文件中。这样,每个小文件最多包含4MB个IP地址;
3.对于每一个小文件,可以构建一个IP为key,出现次数为value的Hash map,同时记录当前出现次数最多的那个IP地址;
4.可以得到1024个小文件中的出现次数最多的IP,再依据常规的排序算法得到总体上出现次数最多的IP;
2、海量数据的Top-K问题
方法一:分治思想/Hash映射 + HashMap统计 + 堆/快速/归并排序
第一步:针对数据太大,内存受限,只能是:把大文件取模映射成小文件;如果内存足够,直接hashTable统计,然后排序。
第二步:使用HashMap统计每个词的出现次数;
第三步:借助堆结构,我们可以在log量级的时间内查找和调整/移动。
3、海量数据-找出2.5亿个数中不重复的整数
方法1:内存充足用字典结构:o(n2)
对2.5亿个数中的每一个数,出现一次,字典对应的值+1。
最后遍历字典,找出value为1的所有key。
方法2:内存不足:分治+hashmap
hash分到不同的批次,每批次遍历一遍,存入hashmap<出现的数字,出现的次数>,读出次数大于1的去除掉,剩下的就是重复数据;遍历两次,时间复杂度O(n2)
改成存到set(),遍历一遍,时间覆盖度O(N)
方法3:内存不足用bool数组
初始化一个(2.5*10^8) * 2 bool数组,并且初始化为False,对于每一个整数。
使用两个bit,来表示它出现的次数:
0 0:出现0次
0 1:出现一次
1 1:出现多次
4、HIVE数据倾斜的表现、原因、解决办法
4.1 表现:任务卡在一个或几个reduce阶段,执行进度为99%
涉及distinct、group by、 join on 等会触发shuffle操作:所有key被拉到一个或多个Reducer节点上,容易发生数据倾斜
4.2 原因:根本原因数据分布不均匀,大量数据分配到一个节点
1)包含大量为null的数据,会被hash成同一个key
2)不同数据类型关联(缺失值为null和缺失值为0的字段关联)
int字段关联string字段,所有string类型的数据会被分hash到同一个id,故分配到同一个reducer上
3)小表join大表,但小表的key比较集中,shuffle阶段只分发到一个或者几个reducer上
4.3 解决办法
1)参数调优
hive阶段开启聚合操作 hive.map.aggr=true
mapred.reduce.tasks 增加reducer个数
开启数据倾斜时负载均衡 hive.groupby.skewindata=true
2)做好列裁剪和filter操作
3)大小表join使用MAPJOIN
小表关联一个超大表时,容易发生数据倾斜,使用 MapJoin把小表全部加载到内存在map端进行join。如果需要的数据在 Map 的过程中可以访问到则不再需要Reduce。
语法很简单只需要在SELECT 后增加 /*+ MAPJOIN(小标) */,把需要分发的表放入到内存中。
4)大表join大表
开启数据倾斜的join运行时优化
set hive.optimize.skewjoin=true;
set hive.optimize.skewjoin.compiletime=true;
5)过滤null或者是给null附上随机值
5、SPARK数据倾斜的表现、原因、解决办法
5.1 表现:
绝大多数task执行得都非常快,但个别task执行极慢。【定位问题:查看task运行时间和数据量】
5.2 原因:数据分配不均匀
5.3解决办法:
1)增加shuffle的并行度 spark.sql.shuffle.partitions,默认200
2)大表join小表,使用broadcast
broadcast原理:将较小RDD中的数据直接通过collect算子拉取到Driver端的内存中来,然后对其创建一个Broadcast变量,广播给其他Executor节点,直接与当前RDD中的每一条数据按照key进行对比,链接,避免shuffle操作。
参考:数据倾斜(五):Spark是如何解决数据倾斜的 - 简书
3)开启AE调优
AE介绍:Adaptive Execution 将可以根据执行过程中的中间数据优化后续执行,从而提高整体执行效率。
spark.sql.adaptive.enabled=True 是否开启AE
Spark.sql.adaptive.skewedJoin.enabled=True 是否自动处理join时数倾斜
Adaptive Execution 可解决 Join 时数据倾斜问题。
其思路可理解为将部分倾斜的 Partition (倾斜的判断标准为该 Partition 数据是所有 Partition Shuffle Write 中位数的 N 倍) 进行单独处理
6、mapreduce过程
大数据开发
一、用户留存率
1、每个用户最早登录日期,可用partion by (user_id,login_date,first_login_date)
2、关联登录表,关联id为user_id,当前登录日期和最早登录日期的差值,1天,7天,30天等
3、计算首次登录用户数,次日留存,7日,30日留存数,求留存率 (group by 首次登录日期)
二、连续登录
1、开窗函数+便宜函数lead(偏移量设置为2)
2、开窗函数+row_number(登录时间-注册时间=rnk,求符合条件的最大的rnk)
【近期待整理】
待整理:
1、两种算子
collect() => list
collectAsMap() => dict
2、python 字典排序方式
sortedList = sorted(cateCountMap.items(), key=lambda item: item[1], reverse=True)
3、sparksession共享文件:
spark.sparkContext.addFile('dict/dict_tmp1.txt')
4、sparksession共享变量
broadcast
5、使用Pandas_UDF改造pandas代码
panda_udf与groupBy().apply()一起使用:
1)用pandas_udf定义一个函数,实现分组映射,每个分组对应一个函数,函数的输入和输出都是pandas.DataFrame
2)通过groupBy().apply()将返回一个pyspark的dataframe
6、reduceByKey、groupByKey和groupBy的区别
1)reduceByKey、groupByKey:
reduceByKey和groupByKey都存在shuffle的操作,但是reduceByKey可以在shuffle前对分区内相同key的数据进行预聚合(combine)功能,这样会减少落磁盘的数据量(io);而groupByKey只是进行分组,不存在数据量减少的问题,reduceByKey的性能高。
reduceByKey其实包含分组和聚合的功能。groupByKey只能分组,不能聚合。所以在分组聚合的场合下,推荐使用reduceByKey,而仅仅只是分组而不需要聚合的,那么只能使用groupByKey。
2)groupByKey和groupBy:
1、groupBy不用考虑数据格式,而groupByKey必须是kv数据格式
2、groupBy需要指定分组规则,而groupByKey是根据key对value分组
3、返回值类型不同,groupBy是将整条数据放在集合中,后面跟聚合操作,groupByKey只是将value放在集合中
7、linux三剑客
grep 更适合单纯的查找或匹配文本
sed 更适合编辑匹配到的文本
awk 更适合格式化文本,对文本进行较复杂格式处理