数据分析——"岩石 vs. 水雷"数据集分析

0.数据集介绍

数据集来自 UC Irvine 数据仓库。数据来源于实验:测试声纳是否可以用于检测在港口军事行动后遗留下来的未爆炸的水雷。声纳信号又叫作啁啾信号(chirped signal),即信号在一个脉冲期间频率会增加或降低。此数据集的测量值代表声纳接收器在不同地点接收到的返回信号,其中在大约一半的例子中,返回的声纳信号反映的是岩石的形状,而另一半是金属圆筒的形状(水雷)。下文就用“岩石 vs. 水雷”来代表这个数据集。

1.确定数据集的规模

import urllib.request
import sys

## 从数据仓库读入数据
target_url = ("https://archive.ics.uci.edu/ml/machine-learning-databases/undocumented/connectionist-bench/sonar/sonar.all-data")
data = urllib.request.urlopen(target_url)
xList = []
labels = []
for line in data:
    ## 按逗号切
    row = str(line, encoding='utf-8').strip().split(',')
    xList.append(row)
    
sys.stdout.write("数据行数: " + str(len(xList)) + '\n')
sys.stdout.write("数据列数: " + str(len(xList[1])))
数据行数: 208
数据列数: 61

数据集的规模(行数、列数)至少在以下几个方面会影响你对数据的处理。首先,根据数据的规模可以大致判断训练所需的时间。对于像“岩石 vs. 水雷”这种小数据集,训练时间会少于 1 分钟,这有利于在训练过程中不断调整和迭代。如果数据集规模增加到1 000×1 000,惩罚线性回归训练时间将不到一分钟,而集成方法训练时间需要几分钟。如果数据集的行、列增加到万级规模,则惩罚线性回归的训练时间将达到 3 ~ 4 小时,而集成方法则长达 12 ~ 24 小时。更长的训练时间将会影响你的开发进度,因为通常需要迭代几次来对算法进行调整或优化。

2.确定属性的数据类型(数值型/类别型)

import urllib.request
import sys
## 从数据仓库读入数据
target_url = ("https://archive.ics.uci.edu/ml/machine-learning-databases/undocumented/connectionist-bench/sonar/sonar.all-data")
data = urllib.request.urlopen(target_url)
xList = []
labels = []
for line in data:
    ## 按逗号切
    row = str(line, encoding='utf-8').strip().split(',')
    xList.append(row)

nrow = len(xList)
ncol = len(xList[1])

type_val = [0] * 3
colCounts = []

for col in range(ncol):
    for row in xList:
        try:
            a = float(row[col])
            if isinstance(a,float):
                type_val[0] += 1
        except ValueError:
            if len(row[col])> 0:
                type_val[1] += 1
            else:
                type_val[2] += 1
    colCounts.append(type_val)
    type_val = [0]*3
    
sys.stdout.write("Col#" + '\t' + "Number" + '\t' + "Strings" + '\t ' + "Other\n")
iCol = 0
for types in colCounts:
    sys.stdout.write(str(iCol) + '\t' + str(types[0]) + '\t' + str(types[1]) + '\t' + str(types[2]) + "\n")
    iCol += 1
Col#	Number	Strings	 Other
0	208	0	0
1	208	0	0
2	208	0	0
3	208	0	0
4	208	0	0
5	208	0	0
6	208	0	0
7	208	0	0
8	208	0	0
9	208	0	0
10	208	0	0
11	208	0	0
12	208	0	0
13	208	0	0
14	208	0	0
15	208	0	0
16	208	0	0
17	208	0	0
18	208	0	0
19	208	0	0
20	208	0	0
21	208	0	0
22	208	0	0
23	208	0	0
24	208	0	0
25	208	0	0
26	208	0	0
27	208	0	0
28	208	0	0
29	208	0	0
30	208	0	0
31	208	0	0
32	208	0	0
33	208	0	0
34	208	0	0
35	208	0	0
36	208	0	0
37	208	0	0
38	208	0	0
39	208	0	0
40	208	0	0
41	208	0	0
42	208	0	0
43	208	0	0
44	208	0	0
45	208	0	0
46	208	0	0
47	208	0	0
48	208	0	0
49	208	0	0
50	208	0	0
51	208	0	0
52	208	0	0
53	208	0	0
54	208	0	0
55	208	0	0
56	208	0	0
57	208	0	0
58	208	0	0
59	208	0	0
60	0	208	0

