个人总结:数据、特征预处理(含word2vec)

缺失值处理

连续值

一般采用取平均值或者中位数来进行填充。

离散值

最频繁出现的类别(或者众数)来填充。

异常值清洗

异常数据可能给模型带来很大的偏差。

聚类清洗

例如,通过KMeans将训练样本分成若干簇,如果某一个簇里的样本数很少,而且簇质心和其他所有的簇都很远,那么这个簇里面的样本极有可能是异常特征样本。可将其从训练集过滤掉。同样道理还可以使用BIRCH和DBSCAN密度聚类算法。

异常点检测算法

使用iForest或者one-class-SVM来进行过滤所有的异常点。

特殊的特征处理

日期

对于20180519这样的值没办法直接使用。

一般有几种比较有代表性的方法:

  1. 时间差值法:使用UTC计算到某一天的时间差,从而将其转化为连续值。
  2. 根据时间的年月日,星期,小时数,将一个时间特征转化为若干个离散特征。
  3. 权重法:根据时间的新旧设置一个权重值。

地理位置

“成都市锦江区XX街道XX号”,可以转化为离散值和连续值。若是离散值的话,可以转化为多个离散特征,如城市名,区县,街道等。但是如果需要判别用户分布区域,则一般处理成连续值比较好,这时可以转化为经度和维度的连续特征。

特征的标准化和归一化

为什么需要标准化/归一化?

因为特征的数值范围不同的话,会影响梯度下降的速率。如果将目标函数的等值图画出来,数值范围大的特征,那个方向会需要更多次的迭代才能找到最优解。如果将每个特征的范围转化成一致的,那么等值图的图形会是一个圆形,梯度下降在各个方向的速率是一样的,可以更快地找到最优解。

不管是标准化还是归一化,它们的本质都是线性变换,是一个的形式,都是压缩后再进行平移。这样的性质决定了对数据进行改变后不会造成“失效”。从公式也可以看出,只是数据的均值和方差发生了变化,数据具体服从某种分布并没有得到改变。

min-max归一化

\frac{x - min}{max - min}

缩放仅仅和最大值,最小值的差别有关。在没有归一化之前,每个特征有自己的量纲,假设有两个特征,面积和房间数。因变量为房价。

在没有归一化之前,面积可以为0~1000,房间数为0~10,损失函数的等高线与参数的收敛关系可能是这样的

可以看到未归一化时图像的等高线类似于椭圆形状。归一化后

图像的等高线类似于圆形形状。明显可以看到最优解的寻优过程会变得平缓,更容易正确收敛到最优解。

z-score标准化

缩放和每个点都有关系,具体方法是求出均值和标准差,用(x-mean)/std来代替原特征。这样就变换到了均值为0,方差为1的分布(这里很容易误以为标准化后就符合正态分布,而是原始随机变量服从什么分布,标准化后就服从什么分布,只是均值和方差变了)。sklearn中使用StandardScaler来做z-score标准化。

è¿éåå¾çæè¿°

可以看出,标准化后能够加速损失函数收敛速度。能够更快得出最优参数ω和b。z-score最适用的数据分布是近似高斯分布,其他分布的效果可能效果会变差,比如长尾分布,分布的改变可能会影响数据原有的表现情况。

标准化(z-score)和归一化(min-max)的选择

归一化输出值为0-1,而标准化根据标准差的大小输出值可能为负无穷到正无穷。

  • 如果对输出结果范围有要求,就用归一化
  • 如果数据较为稳定,不存在极端的最大最小值,就用归一化
  • 如果数据存在异常值和较多噪音,就用标准化,可以间接通过中心化避免异常值和极端值的影响

白化 与 批标准化BatchNormalization

它们和z-score标准化有不少共同之处,详细内容可以看这篇文章

范数标准化

L1范数标准化用\overrightarrow{x}/\left \| \overrightarrow{x} \right \|_{1},L2范数标准化用\overrightarrow{x}/\left \| \overrightarrow{x} \right \|_{2}

中心化

PCA降维时,会涉及到中心化的操作。mean为特征x的均值,对x内的所有数据采用x-mean的操作,此时特征的均值为0。但是方差并不改变。在PCA中,这是因为PCA就是通过方差来进行降维。

小结

什么时候需要做标准化或者归一化?一般来说,标准化和归一化是为了加速收敛服务的,通过梯度下降求解的模型通常是需要归一化的,包括线性回归、逻辑回归、支持向量机、神经网络等模型对但也有部分类似贝叶斯、CART、随机森林等基于概率分布的模型不用做。

