为什么要做特征生成?

特征生成的目的是为了把人的先验知识通过特征的方式注入模型中。

什么时候做特征生成?

优先使用直接观测或收集到的特征,而不是创造特征。
如果模型性能不好,再考虑特征生成。

Tips:

对于聚类任务,尽量少的创造特征。
	因为聚类没有明确目标,而创造的特征又是目的性的,所以二者有冲突。
对于分类和回归任务则尽量多的创造特征。
	分类和回归任务的目标明确,因此可以把人工对任务的理解的一些知识加入,有助于更好的达成这个目标。

特征生成的常用方法:

用人类可理解的方式对已有特征进行组合或修改来得到新特征。
	1变多------比如把基于天的时间特征变成早上,上午,下午,晚上这样的category特征并替换原时间特征(替换原特征)
	多变少------比如可以把国家,省,市三个特征变成经纬度2个特征并追加(追加新特征)
合并category特征的稀疏类别:
	如果某category特征的一些类别只有很少数量的样本,可以将这些类别统一归并成一大类“Other”。
时间窗口内的统计聚合特征:
	单个特征的统计聚合量:比如count,min,max,sum,average
基于category特征的某个枚举值计算连续特征或者其他category特征的一些统计量,常见的分组统计量如下:
	分组统计中位数:比如不同公司职员的工资的中位数。
	分组统计算术平均数:比如顾客平均每次的购买金额。
	某段时间内的分组统计众数:比如某类客户一周内购买商品类型的众数。
通过特征之间的语义来进行加减乘除创造新的特征。
	特征相减:比如根据房屋的建造时间和购买时间的差来得到房屋购买时的年限。
	特征相加:比如想要通过预售数据来预测收入,通过sales_blue_pens和sales_black_pens相加,可以得到sales_pens的总销量。
	特征相乘:比如可以通过售价和成交率相乘来得到新的特征earnings。
	特征相除:比如可以通过点击次数和网页曝光次数相除来得到点击率。
根据对业务的理解,把先验知识作为新的特征加入数据集
	比如一些衣服会根据季节不同销量不同,那需要把季节特征加入进来。
通过机器学习算法来构造新特征。
	比如聚类算法和主题模型来提取隐特征。
	比如通过GDBT在每棵树的输出的叶子节点的索引来构造新特征。
考虑交叉特征,尤其是在推荐系统和广告点击预测中经常使用。
	Sklearn中提供PolynomialFeatures()来建立包括交叉特征的多项式特征。
	有些DL的模型可以用来自动生成交叉特征比如Deep & Cross network(DCN)。
可以尝试使用能自动生成特征的工具比如featuretools。
	自动生成特征的工具的问题是会导致“特征爆炸”。
Read more »

什么是特征缩放?

特征缩放是用来统一数据集中的特征的值的幅度变化范围的方法。
主要针对的是连续性特征,尽管数值型的category有序特征也适用。

特征缩放有什么作用?(假设两个特征的值有数量级的差别)

在这里插入图片描述

在这里插入图片描述

左上图是未作特征scaling的目标函数关于2个模型参数的等高线,右上图是作完特征scaling的。可以看出右上图最优解的寻优过程明显会变得平缓,更容易正确的收敛到最优解。也就是说作完scaling,梯度下降不容易震荡,能更快收敛。

特征缩放的缺点:

容易让特征失真;可能丢失对训练模型一些重要的信息。

什么时候做特征scaling(不一定要做)?

通用原则:简单就是美-------因为特征缩放有缺点,先不要这样做,发现预测效果不好再尝试。
如果样本的所有特征的幅度范围都具有同样的量级,先不做特征缩放。
之后是否需要做特征降维:
	比如对于PCA(主成分分析),这里只做中心化(即特征值减去均值作为新的特征值,因此新特征的均值为0),不做其他特征缩放。
	对于LDA(线性判别分析),即不做中心化也不做其他特征缩放。
之后如果选择对于数据尺寸不敏感的基于tree的模型,先忽略该步骤。
最后在对原特征或者特征降维后得到的新特征做特征缩放。
Read more »

连续特征离散化,数值型category特征编码,特征缩放都属于特征变换

通过一个简单的例子,体会样本的变量/特征类型:

在这里插入图片描述

在这里插入图片描述

连续性特征离散化

离散化有什么好处?

离散化之后的特征对于异常数据具有较强的鲁棒性,模型会更稳定。
离散化相当于引入了非线性,提升模型的表达能力,增强拟合能力。
离散化之后方便进行特征交叉:连续特征不方便做特征交叉。也有人对所有特征包括连续特征做embedding,然后对embedding向量做内积来表示特征交叉。他的实现是离散特征每个枚举值对应1个embedding向量,而连续特征只对应1个embedding向量。
使得模型要拟合的值大幅度降低,也降低了模型的复杂度。