3.数值型和类别型属性的统计信息

确定哪些属性是类别型,哪些是数值型之后,下一步就是获得数值型属性的描述性统计信息和类别型属性具体类别的数量分布

import urllib.request
import sys
import numpy as np
## 从数据仓库读入数据
target_url = ("https://archive.ics.uci.edu/ml/machine-learning-databases/undocumented/connectionist-bench/sonar/sonar.all-data")
data = urllib.request.urlopen(target_url)
xList = []
labels = []
for line in data:
    ## 按逗号切
    row = str(line, encoding='utf-8').strip().split(',')
    xList.append(row)

nrow = len(xList)
ncol = len(xList[1])

type_val = [0] * 3
colCounts = []

## 生成统计汇总(以第3列为例)
col = 3
colData = []
for row in xList:
    colData.append(float(row[col]))
    
colArray = np.array(colData)
colMean = np.mean(colArray)
colsd = np.std(colArray)
sys.stdout.write("Mean = " + '\t' + str(colMean) + '\t\t' + "Standard Deviation = " + '\t ' + str(colsd) + "\n")

## 计算四分位点
ntiles = 4

percentBdry = []
for i in range(ntiles+1):
    percentBdry.append(np.percentile(colArray,i*(100)/ntiles))

sys.stdout.write("\nBoundaries for 4 Equal Percentiles \n")
print(percentBdry)
sys.stdout.write(" \n")

## 计算十分位点
ntiles = 10

percentBdry = []
for i in range(ntiles+1):
    percentBdry.append(np.percentile(colArray,i*(100)/ntiles))

sys.stdout.write("\nBoundaries for 10 Equal Percentiles \n")
print(percentBdry)
sys.stdout.write(" \n")

## 最后一列包含类别变量

col = 60
colData = []
for row in xList:
    colData.append(row[col])

unique = set(colData)
sys.stdout.write("Unique Label Values \n")
print(unique)

catDict = dict(zip(list(unique),range(len(unique))))
catCount = [0]*2

for elt in colData:
    catCount[catDict[elt]] +=1
sys.stdout.write("\nCounts for Each Value of Categorical Label \n")
print(list(unique))
print(catCount)
Mean = 	0.053892307692307684		Standard Deviation = 	 0.04641598322260027

Boundaries for 4 Equal Percentiles 
[0.0058, 0.024375, 0.04405, 0.0645, 0.4264]
 

Boundaries for 10 Equal Percentiles 
[0.0058, 0.0141, 0.022740000000000003, 0.027869999999999995, 0.03622, 0.04405, 0.05071999999999999, 0.059959999999999986, 0.07794000000000001, 0.10836, 0.4264]
 
Unique Label Values 
{'M', 'R'}

Counts for Each Value of Categorical Label 
['M', 'R']
[111, 97]

代码第一部分读取数值型数据的某一列,然后产生它的统计信息。第一步计算此属性的均值和方差。了解这些统计信息可以加强在建立预测模型时的直观感受。
第二部分代码主要是为了找到异常值。基本过程如下:假设在下面数值列表 [0.1,0.15,0.2,0.25,0.3,0.35,0.4,4] 中确定是否有异常值,显然最后一个数“4”是异常值。

4.用分位图展示异常点

更具体地研究异常点(异常值)的一个方法就是画出数据的分布图,然后与可能的分布进行比较,判断相关的数据是否匹配。

import urllib.request
import sys
import numpy as np
import pylab
import scipy.stats as stats