离散特征的连续化处理

类似线性回归、逻辑回归这样的算法无法使用离散特征,所以需要对离散特征进行连续化处理。

序号编码 serial-encoding

通常用于处理类别间具有大小关系的数据,例如成绩,就可以分为低、中、高三档,并且存在“高>中>低”的排序关系。序号编码会按照大小关系对类别型特征赋予一个数值ID,例如高表示3,中表示为2,低表示为1,转换后依然保留了大小关系。

独热编码 one-hot encoding

独热编码是最常见的处理方法,比如一个特征有三个类别a/b/c。那对于a可以编码为1,0,0.b则为0,1,0.c则为0,0,1.sklearn的onehotEncoder可以做这个事情。独热编码在类别过多的情况下可能会发生维度灾难,这对内存是不小的考验,常常结合稀疏编码,不仅能够节省内存,还可以加快计算速度。

二进制编码 binary-encoding

第一步,先用序号编码给每个类别编码;第二步,将类别ID转化为相应的二进制。例如,B型血的ID为2,二进制表示为010。这种方法的优点是得到的结果维数少于独热编码。

特征嵌入 embedding

NLP学习笔记(四)中提到了嵌入Embedding在深度学习NLP中的应用。其实不仅是NLP,在深度学习的其他应用中,也可以使用这一原理,它的原理都是通过具体的样本,找到在嵌入的特征矩阵中对应的向量。比如用户ID,如果有100万个,那嵌入的特征矩阵的行就是100万,列会取得比较小,比如20,这样就将每个用户ID转化为了一个20维的特征向量。

离散特征的离散化处理

虚拟编码 dummy coding

它的道理和独热编码类似,但是独热编码对所有类别进行编码,如果有N类的话就需要N位编码。而虚拟编码则可以少一位,只需要N-1位即可。比如A/B/C三类,只编码A.B,则10为A,01为B。剩下没有提到的00就默认为C了。

连续特征的离散化处理

通过将连续特征离散化,可能在不通过算法模型的前提下获得一些特征的本质,方便之后一些算法的处理。

阈值法

比如特征的取值范围为0-1,可以根据特征的分位数,将0-0.3设置为高,0.3-0.7设置为中,0.7-1设置为高。

一些高级思路

在LR+GBDT的经典模式中,就是使用GBDT先将连续特征转化为离散特征。比如用所有的连续值和标签输出来训练GBDT,假设最后得到两棵决策树,第一棵树有三个叶子节点,第二棵树有四个叶子节点。如果某个样本在第一棵决策树落到第二个叶子节点,在第二棵决策树落到第四个叶子节点,那么编码就是0,1,0,0,0,0,1。sklearn中可以用GradientBoostingClassifier的apply方法很方便地得到离散化后的特征,然后使用独热编码即可。

from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.preprocessing import OneHotEncoder
X, y = make_classification(n_samples=10)  
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5)
gbc = GradientBoostingClassifier(n_estimators=2)
one_hot = OneHotEncoder()
gbc.fit(X_train, y_train)
X_train_new = one_hot.fit_transform(gbc.apply(X_train)[:, :, 0])
print (X_train_new.todense())
[[0. 1. 1. 0.]
 [1. 0. 0. 1.]
 [1. 0. 0. 1.]
 [1. 0. 0. 1.]
 [0. 1. 1. 0.]]

对于逻辑回归,可以将连续特征和离散特征一同放进模型进行训练,但是前提是离散特征要变化成0,1这样的数值型离散值。

组合特征

为了提高复杂关系的拟合能力,有时会把一阶离散特征两两组合,构成高阶组合特征。以广告点击预估问题为例,原始数据有语言和类型两种离散特征,第一张表是语言和类型对点击的影响。为了提高拟合能力,语言和类型可以组成二阶特征。第二张表示语言和类型的组合特征对点击的影响。

上述的规模只是2x2,但是在数据为用户ID和物品ID时容易出现超大的学习规模(mxn),这是因为在互联网环境下用户数量和物品数量都可以达到千万量级,如果拿LR来作为模型的话,几乎无法学习mxn规模的参数。

如何处理高维组合特征?

