在构建机器学习预测分析模型之前,我们首先要做的就是把源数据基本情况搞清楚搞明白。源数据分为属性数据和标签数据,属性数据就是数学含义下的自变量,标签数据就是数学含义下的因变量(函数)。属性和标签的不同类型决定模型的选择。初始审视数据集时,需要考虑数据集的相关特性,如下:
• 行数、列数
• 类别变量的数目、类别变量的取值范围
• 缺失的值(检测与处理)
• 属性和标签的统计特性
• 异常值(检测与处理)
拿到数据后我们第一件事情是要搞清楚数据的规模,行数列数,每列数据具体情况,属性标签的统计特征等。
首先看一下数据的整体规模,代码如下:
import urllib.request, urllib.error, urllib.parse
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 = line.strip().decode().split(",")
xList.append(row)
sys.stdout.write("Number of Rows of Data = " + str(len(xList)) + '\n')
sys.stdout.write("Number of Columns of Data = " + str(len(xList[1])))
运行结果为:
看完数据集整体情况后,如果要观测某一列数据情况,可以通过如下代码查看:
import urllib.request, urllib.error, urllib.parse
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:
#split on comma
row = line.strip().decode().split(",")
xList.append(row)
nrow = len(xList)
ncol = len(xList[1])
type = [0]*3
colCounts = []
#以第三列为例
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")
#计算4分位数
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("Boundaries 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)
运行结果为:
代码第一部分读取数据的某一列,这里是以第3列为例,然后生成它的统计信息。第一步计算均值和方差,第二步分计算分位数,分别计算了四分位数和十分位数。通过分位数可以判断是否有异常值存在。最后分析了一下标签列的数据分布情况。
也可以对数据的每一列进行描述性的数据分析,列出均值、标准差、分位数等。代码如下:
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)
描述性分析的结果如下:
通过这种方式虽然也能看出一些问题,但是最直接的方式非可视化莫属。利用平行坐标图进行可视化展示是一种非常好的方式,基于标签对折现标不同的颜色,可以直观的观测属性与标签之间的关系。下面以Iris数据集(鸢尾花卉数据集)为例,看一下平行坐标图。代码如下:
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
from pandas.plotting import parallel_coordinates
data = sns.load_dataset('iris')
fig,axes = plt.subplots()
parallel_coordinates(data,'species',ax=axes)
fig.savefig('parallel.png')
运行结果如下:
通过平行坐标图可以看到,不同种类的鸢尾花卉的petal_length和petal_width这两个指标差异较大。通过源数据的分析,更加有利于选择模型,达到机器学习算法进行分类的目标。
另一个需要了解的就是属性之间的关系,获取这种成对关系的快速方法就是绘制交会图(散点图),通过交会图观察变量之间的关系。
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()
本段代码绘制了两个图,分别是第二个变量和第三个变量之间的交会图,第二个变量和第21个变量之间的交会图。
如果是一个分类标签和一个数值标签之间的交会图,那么我们需要做一些简单的加小随机数的方法。
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):
#1和0分别代表 "M"和"R"
if rocksVMines.iat[i,60] == "M":
target.append(1.0)
else:
target.append(0.0)
#绘制原始值交会图
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):
#1和0分别代表 "M"和"R"
# 加一个小的随机数
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()
结果如下:
可以看出,加了小的随机数之后,变量之间的关系可以看的更加清晰。
除此之外,我们经常用数值方法判断数据之间的相关性,例如:皮尔逊法。
import pandas as pd
from pandas import DataFrame
from math import sqrt
import sys
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")
通过相关系数可见,特征2和特征3之间的相关系数比特征2与特征21之间相关系数更大,说明特征2与特征3之间的相关性更强一些。相关系数大于0为正相关,小于0为负相关。1为完全正相关,-1为完全负相关。
All things are difficult before they are easy.