## 从数据仓库读入数据
target_url = ("https://archive.ics.uci.edu/ml/machine-learning-databases/undocumented/connectionist-bench/sonar/sonar.all-data")
data = urllib.request.urlopen(target_url)
xList = []
labels = []
for line in data:
    ## 按逗号切
    row = str(line, encoding='utf-8').strip().split(',')
    xList.append(row)

nrow = len(xList)
ncol = len(xList[1])

type_val = [0] * 3
colCounts = []

## 生成统计汇总(以第3列为例)
col = 3
colData = []
for row in xList:
    colData.append(float(row[col]))
    
stats.probplot(colData,dist="norm",plot=pylab)
pylab.show()

在这里插入图片描述

那么如何利用这些信息?异常点在建模或预测期间都会带来麻烦。基于此数据集训练完一个模型后,可以查看此模型预测错误的情况,然后确认此错误是否与这些异常点有关。如果确实是这样的话,可以采取步骤进行校正。例如,可以复制这些预测模型表现不好的例子,以加强这些例子在数据集中的比重。也可以把这些不好的例子分离出来,然后单独训练。如果认为预测模型在真正部署时不会遇到此类异常数据,则也可以把这些例子排除出数据集。一个可行办法是在对数据集进行探究阶段,先产生四分位数边界,然后看看潜在的异常点的规模对后续建模及预测可能的影响。这样在分析错误时,可以通过分位数图(quantile-quantile,Q-Q)确定哪些数据可以称为异常点。

5.类别属性的统计特征

上述的分析过程只适用于数值属性。对于类别属性我们想知道是一共可以分为几类、每类数据的数目。

import pandas as pd
from pandas import DataFrame
import matplotlib.pyplot as plot 
target_url = ("https://archive.ics.uci.edu/ml/machine-learning-databases/undocumented/connectionist-bench/sonar/sonar.all-data")
rocksVMines = pd.read_csv(target_url,header=None,prefix="V")
print(rocksVMines.head())
print(rocksVMines.tail())

summary = rocksVMines.describe()
print(summary)
       V0      V1      V2      V3      V4      V5      V6      V7      V8  \
0  0.0200  0.0371  0.0428  0.0207  0.0954  0.0986  0.1539  0.1601  0.3109   
1  0.0453  0.0523  0.0843  0.0689  0.1183  0.2583  0.2156  0.3481  0.3337   
2  0.0262  0.0582  0.1099  0.1083  0.0974  0.2280  0.2431  0.3771  0.5598   
3  0.0100  0.0171  0.0623  0.0205  0.0205  0.0368  0.1098  0.1276  0.0598   
4  0.0762  0.0666  0.0481  0.0394  0.0590  0.0649  0.1209  0.2467  0.3564   

       V9  ...     V51     V52     V53     V54     V55     V56     V57  \
0  0.2111  ...  0.0027  0.0065  0.0159  0.0072  0.0167  0.0180  0.0084   
1  0.2872  ...  0.0084  0.0089  0.0048  0.0094  0.0191  0.0140  0.0049   
2  0.6194  ...  0.0232  0.0166  0.0095  0.0180  0.0244  0.0316  0.0164   
3  0.1264  ...  0.0121  0.0036  0.0150  0.0085  0.0073  0.0050  0.0044   
4  0.4459  ...  0.0031  0.0054  0.0105  0.0110  0.0015  0.0072  0.0048   

      V58     V59  V60  
0  0.0090  0.0032    R  
1  0.0052  0.0044    R  
2  0.0095  0.0078    R  
3  0.0040  0.0117    R  
4  0.0107  0.0094    R  

[5 rows x 61 columns]
         V0      V1      V2      V3      V4      V5      V6      V7      V8  \
203  0.0187  0.0346  0.0168  0.0177  0.0393  0.1630  0.2028  0.1694  0.2328   
204  0.0323  0.0101  0.0298  0.0564  0.0760  0.0958  0.0990  0.1018  0.1030   
205  0.0522  0.0437  0.0180  0.0292  0.0351  0.1171  0.1257  0.1178  0.1258   
206  0.0303  0.0353  0.0490  0.0608  0.0167  0.1354  0.1465  0.1123  0.1945   
207  0.0260  0.0363  0.0136  0.0272  0.0214  0.0338  0.0655  0.1400  0.1843   

         V9  ...     V51     V52     V53     V54     V55     V56     V57  \