在这种情况下,一种行之有效的方法是将用户和物品分别用k维的低维向量表示(k<<m, k<<n),学习的规模变成了mxk+nxk。这其实等价于矩阵分解。至于为什么是这样一个规模,可以在个人总结:推荐算法篇(附协同过滤等) 综述——》基于协同过滤的推荐——》基于模型的协同过滤——》矩阵分解——》FunkSVD(隐含语义模型 Latent Factor Model) 中找到答案。

怎样有效地找到组合特征?

例如通过构建决策树,每一条从根节点到叶节点的路径都可以看成一种特征组合的方式:

(1)“年龄小于等于35”且“性别为女”

(2)“年龄小于等于35”且“物品类别为护肤”

(3)“用户类型=付费”且“物品类型=食品”

(4)“用户类型=付费”且“年龄小于等于40”

有两个样本:

样本一就可以编码成(1,1,0,0),同时满足(1)(2),不满足(3)(4),而样本二可以编码为(0,0,1,1)。

处理不平衡数据

一般是对于分类问题,标签中某一类的样本数量远远超过另外一类的样本数量。这导致训练出的模型在预测另外数量少的那一类别时准确率会很低。

阈值法

类似逻辑回归这样的模型的输出范围为0-1,默认当某个样本输出大于0.5就会被划分为正例,反之为反例。当数据不平衡时可能导致输出全部为反例,产生虚假的高准确度,导致过拟合的出现,分类失败。可以通过调整阈值,使得模型对于较少的类别更为敏感。也可以选择合适的评价标准,比如使用ROC或者F1 score.

权重法

对于每个类别加一个权重class weight。如果该类样本数多,那么它的权重就低,反之权重越高。

采样法

  • 过采样(上采样):重复提取类别少的数据,直到两种类别样本数目接近。这种做法很大的缺点就是容易导致对类别少的那一类过拟合。
  • 欠采样(下采样):抛弃大部分类别多的那一类数据,使两种类别样本数目接近。这可能导致欠拟合。所以另外一种做法是重复对样本数量多的那一类重复欠采样,这样可以构造多个样本集,分别进行训练,将结果进行集成。
  • SMOTE:它和过采样类似,但并不是像过采样那样单纯重复生成类别少的那一类样本。而是通过K-近邻生成新的样本。举个例子,加入候选合成集合里有两个样本(x1,y),(x2,y),那么SMOTE采样后,可以得到一个新的训练样本\left ( \frac{x_1 + x_2}{2}, y \right).但缺点也存在,可能会生成一些异常点。但实验发现大部分和过采样效果相似。

小结

过采样在大部分时候效果比欠采样更好。遇到不平衡的情况时,使用过采样(或者SMOTE)+强正则模型(如XGBoost)也许是个不错的方法,可以先试着作为基准。

 

处理非结构化数据(这里主要说明文本数据)

处理文本数据有:词袋模型(Bag Of Words)、TF-IDF(Term Frequency-Inverse Document Frequency)、主题模型(Topic Model)、词嵌入模型(Word Embedding)

词袋模型和N-gram模型

将每篇文章看成一袋子词,并忽略每个词出现的顺序,将整段文本以此词为单位切分开,每篇文章可以表示成一个长向量,向量中的每一维代表一个单词,而该维的权重反映这个词在原文章中的重要程度。常用TF-IDF来计算权重,公式为

TF(t,d)为 单词t在文档d中出现的频率,IDF(t)是逆文档频率,用来衡量单词t对表达语义所起的重要性,表示为

直观来说就是若一个单词在非常多的文章里都出现,那么它可能是一个比较通用的词汇,对区分某篇文章特殊语义的贡献较小,因此对权重做一定惩罚。

NLP学习笔记(一) : 数据预处理(词袋)NLP学习笔记(二):创建特征及训练(关键词:词袋,TFIDF)分别进行了实战演示。

有时将所有词进行切分不是一种好的做法,如natural language processing一词,所表达的含义与三个词连续出现时大相径庭。因此也可以将连续出现的n个词(n<=N)组成的词组(N-gram)也作为一个单独的特征放到向量表示中去,构成N-gram模型。另外,同一个词可能有多种词性变化,却具有相似的含义。在实际应用中,一般会对单词进行词干抽取(word stemming),将不同磁性的单词统一成为同一词干的单词,例如happy是happiness的词干。

主题模型

主题模型能够计算出每篇文章的主题分布。典型的代表有LDA等。

词嵌入与深度学习模型

