(原创)(一) 机器学习之数据探索

<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script> href="custom.css" rel="stylesheet"> <script src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML"></script> <script type="text/x-mathjax-config"> MathJax.Hub.Config({ tex2jax: { inlineMath: [ ['$','$'], ["\\(","\\)"] ], displayMath: [ ['$$','$$'], ["\\[","\\]"] ], processEscapes: true, processEnvironments: true }, // Center justify equations in code and markdown cells. Elsewhere // we use CSS to left justify single line equations in code cells. displayAlign: 'center', "HTML-CSS": { styles: {'.MathJax_Display': {"margin": 0}}, linebreaks: { automatic: true } } }); </script>

机器学习的一般步骤

1.确定特征
(1)数据探索
(2)数据预处理
2.确定模型
(1)确定目标函数
3.模型训练
(1)确定优化算法,估计模型参数
4.模型选择
选择不同参数下的模型。
5.模型评估
对所选择的模型进行评估:估计模型在未知数据上的性能(泛化能力).

以上5个过程不断迭代,直到寻找到一个最优的模型和其参数。

以下,以波士顿房价预测为例,先简单讲讲数据探索。
一般我们拿到一堆数据之后,并不知道数据有何规律,为了了解数据特征的规律(概率分布),我们第一个步骤就是数据探索,探索数据的特征有何规律或者分布,为模型选择奠定基础。

数据探索

数据探索包括:
(1) 数据规模。
(2) 数据类型,确定是否需要进一步编码。
(3) 数据是否有缺失值,如果有则进行数据填补。
(4) 查看数据分布,是否有异常数据点,如果有则进行离群点处理。
(5) 查看是否需要降维:查看两两特征之间的关系,看数据是否有相关(冗余)。

1. 导入必要的工具包

数据处理工具包为:Numpy,SciPy,pandas,其中SciPy,pandas是基于Numpy进一步的封装
数据可视化工具包为:Matplotlib,Seaborn,其中Seaborn是基于Matplotlib进一步的封装

In [38]:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

#将matplotlib的图表直接嵌入到Notebook之中
%matplotlib inline
%matplotlib inline :

将matplotlib的图表直接嵌入到Notebook之中.
IPython提供了许多魔法命令。魔法命令都以%或者%%开头,以%开头的成为行命令,%%开头的称为单元命令。行命令只对命令所在的行有效,而单元命令则必须出现在单元的第一行,对整个单元的代码进行处理。执行%magic可以查看关于各个命令的说明,而在命令之后添加?可以查看该命令的详细说明:
%matplotlib?

2.读取结构化数据

pandas.read_csv(filepath_or_buffer,...,header='infer', names=None,..., encoding=None, ...)

read_csv与to_csv 是一对输入输出的工具,read_csv直接返回pandas.DataFrame,而to_csv只要执行命令即可写文件
header: 表示数据中是否存在列名,如果在第0行就写就写0,并且开始读数据时跳过相应的行数,不存在可以写none。
names: 表示要用给定的列名来作为最终的列名。
encoding:表示数据集的字符编码,通常而言一份数据为了方便的进行文件传输都以utf-8作为标准。

In [39]:
dpath = './data/'
data = pd.read_csv(dpath + "boston_housing.csv") #返回的是DataFrame类型

3.数据概览

df.head(n):查看DataFrame对象的前n行,默认是5行
data.tail(n):查看DataFrame对象的后n行,默认是5行
data.info(): 查看索引、数据类型和内存信息
data.isnull():检查DataFrame对象中的空值,并返回一个Boolean数组   data.describe():查看数值型列的汇总统计  