203  0.2684  ...  0.0116  0.0098  0.0199  0.0033  0.0101  0.0065  0.0115   
204  0.2154  ...  0.0061  0.0093  0.0135  0.0063  0.0063  0.0034  0.0032   
205  0.2529  ...  0.0160  0.0029  0.0051  0.0062  0.0089  0.0140  0.0138   
206  0.2354  ...  0.0086  0.0046  0.0126  0.0036  0.0035  0.0034  0.0079   
207  0.2354  ...  0.0146  0.0129  0.0047  0.0039  0.0061  0.0040  0.0036   

        V58     V59  V60  
203  0.0193  0.0157    M  
204  0.0062  0.0067    M  
205  0.0077  0.0031    M  
206  0.0036  0.0048    M  
207  0.0061  0.0115    M  

[5 rows x 61 columns]
               V0          V1          V2          V3          V4          V5  \
count  208.000000  208.000000  208.000000  208.000000  208.000000  208.000000   
mean     0.029164    0.038437    0.043832    0.053892    0.075202    0.104570   
std      0.022991    0.032960    0.038428    0.046528    0.055552    0.059105   
min      0.001500    0.000600    0.001500    0.005800    0.006700    0.010200   
25%      0.013350    0.016450    0.018950    0.024375    0.038050    0.067025   
50%      0.022800    0.030800    0.034300    0.044050    0.062500    0.092150   
75%      0.035550    0.047950    0.057950    0.064500    0.100275    0.134125   
max      0.137100    0.233900    0.305900    0.426400    0.401000    0.382300   

               V6          V7          V8          V9  ...         V50  \
count  208.000000  208.000000  208.000000  208.000000  ...  208.000000   
mean     0.121747    0.134799    0.178003    0.208259  ...    0.016069   
std      0.061788    0.085152    0.118387    0.134416  ...    0.012008   
min      0.003300    0.005500    0.007500    0.011300  ...    0.000000   
25%      0.080900    0.080425    0.097025    0.111275  ...    0.008425   
50%      0.106950    0.112100    0.152250    0.182400  ...    0.013900   
75%      0.154000    0.169600    0.233425    0.268700  ...    0.020825   
max      0.372900    0.459000    0.682800    0.710600  ...    0.100400   

              V51         V52         V53         V54         V55         V56  \
count  208.000000  208.000000  208.000000  208.000000  208.000000  208.000000   
mean     0.013420    0.010709    0.010941    0.009290    0.008222    0.007820   
std      0.009634    0.007060    0.007301    0.007088    0.005736    0.005785   
min      0.000800    0.000500    0.001000    0.000600    0.000400    0.000300   
25%      0.007275    0.005075    0.005375    0.004150    0.004400    0.003700   
50%      0.011400    0.009550    0.009300    0.007500    0.006850    0.005950   
75%      0.016725    0.014900    0.014500    0.012100    0.010575    0.010425   
max      0.070900    0.039000    0.035200    0.044700    0.039400    0.035500   

              V57         V58         V59  
count  208.000000  208.000000  208.000000  
mean     0.007949    0.007941    0.006507  
std      0.006470    0.006181    0.005031  
min      0.000300    0.000100    0.000600  
25%      0.003600    0.003675    0.003100  
50%      0.005800    0.006400    0.005300  
75%      0.010350    0.010325    0.008525  
max      0.044000    0.036400    0.043900  

[8 rows x 60 columns]

Pandas 可以自动计算出均值、方差、分位数。由于 describe 函数输出的总结(统计信息)本身就是一个数据框,因此可以自动化属性值的筛选过程以发现异常点。可以比较不同分位数之间的差异。对于同一属性列,如果存在某一个差异严重异于其他差异,则说明存在异常点。这就值得进一步探究这些异常点牵扯到多少行数据,这些异常点涉及的数据很可能是少量的,这些都需要仔细分析。