词嵌入是一类将词向量化的模型的统称,核心思想是将每个词都映射为低维空间(通常K=50-300维)上的一个稠密向量。K维空间的每一维可以看做一个隐含的主题,只不过不像主题模型中的主题那么直观。

假设每篇文章有N个词,每个词映射为K维的向量,那就可以用一个NxK维的矩阵来表示这篇文章。但是实际中直接输入很难获得令人满意的结果,因此还需要在此基础上加工出更高层的特征。传统浅层机器学习模型中,一个好的特征工程可以带来算法效果的显著提升。而深度学习模型正好为我们提供了一种自动进行特征工程的方式,每个隐层都可以认为对应不同抽象层次的特征。从这个角度来讲深度学习能够打败浅层模型也就顺理成章了。卷积神经网络和循环神经网络一方面很好抓住了文本的特征,另一方面又减少了网络中待学习的参数,提高了训练速度,并且降低了过拟合的风险。

谷歌2013年提出了word2vec,是最常用的词嵌入模型。它实际上是一种浅层的神经网络结构,分别有两种结构,CBOW(continuous bag of words)skip-gram

CBOW根据上下文出现的词语来预测当前词的生成概率,w(t)是当前词,w(t-2)、w(t-1)、w(t+1)、w(t+2)是上下文中出现的词:

输入层有上下文词数这么多个神经元,输入层中每个词都由独热编码方式表示,即所有词均表示成一个N维向量,输出层有词汇表大小个神经元,其中N为词汇表中单词的总数。隐藏层的神经元个数可以自己指定,K个隐含单元的取值可以由N维输入向量以及连接输入和隐含单元之间的NxK维权重矩阵计算得到,也就是embedding的维度,这个隐藏层也就是我们的词向量层。在CBOW中,还需要将各个输入词所计算出的隐含单元求和。训练目标是期望训练样本特定词对应的softmax概率最大。通过DNN的反向传播,我们可以训练出DNN模型的参数,同时得到所有词的词向量。这样当我们需要通过上下文预测中心词时,通过一次前向传播以及softmax函数就可以找到概率最大的词对应的神经元。

比如在CBOW中,预测中间出现的一个词,输入8个上下文词,最后输出的是所有词的softmax概率,投影时预测词的词向量为上下文的词向量平均值。

而Skip-gram是根据当前词来预测上下文中各词的生成概率:

对应的输入层只有一个神经元,输出层有N个神经元。隐藏层可以自己指定。同样通过DNN的反向传播算法进行训练,可以求出DNN模型参数,同时得到对应的词向量。这样当有新的需求,通过输入一个词便可以得到概率大小排前8的softmax概率对应的神经元所对应的词即可。

接下来训练权重,使得所有单词的整体概率最大化(极大似然估计),学习权重可以用反向传播算法实现,由于softmax存在的归一化项,推导出来的参数的迭代公式需要对词汇表中所有单词进行遍历

这使得每次迭代过程非常非常缓慢,由此产生了Hierarchical Softmax基于霍夫曼树)和Negative Sampling两种改进方法。训练得到维度为NxK和KxN的两个权重矩阵后,可以选择其中一个矩阵作为N个词的K维向量表示。

Word2Vec与LDA的区别和联系?

首先,LDA是利用文档中单词的共现关系来对单词按主题聚类,也可以理解为对“文档-单词”矩阵进行分解,得到“文档-主题”和“主题-单词”两个概率分布。而word2vec其实是对“上下文-单词”矩阵进行学习,其中上下文由周围几个单词组成,由此得到的词向量表示更多地融入了上下文共现的特征。也就是说如果两个单词对应的word2vec向量相似度较高,那它们很可能经常在同样的上下文中出现。

主题模型和词嵌入模型的区别?

主题模型和词嵌入两类方法最大的不同在于模型本身,主题模型是一种基于概率图模型的生成式模型,其似然函数可以写成若干条件概率连乘的形式,其中包括需要推测的隐含变量(即主题);词嵌入模型一般表示为神经网络的形式,似然函数定义在网络的输出之上,需要通过学习网络的权重以得到单词的稠密向量表示。

如何处理涉及图像数据的任务中,训练不足的情况?

个人总结:CNN、tf.nn.conv2d(卷积)与 tf.nn.conv2d_transpose(反卷积)以及激活函数中,针对如何应对CNN过拟合的问题中有提到。

发布了94 篇原创文章 · 获赞 137 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/yyhhlancelot/article/details/93471722
今日推荐