In [40]:
data.head(5) #查看DataFrame对象的前5行数据
Out[40]:
CRIMZNINDUSCHASNOXRMAGEDISRADTAXPTRATIOBLSTATMEDV
00.00632182.3100.5386.57565.24.0900129615396.904.9824.0
10.0273107.0700.4696.42178.94.9671224217396.909.1421.6
20.0272907.0700.4697.18561.14.9671224217392.834.0334.7
30.0323702.1800.4586.99845.86.0622322218394.632.9433.4
40.0690502.1800.4587.14754.26.0622322218396.905.3336.2
In [41]:
data.tail(5) #查看DataFrame对象的后5行数据
Out[41]:
CRIMZNINDUSCHASNOXRMAGEDISRADTAXPTRATIOBLSTATMEDV
5010.06263011.9300.5736.59369.12.4786127321391.999.6722.4
5020.04527011.9300.5736.12076.72.2875127321396.909.0820.6
5030.06076011.9300.5736.97691.02.1675127321396.905.6423.9
5040.10959011.9300.5736.79489.32.3889127321393.456.4822.0
5050.04741011.9300.5736.03080.82.5050127321396.907.8811.9
In [42]:
data.info() #查看索引、数据类型和内存信息
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 506 entries, 0 to 505
Data columns (total 14 columns):
CRIM       506 non-null float64
ZN         506 non-null int64
INDUS      506 non-null float64
CHAS       506 non-null int64
NOX        506 non-null float64
RM         506 non-null float64
AGE        506 non-null float64
DIS        506 non-null float64
RAD        506 non-null int64
TAX        506 non-null int64
PTRATIO    506 non-null int64
B          506 non-null float64
LSTAT      506 non-null float64
MEDV       506 non-null float64
dtypes: float64(9), int64(5)
memory usage: 55.4 KB
In [43]:
data.isnull().sum() #检查DataFrame对象中的是否存在空值
Out[43]:
CRIM       0
ZN         0
INDUS      0
CHAS       0
NOX        0
RM         0
AGE        0
DIS        0
RAD        0
TAX        0
PTRATIO    0
B          0
LSTAT      0
MEDV       0
dtype: int64
In [44]:
data.describe() #查看数值型列的汇总统计
Out[44]:
CRIMZNINDUSCHASNOXRMAGEDISRADTAXPTRATIOBLSTATMEDV
count506.000000506.000000506.000000506.000000506.000000506.000000506.000000506.000000506.000000506.000000506.000000506.000000506.000000506.000000
mean3.61352411.34782611.1367790.0691700.5546956.28463468.5749013.7950439.549407408.23715418.083004356.67403212.65306322.532806
std8.60154523.3105936.8603530.2539940.1158780.70261728.1488612.1057108.707259168.5371162.28057491.2948647.1410629.197104
min0.0063200.0000000.4600000.0000000.3850003.5610002.9000001.1296001.000000187.00000012.0000000.3200001.7300005.000000
25%0.0820450.0000005.1900000.0000000.4490005.88550045.0250002.1001754.000000279.00000017.000000375.3775006.95000017.025000
50%0.2565100.0000009.6900000.0000000.5380006.20850077.5000003.2074505.000000330.00000019.000000391.44000011.36000021.200000
75%3.67708212.00000018.1000000.0000000.6240006.62350094.0750005.18842524.000000666.00000020.000000396.22500016.95500025.000000
max88.976200100.00000027.7400001.0000000.8710008.780000100.00000012.12650024.000000711.00000022.000000396.90000037.97000050.000000

此处得到各属性的样本数目、均值、标准差、最小值、1/4分位数(25%)、中位数(50%)、3/4分位数(75%)、最大值 可初步了解各特征的分布

4.以数据可视化的方式查看各属性的统计特征

(1) 直方图distplot

seaborn.distplot(a, bins=None, ..., kde=True,....)

a:数据, bins:箱子数,kde:是否进行核密度估计

In [45]:
from matplotlib.font_manager import FontProperties   #添加相关包,指定相关字体
font_set = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=12)

# 房价(即目标)的直方图
sns.distplot(data.MEDV.values, bins=30,kde=True)
plt.xlabel(u"房价分布",fontproperties=font_set)
plt.show()
In [46]:
# 犯罪率的直方图
sns.distplot(data.CRIM.values, bins=30, kde=False)
plt.xlabel(u"犯罪率直方图", fontproperties=font_set)
plt.show()

犯罪率特征的分布是长尾分布,和指数分布比较接近。大部分城镇的犯罪率很低,极少数样本的犯罪率高。从常理看,该数值应该比较准确,可以不予处理。

(2)散点图scatter

In [47]:
# 房价(即目标)的散点图
plt.scatter(range(data.shape[0]), data.MEDV.values, color='purple')
plt.title(u"房价的散点分布",fontproperties=font_set)
Out[47]:
<matplotlib.text.Text at 0x10afe7b8>

可以看出,数据大多集中在均值附近,和正态分布比较接近。但最大值50的样本数目偏多,可能是原始数据将所有大于50的样本的值都设置为50(猜测),在模型训练时也可以考虑将y等于50的样本当成outliers(离群点)去掉。

(3)计数图countplot

计数图,可将它认为一种应用到分类变量的直方图,用以统计不同的类别的计数值:

seaborn.countplot(x=None, y=None, hue=None, data=None, order=None, ...)

order:控制变量绘图的顺序

In [30]:
#sns.countplot(data.ZN)
#sns.countplot(data.CHAS, order=[0,1]) #与下面等价
sns.countplot(data.CHAS)
Out[30]:
<matplotlib.axes._subplots.AxesSubplot at 0xc5dd780>
In [48]:
sns.countplot(data.RAD)
Out[48]:
<matplotlib.axes._subplots.AxesSubplot at 0x11be3898>

5.两两特征之间的相关性

a.希望特征与标签之间强相关
b.如果特征和特征之间强相关,说明信息冗余,可常用处理方法:
1)两个特征之间只保留其中一个特征。
2)采用组成分析(PCA)等进行降维。
3)在模型的正则项采用L1正则。

(1)热力图heatmap