6.利用平行坐标图进行可视化展示

import pandas as pd
from pandas import DataFrame
import matplotlib.pyplot as plot 
target_url = ("https://archive.ics.uci.edu/ml/machine-learning-databases/undocumented/connectionist-bench/sonar/sonar.all-data")
rocksVMines = pd.read_csv(target_url,header=None,prefix="V")

for i in range(208):
    if rocksVMines.iat[i,60] == "M":
        pcolor = "red"
    else:
        pcolor = "blue"
    
    #plot rows of data as if they were series data
    dataRow = rocksVMines.iloc[i,0:60]
    dataRow.plot(color=pcolor)
    
plot.xlabel("Attribute Index")
plot.ylabel("Attribute Values")
plot.show()    

在这里插入图片描述

7.属性和标签的关系可视化

另外一个需要了解的问题就是属性之间的关系。获得这种成对关系的快速方法就是绘制属性与标签的交会图(cross-plots)

import pandas as pd
from pandas import DataFrame
import matplotlib.pyplot as plot 
target_url = ("https://archive.ics.uci.edu/ml/machine-learning-databases/undocumented/connectionist-bench/sonar/sonar.all-data")
rocksVMines = pd.read_csv(target_url,header=None,prefix="V")

dataRow2 = rocksVMines.iloc[1,0:60]
dataRow3 = rocksVMines.iloc[2,0:60]
plot.scatter(dataRow2,dataRow3)
plot.xlabel("2nd Attribute")
plot.ylabel(("3rd Attribute"))
plot.show()

dataRow21 = rocksVMines.iloc[20,0:60]
plot.scatter(dataRow2,dataRow21)

plot.xlabel("2nd Attribute")
plot.ylabel("21st Attribute")
plot.show()

在这里插入图片描述
在这里插入图片描述
如果散点图上的点沿着一条“瘦”直线排列,则说明这两个变量强相关;如果这些点形成一个球型,则说明这些点不相关。

import pandas as pd
from pandas import DataFrame
import matplotlib.pyplot as plot 
from random import uniform

target_url = ("https://archive.ics.uci.edu/ml/machine-learning-databases/undocumented/connectionist-bench/sonar/sonar.all-data")
rocksVMines = pd.read_csv(target_url,header=None,prefix="V")

target = []
for i in range(208):
    if rocksVMines.iat[i,60] == "M":
        target.append(1.0)
    else:
        target.append(0.0)
        
## 画出第35属性
dataRow = rocksVMines.iloc[0:208,35]
plot.scatter(dataRow,target)
plot.xlabel("Attribute Value")
plot.ylabel("Target Value")
plot.show()

## 为了让可视化更明显,加上抖动
target = []
for i in range(208):
    if rocksVMines.iat[i,60] == "M":
        target.append(1.0 + uniform(-0.1,0.1))
    else:
        target.append(0.0 + uniform(-0.1,0.1))
dataRow = rocksVMines.iloc[0:208,35]
plot.scatter(dataRow,target,alpha=0.5,s=120)

plot.xlabel("Attribute Value")
plot.ylabel("Target Value")
plot.show()

在这里插入图片描述
在这里插入图片描述

这里把M用 1 代表,R用0代表,得到如图1所示的散点图。在图1中可以看到一个交会图常见的问题。当其中一个变量只取有限的几个值时,很多点会重叠在一起。如果这种点很多,则只能看到很粗的一条线,分辨不出这些点是如何沿线分布的。第二图通过 2 个小技巧克服了上述的问题。每个点都加上一个小的随机数,产生了少量的离散值(这里是对标签值进行了处理)。标签值最初是0或 1。在代码中可以看到,标签值加上了一个在 −0.1 和 0.1 之间均匀分布的随机数,这样就把这些点分散开,但是又不至于把这 2 条线混淆。此外,这些点绘制时取 alpha=0.5,这样这些点就是半透明的。那么在散点图中若多个点落在一个位置就会形成一个更黑的区域,这时需要对数据做一些微调使你能看到你想看到的。

