在获得数据之后,我们需要对数据进行分析,以便了解数据的基本性质,为后续的模型选择和模型训练提供依据。了解特征的分布,是机器学习的第一步,同时也是相当关键的一步。我们引入了核密度估计来帮助我们了解数据的基本分布。
在上一篇文章中,我们重点描述了数据的导入和转换。在利用pandas的read_csv函数导入数据的过程中,根据自定义函数将特征转换为我们需要的形式。下面依然后贴上该代码。如下:
#--coding:utf-8
import warnings
warnings.filterwarnings("ignore")
import numpy as np
import pandas as pd
import os
from sklearn.neighbors import KernelDensity
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d
filepath = os.path.join("../dataset/Internet Advertisements/Data Folder","ad.data")
#对DataFrame的列做数据转换
def Converter_number(x):
try:
return np.float64(x)
except ValueError:
return np.nan
#字典推导式
converters = {key:Converter_number for key in range(1558)}
converters[1558] = lambda x: 1 if x.strip()=='ad.' else 0
ads = pd.read_csv(filepath,header=None,converters=converters)
print(ads[:5])
# 0 1 2 3 4 5 6 7 8 9 ... 1549 \
# 0 125.0 125.0 1.0000 1.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0
# 1 57.0 468.0 8.2105 1.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0
# 2 33.0 230.0 6.9696 1.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0
# 3 60.0 468.0 7.8000 1.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0
# 4 60.0 468.0 7.8000 1.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0
#
# 1550 1551 1552 1553 1554 1555 1556 1557 1558
# 0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1
# 1 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1
# 2 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1
# 3 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1
# 4 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1
#
# [5 rows x 1559 columns]
#首先去掉空值,并查看数据的统计
ads = ads.dropna(axis=0)
print(ads.describe())
#我们可以看到,大量的特征的25%,50%,75%分位数显示,特征分布在0或1,我们可以大胆猜测,这些特征大量包含0或者1.
# 0 1 2 3 4 \
# count 2359.000000 2359.000000 2359.000000 2359.000000 2359.000000
# mean 63.912251 155.631624 3.912982 0.759644 0.002120
# std 54.881130 130.237867 6.047220 0.427390 0.045999
# min 1.000000 1.000000 0.001500 0.000000 0.000000
# 25% 25.000000 80.500000 1.033450 1.000000 0.000000
# 50% 51.000000 110.000000 2.111100 1.000000 0.000000
# 75% 84.000000 184.000000 5.333300 1.000000 0.000000
# max 640.000000 640.000000 60.000000 1.000000 1.000000
#
# 5 6 7 8 9 \
# count 2359.0 2359.000000 2359.000000 2359.000000 2359.000000
# mean 0.0 0.006359 0.004663 0.004663 0.014837
# std 0.0 0.079504 0.068141 0.068141 0.120925
# min 0.0 0.000000 0.000000 0.000000 0.000000
# 25% 0.0 0.000000 0.000000 0.000000 0.000000
# 50% 0.0 0.000000 0.000000 0.000000 0.000000
# 75% 0.0 0.000000 0.000000 0.000000 0.000000
# max 0.0 1.000000 1.000000 1.000000 1.000000
#
# ... 1549 1550 1551 1552 \
# count ... 2359.000000 2359.000000 2359.000000 2359.000000
# mean ... 0.003815 0.001272 0.002120 0.002543
# std ... 0.061662 0.035646 0.045999 0.050379
# min ... 0.000000 0.000000 0.000000 0.000000
# 25% ... 0.000000 0.000000 0.000000 0.000000
# 50% ... 0.000000 0.000000 0.000000 0.000000
# 75% ... 0.000000 0.000000 0.000000 0.000000
# max ... 1.000000 1.000000 1.000000 1.000000
#
# 1553 1554 1555 1556 1557 \
# count 2359.000000 2359.000000 2359.000000 2359.00000 2359.000000
# mean 0.008478 0.013989 0.014837 0.00975 0.000848
# std 0.091705 0.117470 0.120925 0.09828 0.029111
# min 0.000000 0.000000 0.000000 0.00000 0.000000
# 25% 0.000000 0.000000 0.000000 0.00000 0.000000
# 50% 0.000000 0.000000 0.000000 0.00000 0.000000
# 75% 0.000000 0.000000 0.000000 0.00000 0.000000
# max 1.000000 1.000000 1.000000 1.00000 1.000000
#
# 1558
# count 2359.000000
# mean 0.161509
# std 0.368078
# min 0.000000
# 25% 0.000000
# 50% 0.000000
# 75% 0.000000
# max 1.000000
#
# [8 rows x 1559 columns]
from sklearn.grid_search import GridSearchCV
#我们来看看前4个特征的分布
fig = plt.figure()
df = (ads[0].sort_values().values)[:,np.newaxis]
grid_param = {
'bandwidth':list(range(1,31))
}
kde_grid = GridSearchCV(KernelDensity(),grid_param)
kde = kde_grid.fit(df).best_estimator_
print(kde_grid.best_params_)
plt.subplot(221)
plt.plot(df[:,0],np.exp(kde.score_samples(df)),'-')
df = (ads[1].sort_values().values)[:,np.newaxis]
grid_param = {
'bandwidth':list(range(1,31))
}
kde_grid = GridSearchCV(KernelDensity(),grid_param)
kde = kde_grid.fit(df).best_estimator_
print(kde_grid.best_params_)
plt.subplot(222)
plt.plot(df[:,0],np.exp(kde.score_samples(df)),'-')
df = (ads[2].sort_values().values)[:,np.newaxis]
grid_param = {
'bandwidth':list(range(1,11))
}
kde_grid = GridSearchCV(KernelDensity(),grid_param)
kde = kde_grid.fit(df).best_estimator_
print(kde_grid.best_params_)
plt.subplot(223)
plt.plot(df[:,0],np.exp(kde.score_samples(df)),'-')
df = (ads[3].sort_values().values)[:,np.newaxis]
grid_param = {
'bandwidth':np.linspace(0.01,0.1,10)
}
kde_grid = GridSearchCV(KernelDensity(),grid_param)
kde = kde_grid.fit(df).best_estimator_
print(kde_grid.best_params_)
plt.subplot(224)
plt.plot(df[:,0],np.exp(kde.score_samples(df)),'-')
#可用来对类别变量进行计数
from collections import Counter
df1558 = ads[1558].values
# c = Counter(df1558)
# plt.bar(list(c.keys()),list(c.values()))
fig = plt.figure()
plt.hist(df1558,bins=2,rwidth=0.8)
plt.show()
if __name__ == "__main__":
print("OK")
图1
图2
这样,我们就得到了特征的分布情况。
上述代码中,我们主要用到了KernelDensity函数,是一个核密度估计函数。kernel density estimation是在概率论中用来估计未知的密度函数,属于非参数检验方法之一,由Rosenblatt (1955)和Emanuel Parzen(1962)提出,又名Parzen窗(Parzen window)。Ruppert和Cline基于数据集密度函数聚类算法提出修订的核密度估计方法。
由给定样本点集合求解随机变量的分布密度函数问题是概率统计学的基本问题之一。解决这一问题的方法包括参数估计和非参数估计。参数估计又可分为参数回归分析和参数判别分析。在参数回归分析中,人们假定数据分布符合某种特定的性态,如线性、可化线性或指数性态等,然后在目标函数族中寻找特定的解,即确定回归模型中的未知参数。在参数判别分析中,人们需要假定作为判别依据的、随机取值的数据样本在各个可能的类别中都服从特定的分布。经验和理论说明,参数模型的这种基本假定与实际的物理模型之间常常存在较大的差距,这些方法并非总能取得令人满意的结果。由于上述缺陷,Rosenblatt和Parzen提出了非参数估计方法,即核密度估计方法.由于核密度估计方法不利用有关数据分布的先验知识,对数据分布不附加任何假定,是一种从数据样本本身出发研究数据分布特征的方法,因而,在统计学理论和应用领域均受到高度的重视。
Parameters: | bandwidth : float
algorithm : string
kernel : string
metric : string
atol : float
rtol : float
breadth_first : boolean
leaf_size : int
metric_params : dict
|
---|
Methods
fit (X[, y]) |
Fit the Kernel Density model on the data. |
get_params ([deep]) |
Get parameters for this estimator. |
sample ([n_samples, random_state]) |
Generate random samples from the model. |
score (X[, y]) |
Compute the total log probability under the model. |
score_samples (X) |
Evaluate the density model on the data. |
set_params (\*\*params) |
Set the parameters of this estimator. |
对于单变量分布,后面会介绍更简单的分析方式。但是核密度估计是一种重要的非参数检验方法,感兴趣的同学可以深入了解。