文章目录
数据的降维
数据的降维是数据预处理中至关重要的一部分。当拥有非常高纬度的数据集时,给数据降低纬度对于分析来说是非常重要的。
数据降维的概念
维度指的是特征的维度。数据的降维指的是要最大程度降低数据特征(剔除无用特征)的同时,尽可能多的保留原数据中包含的信息。简单的说降维指的是特征的数量减少。
数据降维的意义
当我们拿到多特征的数据时,有一些字段的数据对于结果是没有意义,或者意义极小,但是在做机器学习的过程中也会参与计算,对我们最终分析结果造成不利影响,我们要根据实际情况,把数据进行降维,使得计算过程更轻便。
数据降维的方法
常用的数据降维方法有两种:
- 特征选择
- 主成分分析
特征选择
特征选择的概念
特征选择指的是在所有特征中选择部分特征作为训练集特征,选择后特征的值不改变,但是选择后的特征维数会降低。
特征选择的目的
当数据的特征较多时,特征量达到成百上千时,会极大的消耗计算性能。并且,有许多无用的特征,也会给计算带来一定的麻烦。
例如,给出一系列猫的数据,我们需要根据特征对猫进行分类,其中有‘是否有爪子’,‘爪子的长度’,‘眼睛的颜色’,‘毛的长度’四个特征。
但是很明显特征1和特征4是无用特征。因为所有的猫都有爪子,并且毛的长度相差不多,这时候就需要把这些无用特征剔除。
特征选择的方法
- Filter(过滤式): VarianceThreshold
- Embedde(嵌入式):正则化,决策树
- Wrapper(包裹式)
- 神经网络
Filter(过滤式): VarianceThreshold
Variance为方差,Threshold为阈值。顾名思义,过滤式特征选择是利用设定方差阈值的方式对特征进行提取。在设定的阈值方差范围内的(即认为无用的特征)特征被剔除,范围外的特征保留。举个例子:
下表中存在特征1和特征2。特征1中每个值都一样,也就说明该特征对最后的判断不会起到任何作用,因为都一样,就不算特征了,并且该列特征的方差为0。所以设定方差阈值为0则可将其筛掉。特征二中只有两个值和其他值不一样,也可认为特征用处不大(当然也有可能这两个特征值对判断结果起到决定性作用,那就不可剔除了),设定方法阈值将其剔除。
所以过滤式特征选择的核心就是:根据设定方差的大小剔除无用的特征,剩余的特征数据不改变。
Sklearn库特征选择API
sklearn.feature_selection.VarianceThreshold(threshold=0.0)#threshold为设定的方差阈值
举个例子,对以下四个特征进行特征选择
1、调库
from sklearn.feature_selection import VarianceThreshold
2、特征选择函数
def var():
var = VarianceThreshold(threshold=0.0) #这里设置的方差阈值为0
data = var.fit_transform([[1,2,3,4],[1,3,4,4],[1,4,5,4]])
print(data)
return None
3、运行结果
if __name__=="__main__":
var()
从上面的结果可以看出,因为设置的阈值方差为0,所以把特征1和特征4删除了。当然,可以继续加大方差阈值,那么可能就只剩下一个特征。在实际的处理过程中方差阈值在0-10之间一般都可以取,那到底有没有最好的值呢?没有,这需要根据实际情况来确定。
主成分分析(PCA)
PCA的概念
PCA是一种分析、简化数据集的技术,其核心在于数据维度压缩,尽可能降低原数据的维度,损失少量信息。 通过PCA可以实现削减回归分析或者聚类分析中特征的数量。
举个例子,用一个相机给三维物体拍照,拍成的照片就是二维的,即给物体进行了降维。但是降维有个要求,要求最大限度地能够体现出原物体的特征,例如下面四个图,都是三维物体的降维结果,但是图4更能反映出原物体的信息。故图4就是我们想要的降维结果。所以说用一个低维度表示高维度物体的时候,会发生一些信息丢失,而我们的目的就是在减少特征数量的同时尽可能减少信息的丢失。
PCA的原理
如果需要深入的了解PCA原理,需要了解一些向量积变换、方差和协方差矩阵等数学知识,感兴趣的可以去百度。这里通过一个简单事例进行说明。给出5个点,如下:
横坐标 | 纵坐标 |
---|---|
-1 | -2 |
-1 | 0 |
0 | 0 |
2 | 1 |
0 | 1 |
在坐标轴上的分布为:
要求:将二维的数据简化为一维。即将平面降维为一条直线。
那么降维的结果会有很多,例如将其降维到x轴上
降维之后原来的5个点就变成了3个点,从5个点变为3个点的过程中就出现了信息的丢失。同样的,如果降维后的结果在y轴上,依然会存在较大的信息丢失。而PCA需要的做的就是将丢失信息减到最小,例如下面的降维结果,就要比之前的降维效果要好。
说到底,PCA就是要找到上面那样的一条最优的红色线。PCA处理的过程中特征数量会减少,数据也会改变,会将丢失的信息降到最低。
PCA的适用场合
当特征数量较少时是不推荐使用PCA的,比如当特征数量只有十几个二十几个,那就没必要了。只有当特征数量达到上百上千时,才考虑对数据进行简化。图片的特征数量通常上千,此时就适合做主成分分析,再比如分析巨量数据时,如医学领域,金融市场领域。
PCA解决的主要问题
高维度的数据中,特征常常是相关的。
例如下表的特征1和特征2。
我们可以发现特征1乘以2倍就是特征2,其变化趋势是相同的,那么我们就可以把两个特征当作一个特征来处理。在实际处理过程中,当数据中存在成百上千个特征时,必然会出现上面的情况,这时我们就可以用PCA进行降维。
Sklearn主成分分析API
sklearn.decomposition.PCA(n_components=None……)
需要注意的是n_components有两种形式,可以是小数,也可以是整数。
- 当n_components是小数时,为(0,1]之间的数,表示的是信息保留量,即降维后要保存多少数据。一般设置为90%-100%,保存原始数据的90%-100%。
- 当n_components是整数时,表示减少到的特征数量。
- 在PCA降维过程中,我们常设置n_components为小数,而不是设置为整数。
举个例子
对下列特征进行降维
1、调库
from sklearn.decomposition import PCA
2、PCA函数
def pca():
pca = PCA(n_components=0.95)#设置为保留原数据的95%
data = pca.fit_transform([[2,5,1,7],[5,1,7,8],[9,4,2,1]])
print(data)
return None
3、结果
if __name__=="__main__":
pca()
保存原数据95%的信息后,降成了2维。
Instacart Market Basket Analysis实战
问题背景
数据集源于kaggle中的一道竞赛题,我们利用其中的四个表格进行降维处理
-
products.csv:商品信息
-
order_products_prior.csv:订单与商品信息
-
orders.csv:用户的订单信息
-
aisles.csv:商品所属具体物品类别
要求:根据用户购买的物品类别,把用户进行分类。
问题分析
要求的终极目标是把user_id与aisle合在一起。但是
user_id和aisle是在两张不同的表上面的,所以我们首先要根据键值利用pandas将表进行合并。user_id在表orders.csv中,aisle在aisles.csv中,两个表没有共同的键值,故需要通过其他的表来进行合并。
通过分析我们发现order_products_prior.csv和products.csv有共同键值product_id,故先将其合并,合并后的表和orders.csv有共同键值order_id。三个表合并后的表和aisles.csv有共同键值aisle_id。由此,便将user_id和aisle放在了一张表上。
表的合并–pd.merge()
表的合并需要用到pd.merge
pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None,
left_index=False, right_index=False, sort=True,
suffixes=('_x', '_y'), copy=True, indicator=False,
validate=None)
- left: 拼接的左侧DataFrame对象
- right: 拼接的右侧DataFrame对象
- on: 要加入的列或索引级别名称。 必须在左侧和右侧DataFrame对象中找到。 如果未传递且left_index和right_index为False,则DataFrame中的列的交集将被推断为连接键。
- left_on:左侧DataFrame中的列或索引级别用作键。 可以是列名,索引级名称,也可以是长度等于DataFrame长度的数组。
- right_on: 左侧DataFrame中的列或索引级别用作键。 可以是列名,索引级名称,也可以是长度等于DataFrame长度的数组。
- left_index: 如果为True,则使用左侧DataFrame中的索引(行标签)作为其连接键。 对于具有MultiIndex(分层)的DataFrame,级别数必须与右侧DataFrame中的连接键数相匹配。
- right_index: 与left_index功能相似。
读取四张表格
import pandas as pd
from sklearn.decomposition import PCA
prior = pd.read_csv("order_products__prior.csv")
aisles = pd.read_csv("aisles.csv")
orders = pd.read_csv("orders.csv")
products = pd.read_csv("products.csv")
合并第一张表后的结果
_mg = pd.merge(prior,products,on='product_id') #将prior表和products合在一起,键值为product_i
可以看到,根据product_id把两张表合并在了一起。
以此类推,可以合并第二张、第三张表,合并后的结果见下图
此时用户和物品就放在了一张表格上。
交叉表–pd.crosstab()
经过上面的处理,我们得到了总表,但是我们只注重用户买了哪些东西。所以我们需要得到一张用户和所买物品数目表。这就需要交叉表操作。
什么是交叉表,先举个例子。
例如下表,我们想到清晰的知道每个人所买商品的数量。即计算按姓名分组的商品频率。
通过交叉表处理后,便得到了下表。
这样,就可以清晰的展现出每个人所买的物品数目。
交叉表API为pd.crosstab()
其默认生成以行和列分类的频数表。
pd.crosstab(index, # 分组依据
columns, # 列
values=None, # 聚合计算的值
rownames=None, # 列名称
colnames=None, # 行名称
aggfunc=None, # 聚合函数
margins=False, # 总计行/列
dropna=True, # 是否删除缺失值
normalize=False #
)
经过交叉表处理后,则可变为下表
上表中,行为用户id,列为所买商品数目。
根据所买商品数目就可以对用户进行划分,有的喜欢买食物、有的喜欢买电器等等。
上表中共有134个特征,但是我们仔细观察就会发现,有很多特征都是0,也就是我们所说的无用特征。所以接下来就进行PCA降维。
pca = PCA(n_components=0.9)
data = pca.fit_transform(cross)
降维结果:
查看降维后的特征
data.shape
(206209, 27)
降维结束后生于27个特征。
完整代码
import pandas as pd
from sklearn.decomposition import PCA
prior = pd.read_csv("order_products__prior.csv")
aisles = pd.read_csv("aisles.csv")
orders = pd.read_csv("orders.csv")
products = pd.read_csv("products.csv")
# 合并四张表
_mg = pd.merge(prior,products,on='product_id')
_mg1 = pd.merge(_mg,orders,on='order_id')
_mg2 = pd.merge(_mg1,aisles,on='aisle_id')
cross = pd.crosstab(_mg2['user_id'],_mg2['aisle'])
pca = PCA(n_components=0.9)
data = pca.fit_transform(cross)