离散化的缺点:

离散化可能会丢失特征的一些信息,可能使模型性能恶化。
离散化可能带入一些噪音。

什么时候考虑离散化?

Read more »

为什么会有样本类别不均衡?

收集数据阶段有问题
业务天然特点:比如欺诈检测,癌症预测

为什么要考虑样本类别不均衡?

样本类别不均衡可能会把模型带偏,让他更关注类别多的样本。

什么情况下需要对样本类别不均衡处理?

如果本身小类别的样本绝对数量足够大,只是相对比其他类别的样本少,可以先暂时跳过这个步骤。
如果不同类别的训练样本数目稍有差别,通常影响不大。比如二分类正负样本比例不大于4:1,先训练看效果,用适合二分类类别不均衡的评价指标AUC-PR来评估。
对于正负样本极不平衡的场景,可以完全换一个不同的角度来看问题:将它看作异常检测问题,并使用异常检测来建模。

处理样本类别不均衡的方法?

收集更多的数据(尤其是对于小类别)--------很重要
Data augmentation:
	 根据已有样本生成同类别的样本,比如图像数据可以平移、放缩、旋转、翻转。
Cost Sensitive Methods:
	按照样本集不同类别的比列来调整类别权重,有些算法比如sklearn的LR算法本身支持自动调整类别的权重
Ensemble sampling:
	基本思想就是把majority进行划分,然后和minority组合成小的训练集, 然后生成学习器, 最后再集成。
	使用对类别不均衡不敏感的算法比如RadiusNeighborsClassifier: 实践中,如果数据集比较大,使用RadiusNeighborsClassifier会占用很多的物理内存(因为它需要用树结构来保存所有的训练样本),如果跑训练的机器的内存比较少,可能会发生OOM killer。这个时候最好减少训练集或者使用更大的机器来训练。
Sampling技术:
	Oversampling: 增加minor类达到数量均衡。常用的SMOTE方法(当前已有很多变体SMOTE):
	首先为每个稀有类样本随机选出几个邻近样本,并且在该样本与这些邻近样本的连线上随机取点,生成新的稀有类样本。
	Undersampling: 减少major类达到数量均衡
基于再缩放rescalling策略进行决策(常用于二分类不均衡问题):
	一种简单的方法:
	比如二分类的阈值判断使用正类个数与负类个数的比例(假设正类样本小于负类样本),而不是使用一般的0.5阈值。该决策假设训练集是真实样本总体的无偏采样(简单地说就是指训练样本的分布的平均值等于真实样本总体分布的平均值),因此可以用观测几率代替真实几率。实际场景中,这个假设往往不成立。
	对于多分类问题,可以给每个类别设置一个阈值(比如按照样本类别占比来设置阈值),最终分类器会选择对应类别的预测概率与该类别的阈值比值最大的类别作为预测结果。Sparkml的逻辑回归模型处理多分类问题就是这样做的。
	一种精细的方法:
	对于二分类的阈值设定问题,根据混淆矩阵的四个统计值和每个统计值对应业务的代价来遍历阈值从而找到最优阈值。
Read more »

什么是特征?

特征的别名:字段,属性,自变量

在这里插入图片描述

特征最基本的2个统计特点:

特征是否发散:
如果一个特征不发散,例如方差接近于0,也就是说样本在这个特征上基本上没有差异,这个特征对于样本的区分并没有什么用,可以丢弃它。(这个其实在数据探索阶段就可以发现)

连续特征和category特征

连续特征指语义上连续的数值型特征,包括整数类型和浮点类型。

Category特征指语义上有枚举特点的特征,包括字符串类型和数值类型。

离散特征是指具有数值类型的Category特征。
Category特征的枚举值数量越多,我们称它的基数越高。

Category特征的无序与有序:

Read more »

机器学习:一个反复迭代的过程(针对通用ML项目)

验证集和测试集的数据不会用于训练模型。

也就是模型在训练过程中,不会看到验证集和测试集的数据。

对于小批量数据,数据拆分的常见比例为:

如果未设置验证集,则将数据三七分:
	70% 的数据用作训练集、30% 的数据用作测试集。
如果设置验证集,则将数据划分为:
	60% 的数据用作训练集、20%的数据用过验证集、20% 的数据用作测试集。

对于大批量数据,验证集和测试集占总数据的比例会更小。

对于百万级别的数据,其中1万条作为验证集、1万条作为测试集即可。
验证集的目的就是验证不同的超参数;测试集的目的就是比较不同的模型。
一方面它们要足够大,才足够评估超参数以及模型。
另一方面,如果它们太大会浪费数据。

当训练集和验证集、测试集的数据分布不同时,有以下经验原则:

确保验证集和测试集的数据来自同一分布。
因为需要用验证集来优化超参数,优化的最终目标是希望模型在测试集上表现更好。
确保验证集和测试集能够反映未来得到的数据,或者最关注的数据。
确保数据被随机分配到验证集和测试集上。
想办法让训练集的分布更接近验证集:
	收集更多的、分布接近验证集的数据作为训练集。
	人工合成训练数据,使得它更接近验证集:它的潜在问题是你可能只是模拟了全部数据空间中的一小部分,导致模型对这一小部分数据过拟合,整体的泛化能力变差。

如果可训练数据很多,如何确定模型训练集样本数量?

Read more »

机器学习:一个反复迭代的过程(针对通用ML项目)

在这里插入图片描述

需求分析

与业务/领域专家沟通并深刻理解业务数据,尽量吃透业务数据的显式表征和可能的隐式表征。

可行性分析

是否需要用机器学习来实现,选择框架

获取原始数据并整理

考察原始数据的覆盖率,并对原始数据整理:
	把多个数据源的数据合并并存放到一个data store中;
	采样,去重,调整样本权重;
	过滤以及去掉不相关的记录或者特征:
		根据业务知识去掉没有业务含义的唯一性特征比如自增主键;
		根据业务知识决定是否去掉大规模高基数特征(比如用户ID是否是随机生成,是否由多个有意义的信息拼接而成,对于推荐系统,用户ID这样的大规模特征是需要保留的),
	根据业务知识去掉冗余特征;
	利用异常检测任务找到并确认异常样本。
	根据数据和业务特点来决定是否进行样本的shuffle

数据探索(利用可视化和统计分析来查看)

类别样本是否不均衡
特征的分布情况
是否有离群点
特征之间的相关度以及特征与目标变量的相关度
Read more »

Eureka是Netflix开源的一款提供服务注册和发现的产品,它提供了完整的Service Registry和Service Discovery实现。也是Spring Cloud体系中最重要最核心的组件之一。

服务中心

服务中心又称注册中心,管理各种服务功能包括服务的注册、发现、熔断、负载、降级等,比如dubbo admin后台的各种功能。

正常调用项目A请求项目B:

在这里插入图片描述

有了服务中心之后,任何一个服务都不能直接去掉用,都需要通过服务中心来调用:

在这里插入图片描述

项目A调用项目B,项目B在调用项目C:

在这里插入图片描述

这时候调用的步骤就会为两步:第一步,项目A首先从服务中心请求项目B服务器,然后项目B在从服务中心请求项目C服务。

Read more »

1、join操作

join操作是在特征提取过程中非常常见的一种需求,从多个不同文件完成了特征提取之后,通过join合并为一个完整的特征,可以方便进行接下来的模型训练、预测等其它操作。首先我们准备两份简单的数据,gender和age,其中两张表中的前3条有相同的姓名,后两条不同。

2、union

就是将两个RDD进行合并,不去重。

3、map

map是对RDD中的每个元素都执行一个指定的函数来产生一个新的RDD。任何原RDD中的元素在新RDD中都有且只有一个元素与之对应。

1
2
3
4
5
6
scala> val a = sc.parallelize(1 to 9, 3)
scala> val b = a.map(x => x*2)
scala> a.collect
res10: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
scala> b.collect
res11: Array[Int] = Array(2, 4, 6, 8, 10, 12, 14, 16, 18)

4、parallelize

Read more »

一般情况下我们用spark mllib训练模型,但我们的线上环境往往不是spark环境,如果需要上线,要导出模型。

部分模型不支持PMML(Predictive Model Markup Language),可以导出特征。

spark.mllib model PMML model
KMeansModel ClusteringModel
LinearRegressionModel RegressionModel (functionName=”regression”)
RidgeRegressionModel RegressionModel (functionName=”regression”)
LassoModel RegressionModel (functionName=”regression”)
SVMModel RegressionModel (functionName=”classification” normalizationMethod=”none”)
Binary LogisticRegressionModel RegressionModel (functionName=”classification” normalizationMethod=”logit”)

以下为KMeans算法导出PMML模型例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import org.apache.spark.mllib.clustering.KMeans
import org.apache.spark.mllib.linalg.Vectors

// Load and parse the data
val data = sc.textFile("data/mllib/kmeans_data.txt")
val parsedData = data.map(s => Vectors.dense(s.split(' ').map(_.toDouble))).cache()

// Cluster the data into two classes using KMeans
val numClusters = 2
val numIterations = 20
val clusters = KMeans.train(parsedData, numClusters, numIterations)

// Export to PMML to a String in PMML format
println(s"PMML Model:\n ${clusters.toPMML}")

// Export the model to a local file in PMML format
clusters.toPMML("/tmp/kmeans.xml")

// Export the model to a directory on a distributed file system in PMML format
clusters.toPMML(sc, "/tmp/kmeans")

// Export the model to the OutputStream in PMML format
clusters.toPMML(System.out)
Read more »