8.皮尔逊相关系数

两个属性(或一个属性、一个标签)的相关程度可以由皮尔逊相关系数(Pearson’s correlation coefficient)来量化。给定2个等长的向量 u 和 v,首先 u 的所有元素都减去 u 的均值得到∆u,对 v 也做同样的处理得到∆v,则u和v之间的皮尔逊相关系数如下所示:
在这里插入图片描述

import pandas as pd
from pandas import DataFrame
import matplotlib.pyplot as plot 
from random import uniform
from math import sqrt

target_url = ("https://archive.ics.uci.edu/ml/machine-learning-databases/undocumented/connectionist-bench/sonar/sonar.all-data")
rocksVMines = pd.read_csv(target_url,header=None,prefix="V")

## 计算皮尔逊相关系数
dataRow2 = rocksVMines.iloc[1,0:60]
dataRow3 = rocksVMines.iloc[2,0:60]
dataRow21 = rocksVMines.iloc[20,0:60]
mean2 = 0.0
mean3 = 0.0
mean21 = 0.0
numElt = len(dataRow2)
for i in range(numElt):
    mean2 += dataRow2[i]/numElt
    mean3 += dataRow3[i]/numElt
    mean21 += dataRow21[i]/numElt
    
var2 = 0.0
var3 = 0.0
var21 = 0.0
for i in range(numElt):
    var2 += (dataRow2[i] - mean2) * (dataRow2[i] - mean2)/numElt
    var3 += (dataRow3[i] - mean3) * (dataRow3[i] - mean3)/numElt
    var21 += (dataRow21[i] - mean21) * (dataRow21[i] - mean21)/numElt
    
corr23 = 0.0
corr221 = 0.0
for i in range(numElt):
    corr23 += (dataRow2[i] - mean2) * (dataRow3[i] - mean3) / (sqrt(var2*var3) * numElt)
    corr221 += (dataRow2[i] - mean2) * (dataRow21[i] - mean21) / (sqrt(var2*var21) * numElt)
    
sys.stdout.write("Correlation between attribute 2 and 3 \n")
print(corr23)
sys.stdout.write(" \n")
sys.stdout.write("Correlation between attribute 2 and 21 \n")
print(corr221)
sys.stdout.write(" \n")
Correlation between attribute 2 and 3 
0.7709381211911223
 
Correlation between attribute 2 and 21 
0.46654808078868865

9.用热图(heat map)展示属性和标签的相关性

对于计算少量的相关性,将相关性结果打印输出或者画成散点图都是可以的。但是对于大量的数据,就很难用这种方法整体把握相关性。如果问题有 100 以上的属性,则很难把散点图压缩到一页。获得大量属性之间相关性的一种方法就是计算出每对属性的皮尔森相关系数后,将相关系数构成一个矩阵,矩阵的第 ij-th 个元素对应第 i 个属性与第 j 个属性的相关系数,然后把这些矩阵元素画到热图上。

import pandas as pd
from pandas import DataFrame
import matplotlib.pyplot as plot 
from random import uniform
from math import sqrt

target_url = ("https://archive.ics.uci.edu/ml/machine-learning-databases/undocumented/connectionist-bench/sonar/sonar.all-data")
rocksVMines = pd.read_csv(target_url,header=None,prefix="V")

#calculate correlations between real-valued attributes
corMat = DataFrame(rocksVMines.corr())
#visualize correlations using heatmap
plot.pcolor(corMat)
plot.show()

在这里插入图片描述
属性之间如果完全相关(相关系数 =1)意味着数据可能有错误,如同样的数据录入两次。多个属性间的相关性很高(相关系数 >0.7),即多重共线性(multicollinearity),往往会导致预测结果不稳定。属性与标签的相关性则不同,如果属性和标签相关,则通常意味着两者之间具有可预测的关系。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值