seaborn.heatmap(data, vmin=None, vmax=None, cmap=None, center=None, robust=False, annot=None, fmt='.2g', annotkws=None, linewidths=0, linecolor='white', cbar=True, cbarkws=None, cbar_ax=None, square=False, ax=None, xticklabels=True, yticklabels=True, mask=None, **kwargs)

data:矩阵数据集,可以使numpy的数组(array),如果是pandas的dataframe,则dataframe的index/column信息会分别对应到heatmap的columns和rows。
linewidths:热力图矩阵之间的间隔大小。
vmax,vmin:图例中最大值和最小值的显示值,没有该参数时默认不显示。
annot : bool or rectangular dataset, optional,If True, write the data value in each cell,显示数值。
mask : boolean array or DataFrame, optional。If passed, data will not be shown in cells where mask is True.
cbar : boolean, optionalWhether to draw a colorbar.

In [49]:
plt.subplots(figsize=(13,9)) #指定窗口尺寸(单位英尺)
data_corr=data.corr().abs() #返回列与列之间的相关系数

#数据为相关系数,显示数值,显示颜色条
sns.heatmap(data_corr, annot=True)
Out[49]:
<matplotlib.axes._subplots.AxesSubplot at 0x111510b8>

(2)打印出两两特征之间的相关系数

sorted(list, key=lambda x: -abs(x[0]))

参数key是关键词, lambda是一个隐函数,是固定写法,表示按照列表x的-abs(x[0])这个值进行排序,其中x可为任意名称,指代前面的列表list。

DataFrame.iloc[i,j]:按位置选取数据
In [35]:
cols = data.columns #获取列的名称
corr_list = []
size = data.shape[1]

for i in range(0, size):
    for j in range(i+1, size):
        if(abs(data_corr.iloc[i,j])>= 0.5):
            corr_list.append([data_corr.iloc[i,j], i, j]) #data_corr.iloc[i,j]:按位置选取数据
                      
sorted_corr_list = sorted(corr_list, key=lambda xx:-abs(xx[0]))

for v,i,j in sorted_corr_list:
    print("%s and %s = %.2f" % (cols[i], cols[j],v)) # cols: 列名           
RAD and TAX = 0.91
NOX and DIS = 0.77
INDUS and NOX = 0.76
AGE and DIS = 0.75
LSTAT and MEDV = 0.74
NOX and AGE = 0.73
INDUS and TAX = 0.72
INDUS and DIS = 0.71
RM and MEDV = 0.70
NOX and TAX = 0.67
ZN and DIS = 0.66
INDUS and AGE = 0.64
CRIM and RAD = 0.63
RM and LSTAT = 0.61
NOX and RAD = 0.61
INDUS and LSTAT = 0.60
AGE and LSTAT = 0.60
INDUS and RAD = 0.60
NOX and LSTAT = 0.59
CRIM and TAX = 0.58
ZN and AGE = 0.57
TAX and LSTAT = 0.54
DIS and TAX = 0.53
ZN and INDUS = 0.53
ZN and NOX = 0.52
AGE and TAX = 0.51
PTRATIO and MEDV = 0.51

通常认为相关系数大于0.5的为强相关,可以看出相关系数大于0.5的特征较多,可对数据进行降维处理,例如去掉一个特征,或者使用主成分分析(PCA),L1正则等进行处理。

(3)呈现数据集中成对的关系pairplot

seaborn.pairplot(data, hue=None, hue_order=None, palette=None, vars=None, x_vars=None, y_vars=None, kind='scatter', diag_kind='hist', markers=None, size=2.5, aspect=1, dropna=True, plot_kws=None, diag_kws=None, grid_kws=None)

数据指定:
vars : 与data使用,否则使用data的全部变量。参数类型:numeric类型的变量list。
{x, y}_vars : 与data使用,否则使用data的全部变量。参数类型:numeric类型的变量list。即指定x,y数据。
dropna : 是否剔除缺失值。参数类型:boolean, optional.

特殊参数: kind : {‘scatter’, ‘reg’}, optional Kind of plot for the non-identity relationships.
diag_kind : {‘hist’, ‘kde’}, optional。Kind of plot for the diagonal subplots.

基本参数:
size : 默认 6,图的尺度大小(正方形)。参数类型:numeric
hue : 使用指定变量为分类变量画图。参数类型:string (变量名).
hue_order : list of strings Order for the levels of the hue variable in the palette.
palette : 调色板颜色.
markers : 使用不同的形状。参数类型:list.
aspect : scalar, optional。Aspect * size gives the width (in inches) of each facet.
{plot, diag, grid}_kws : 指定其他参数。参数类型:dict
返回:
PairGrid 对象.

In [37]:
for v,i,j in sorted_corr_list:
    sns.pairplot(data, size=6, x_vars=cols[i], y_vars=cols[j]) #绘制x_vars列和y_vars列特征之间的关系,看是否有线性关系
    plt.show()
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值