您当前的位置: 首页 >  算法

凌云时刻

暂无认证

  • 0浏览

    0关注

    1437博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

机器学习笔记(三):NumPy、Matplotlib、kNN算法 | 凌云时刻

凌云时刻 发布时间:2020-06-23 20:49:24 ,浏览量:0

凌云时刻 · 技术

导读:NumPy是Python中的一个类库,它支持高阶维度数组(矩阵)的创建及各种操作、运算,是我们在机器学习中经常会使用的一个类库。这一节再看一些NumPy的矩阵用法。

作者 | 计缘

来源 | 凌云时刻(微信号:linuxpk)

 numpy.random

NumPy也提供了生成随机数和随机元素数组的方法,我们来看一下:

# 生成从0到10之间的随机数
np.random.randint(0, 10)
# 结果
3

# 生成元素从0到10,一共4个随机元素的数组
np.random.randint(0, 10, size=4)
# 结果
array([4, 7, 8, 1])

# 生成元素随机从0到10,3行5列的矩阵
np.random.randint(0, 10, size=(3, 5))
# 结果
array([[6, 9, 7, 0, 9],
	   [7, 4, 8, 7, 8],
	   [4, 4, 9, 7, 2]])

如果我们希望每次使用随机方法生成的结果都是一样的,一般调试时候有这个需求,此时NumPy的random()方法也提供了方便简单的方式,既随机种子的概念:

# 生成随机矩阵前给定一个种子
np.random.seed(123)
# 然后生成随机矩阵
np.random.randint(0, 10, size=(4, 5))
# 结果
array([[2, 2, 6, 1, 3],
	   [9, 6, 1, 0, 1],
	   [9, 0, 0, 9, 3],
	   [4, 0, 0, 4, 1]])

# 再次生成随机矩阵时,只要传入相同的种子,就可以得到相同结果的矩阵
np.random.seed(123)
np.random.randint(0, 10, size=(4, 5))
# 结果
array([[2, 2, 6, 1, 3],
	   [9, 6, 1, 0, 1],
	   [9, 0, 0, 9, 3],
	   [4, 0, 0, 4, 1]])

# 默认范围是从0.0到1.0,返回值为float型
np.random.random()
# 结果
0.18249173045349998

# 传入的参数是数组的大小
np.random.random(10)
# 结果
array([ 0.17545176,  0.53155137,  0.53182759,  0.63440096,  0.84943179,
		0.72445532,  0.61102351,  0.72244338,  0.32295891,  0.36178866])

# 创建4行5列,元素值的范围从0.0到1.0的矩阵
np.random.random((4, 5))
# 结果
array([[ 0.22826323,  0.29371405,  0.63097612,  0.09210494,  0.43370117],
	   [ 0.43086276,  0.4936851 ,  0.42583029,  0.31226122,  0.42635131],
	   [ 0.89338916,  0.94416002,  0.50183668,  0.62395295,  0.1156184 ],
	   [ 0.31728548,  0.41482621,  0.86630916,  0.25045537,  0.48303426]])
 指定均值和标准差生成随机数数组或矩阵

我们先来看看均值、方差、标准差的概念。均值很好理解,就是所有样本数据的平均值,描述了样本集合的中间点:

   

方差是衡量样本点和样本期望值相差的度量值:

   

标准差描述的是样本集合的各个样本点到均值的距离之平均:

   

标准差也就是对方差开根号。举个例子,[0, 8, 12, 20][8, 9, 11, 12],两个集合的均值都是10,但显然两个集合的差别是很大的,计算两者的标准差,前者是8.3后者是1.8,显然后者较为集中,标准差描述的就是这种散布度或者叫做波动大小。综上,方差的意义在于描述随机变量稳定与波动、集中与分散的状况。标准差则体现随机变量取值与其期望值的偏差。

NumPy也提供了指定均值和标准差生成随机数的方法,我们来看一下:

# 第一个参数是均值,第二个参数是标准差
np.random.normal(10, 100)
# 结果
53.781947121910044

# 创建均值为10,方差为100的3行5列矩阵
np.random.normal(10, 100, size=(3, 5))
# 结果
array([[ 124.10915759,   27.14517732, -144.95788359,  -87.40234817,
		 -94.91106048],
	   [ -36.4834381 ,  -39.05598871,  110.07456975,  224.85141913,
		 153.24092557],
	   [  -3.33533336,   10.57740526,  -56.76208107,  -84.06189149,
		 103.08098119]])

# 创建一个正态分布的3行5列矩阵,既均值为0,标准差为1
np.random.normal(0, 1, size=(3, 5))
# 结果
array([[-0.94574322,  2.0742057 ,  0.34477911,  0.1375712 ,  0.45385364],
	   [-2.07928914,  1.26474497,  1.56236822, -1.0032234 , -0.14807477],
	   [ 0.01992922,  0.3924738 , -0.11268871,  2.04509319,  0.01095378]])
 查看数组维度
# 生成10个元素的一维数组和3行5列的矩阵
import numpy as np
x = np.arange(10)
X = np.arange(15).reshape(3, 5)
x
X
# 结果
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
array([[ 0,  1,  2,  3,  4],
	   [ 5,  6,  7,  8,  9],
	   [10, 11, 12, 13, 14]])

# 查看x的维度
x.ndim
# 结果
1

# 查看X的维度
X.ndim
# 结果
2

# 查看数组每个维度的具体信息
x.shape
# 结果
(10,)

X.shape
# 结果
(3, 5)

 numpy.array的数据访问

 

# 一维数组访问第1个元素
x[0]
# 结果
0

# 一维数组访问最后一个元素
x[-1]
# 结果
9

# 二维数组访问第3行,第4列的元素
X[2, 3]
# 结果
13
 切片

Python中,有一个获取数组片段非常方便的方法,叫做切片,numpy.array中同样支持切片,我们来看一下:

# 获取x数组中从第1个元素到第5个元素的片段
x[0:5]
# 结果
array([0, 1, 2, 3, 4])

# 如果冒号前不指定位置,那么默认从第一个元素开始
x[:3]
# 结果
array([0, 1, 2])

# 如果冒号后面不指定位置,那么默认取到最后一个元素
x[3:]
# 结果
array([3, 4, 5, 6, 7, 8, 9])

# 切片也支持步长
x[0:10:2]
# 结果
array([0, 2, 4, 6, 8])

x[::2]
# 结果
array([0, 2, 4, 6, 8])

# 取X矩阵的前2行,前3列
X[:2, :3]
# 结果
array([[0, 1, 2],
	   [5, 6, 7]])

# 对于每个维度都可以指定步长
X[:2, ::2]
# 结果
array([[0, 2, 4],
	   [5, 7, 9]])

一般将高维矩阵降为低维矩阵其实也是使用切片来处理:

# 取X矩阵所有行的第一列
X[:, 0]
# 结果
array([ 0,  5, 10])

另外需要注意的是通过切片获取NumPy的数组或者矩阵的子数组,子矩阵是通过引用方式的,而Python中的数组通过切片获取的子数组是拷贝方式的。NumPy主要是考虑到性能效率问题。我们来看一下:

# 取X矩阵的前2行,前3列作为子矩阵
subX = X[:2, :3]
subX
# 结果
array([[0, 1, 2],
	   [5, 6, 7]])

# 给subX矩阵的第1行,第1列的元素赋值
subX[0, 0] = 100
subX
# 结果
array([[100,   1,   2],
	   [  5,   6,   7]])

# 再看看X矩阵
X
# 结果
array([[100,   1,   2,   3,   4],
	   [  5,   6,   7,   8,   9],
	   [ 10,  11,  12,  13,  14]])

# 复制子矩阵
subX1 = X[:2, :3].copy()
subX1
# 结果
array([[100,   1,   2],
	   [  5,   6,   7]])

subX1[0, 0] = 0
subX1
# 结果
array([[0, 1, 2],
	   [5, 6, 7]])

X
# 结果
array([[100,   1,   2,   3,   4],
	   [  5,   6,   7,   8,   9],
	   [ 10,  11,  12,  13,  14]])
 改变数组维度

NumPy也提供了修改数组维度的方法,我们来看看:

# x是一个一维数组
x
# 结果
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

# 将x改为二维数组,既2行5列的矩阵
x.reshape(2, 5)
x
# 结果
array([[0, 1, 2, 3, 4],
	   [5, 6, 7, 8, 9]])

# 如果想让NumPy自动计算某个维度的数,比如我只想将x转换为只有2列的矩阵,有多少行交给NumPy处理
x.reshape(-1, 2)
# 结果
array([[0, 1],
	   [2, 3],
	   [4, 5],
	   [6, 7],
	   [8, 9]])
 数组合并操作

NumPy也提供两个数组合并的操作:

x = np.arange(5)
x
# 结果
array([0, 1, 2, 3, 4])

y = np.arange(5)
y
# 结果
array([0, 1, 2, 3, 4])

# 将x,y这两个一维数组合并
np.concatenate([x, y])
# 结果
array([0, 1, 2, 3, 4, 0, 1, 2, 3, 4])

z = np.array([6, 6, 6, 6, 6])
z
# 结果
array([6, 6, 6, 6, 6])

# 将x,y,z三个一维数组合并
np.concatenate([x, y, z])
# 结果
array([0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 6, 6, 6, 6, 6])

多维数组也支持合并:

# 2行3列的矩阵
V = np.random.randint(0, 10, size=(2, 3))
V
# 结果
array([[9, 2, 0],
	   [8, 0, 2]])

# 将两个V矩阵合并
np.concatenate([V, V])
# 结果
array([[9, 2, 0],
	   [8, 0, 2],
	   [9, 2, 0],
	   [8, 0, 2]])

# 合并多维数组时,可以设置按照哪个维度合并,axis参数为0时按照行合并,axis参数为1时按照列合并,默认axis为0
np.concatenate([V, V], axis=1)
# 结果
array([[9, 2, 0, 9, 2, 0],
	   [8, 0, 2, 8, 0, 2]])

上面的示例都是同维度的数组进行合并,那么不同维度的数组如何合并呢,我们来看一下:

# z为一个一维数组
z = np.array([1, 2, 3])
z
# 结果
array([1, 2, 3])

# V为一个2行3列的矩阵
V
# 结果
array([[9, 2, 0],
	   [8, 0, 2]])

# 直接将V和z合并会抛异常
np.concatenate([V, z])
# 结果
ValueError: all the input arrays must have same number of dimensions

# 在合并时将一维数组z转变为二维数组
np.concatenate([V, z.reshape(1, -1)])
# 结果
array([[8, 2, 9],
	   [7, 3, 8],
	   [1, 2, 3]])

其实NumPy提供了更智能的不同维度数组合并的方法,我们来看一下:

# 按垂直方向合并
np.vstack([V, z])
# 结果
array([[8, 2, 9],
	   [7, 3, 8],
	   [1, 2, 3]])

# 创建一个2行2列的矩阵
V1 = np.full((2, 2), 10)
V1
# 结果
array([[10, 10],
	   [10, 10]])

# 按水平方向合并
np.hstack([V, V1])
# 结果
array([[ 8,  2,  9, 10, 10],
	   [ 7,  3,  8, 10, 10]])
 数组分割操作

有合并自然就会有分割,我们来看看NumPy提供的分割方法:

x = np.arange(10)
x
# 结果
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

# 对x进行分割,然后传入分割点,如下有两个分割点,所以将会把x分割为3个数组
x1, x2, x3 = np.split(x, [3, 7])
x1
x2
x3
# 结果
array([0, 1, 2])
array([3, 4, 5])
array([6, 7, 8, 9])

# 对于多维数组也是一样
X = np.arange(16).reshape((4, 4))
X
# 结果
array([[ 0,  1,  2,  3],
	   [ 4,  5,  6,  7],
	   [ 8,  9, 10, 11],
	   [12, 13, 14, 15]])

# 传入一个分割点,既将X矩阵分割为两个矩阵
X1, X2 = np.split(X, [2])
X1
X2
# 结果
array([[0, 1, 2, 3],
	   [4, 5, 6, 7]])
array([[ 8,  9, 10, 11],
	   [12, 13, 14, 15]])

# 分割多维数组同样可以设定按照哪个维度分割,axis默认为0,既按行分割
# axis为1时按列分割
X3, X4 = np.split(X, [2], axis=1)
X3
X4
# 结果
array([[ 0,  1],
	   [ 4,  5],
	   [ 8,  9],
	   [12, 13]])
array([[ 2,  3],
	   [ 6,  7],
	   [10, 11],
	   [14, 15]])

和合并一样,分割也有更快接的方法:

# 按垂直方向分割,既按行分割
X5, X6 = np.vsplit(X, [2])
X5
X6
# 结果
array([[0, 1, 2, 3],
	   [4, 5, 6, 7]])
array([[ 8,  9, 10, 11],
	   [12, 13, 14, 15]])

# 按水平方向分割,既按列分割
X7, X8 = np.hsplit(X, [2])
X7
X8
# 结果
array([[ 0,  1],
	   [ 4,  5],
	   [ 8,  9],
	   [12, 13]])
array([[ 2,  3],
	   [ 6,  7],
	   [10, 11],
	   [14, 15]])
 矩阵运算

NumPy中提供了完整的矩阵的运算,我们从加减法来看一下:

# A为一个2行5列的矩阵
A = np.arange(10).reshape(2, 5)
A
# 结果
array([[0, 1, 2, 3, 4],
	   [5, 6, 7, 8, 9]])

# B也是一个2行5列的矩阵
B = np.random.randint(0, 10, size=(2, 5))
B
# 结果
array([[4, 8, 3, 5, 7],
	   [9, 6, 6, 6, 6]])

# 矩阵加常数
A + 1
#结果
array([[ 1,  2,  3,  4,  5],
	   [ 6,  7,  8,  9, 10]])

# 矩阵减常数
A - 1
# 结果
array([[-1,  0,  1,  2,  3],
	   [ 4,  5,  6,  7,  8]])

# 矩阵加矩阵
A + B
# 结果
array([[ 4,  9,  5,  8, 11],
	   [14, 12, 13, 14, 15]])

# 矩阵减矩阵
A - B
# 结果
array([[-4, -7, -1, -2, -3],
	   [-4,  0,  1,  2,  3]])

下面我们再来看看数乘:

# 矩阵乘常数
2*A
# 结果
array([[ 0,  2,  4,  6,  8],
	   [10, 12, 14, 16, 18]])

# C为5行3列的矩阵
C = np.arange(15).reshape(5, 3)
C
# 结果
array([[ 0,  1,  2],
	   [ 3,  4,  5],
	   [ 6,  7,  8],
	   [ 9, 10, 11],
	   [12, 13, 14]])

# 矩阵乘矩阵,真正的矩阵相乘
A.dot(C)
# 结果
array([[ 90, 100, 110],
	   [240, 275, 310]])

# 矩阵中每个对应元素相乘
A*B
# 结果
array([[ 0,  8,  6, 15, 28],
	   [45, 36, 42, 48, 54]])

我们再来看看矩阵的转置:

A.T
# 结果
array([[0, 5],
	   [1, 6],
	   [2, 7],
	   [3, 8],
	   [4, 9]])
 聚合操作

NumPy中有很多对数组的聚合操作方法,我们先来看看一维数组:

# 随机取10个元素的 一维数组
D = np.random.random(10)
D
# 结果
array([ 0.70908471,  0.29268356,  0.69885019,  0.28796429,  0.04189265,
		0.36932107,  0.0641322 ,  0.63989077,  0.02753356,  0.0605743 ])

# 求每个元素的和
np.sum(D)
# 结果
3.1919272951030706

# 求元素的最小值
np.min(D)
# 结果
0.027533561561906672

# 求元素最大值
np.max(D)
# 结果
0.70908470606410545

# 求元素的均值
np.mean(D)
# 结果
0.31919272951030708

# 求元素的标准差
np.std(D)
# 结果
0.26402525382852743

我们再来看看矩阵的聚合操作:

# X为2行3列的矩阵
X = np.arange(6).reshape(2, 3)
X
# 结果
array([[0, 1, 2],
	   [3, 4, 5]])

# 矩阵中所有元素的和
np.sum(X)
# 结果
15

# 矩阵中所有元素的乘积
np.prod(X)
# 结果
0

np.prod(X + 1)
# 结果
720

# 矩阵元素的均值
np.mean(X)
# 结果
2.5

# 矩阵元素的中位数,median可有效避免元素中出现极值,从而导致均值不准的问题
np.median(X)
# 结果
2.5

# 矩阵元素的方差
np.var(X)
# 结果
2.9166666666666665

# np.std(X)
# 结果
1.707825127659933
 索引和排序的相关操作

NumPy提供了一系列对数组索引操作的方法,我们来看一下:

# 随机一维数组
x = np.random.random(10)
x
# 结果
array([ 0.17035458,  0.8968506 ,  0.01007584,  0.45925501,  0.6838149 ,
		0.32393039,  0.53746647,  0.68561243,  0.66195346,  0.32696068])

# x中元素最小值
np.min(x)
# 结果
0.010075835471876626

# x中最小值元素所在的索引位置
np.argmin(x)
# 结果
2

我们再来看看排序:

# 对x进行排序
np.sort(x)
# 结果
array([ 0.01007584,  0.17035458,  0.32393039,  0.32696068,  0.45925501,
		0.53746647,  0.66195346,  0.6838149 ,  0.68561243,  0.8968506 ])

# 获取排序后的索引,返回的数组中的元素是索引
np.argsort(x)
# 结果
array([2, 0, 5, 9, 3, 6, 8, 4, 7, 1])

# 对矩阵排序
X1 = np.random.randint(0, 15, size=(3, 5))
X1
# 结果
array([[ 8,  1,  8, 12,  4],
	   [ 8,  6,  6,  6, 13],
	   [13,  2,  5, 11,  4]])

np.sort(X1)
# 结果
array([[ 1,  4,  8,  8, 12],
	   [ 6,  6,  6,  8, 13],
	   [ 2,  4,  5, 11, 13]])

# 获取排序后的索引
np.argsort(X1)
# 结果
array([[1, 4, 0, 2, 3],
	   [1, 2, 3, 0, 4],
	   [1, 4, 2, 3, 0]])
 NumPy的Fancy Indexing

 

一般情况下我们访问NumPy数组的数据,可以使用索引,甚至可以用步长来取:

x = np.arange(16)
x
# 结果
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15])

# 取从0到6范围内,步长为2的元素
x[0:6:2]
# 结果
array([0, 2, 4])

但是有时候我们需要取数组中没有什么规律的元素,比如元素之间步长不等的,这就需要用到NumPy提供的Fancy Indexing机制来获取了:

# 将我们需要访问的索引生产一个数组,然后将索引数组传入x数组
ind = [3, 5, 8]
x[ind]
# 结果
array([3, 5, 8])

# 矩阵也是同样的,先生成索引矩阵
ind1 = np.array([[0, 1],
				[2, 3]])
x[ind1]
# 结果
array([[0, 1],
	   [2, 3]])

# 将x转换为4行4列的矩阵X
X = x.reshape(4, -1)
X
# 结果
array([[ 0,  1,  2,  3],
	   [ 4,  5,  6,  7],
	   [ 8,  9, 10, 11],
	   [12, 13, 14, 15]])

# 生成希望查询的行和列的索引矩阵,然后传入矩阵X
row = np.array([0, 1, 2])
col = np.array([1, 2, 3])
X[row, col]
# 结果
array([ 1,  6, 11])

# 或者指定前两行
X[:2, col]
# 结果
array([[1, 2, 3],
	   [5, 6, 7]])

除了使用指定索引以外,我们还可以使用布尔数组或者矩阵来使用Fancy Indexing,我们来看一下:

X
# 结果
array([[ 0,  1,  2,  3],
	   [ 4,  5,  6,  7],
	   [ 8,  9, 10, 11],
	   [12, 13, 14, 15]])

# 生成一个布尔数组,True表示感兴趣的索引,False表示不感兴趣的索引
col = [True, False, True, True]
# 然后传入矩阵X,比如我们要获取前三行,第1列,第3列,第4列的元素
X[1:3, col]
# 结果
array([[ 4,  6,  7],
	   [ 8, 10, 11]])

x
# 结果
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15])

# x数组中的元素小于2的有几个
np.sum(x < 2)
# 结果
2

# x数组中的元素大于3小于10的有几个
np.sum((x > 3) & (x < 10))
# 结果
6

# 判断x数组中的所有元素是否满足一个条件,若有一个满足返回True,若都不满足返回False
np.any(x == 0)
# 结果
True

np.any(x < 0)
# 结果
False

# 判断x数组中的所有元素是否满足一个条件,若有所有元素都满足返回True,若有一个元素不满足返回False
np.all(X > 0)
# 结果
False

np.all(X >= 0)
# 结果
True

# 获取x数组中元素小于5的是哪几个元素
x[x < 5]
# 结果
array([0, 1, 2, 3, 4])

# 获取x数组中元素是偶数的是哪几个元素
x[x % 2 == 0]
# 结果
array([ 0,  2,  4,  6,  8, 10, 12, 14])

X
# 结果
array([[ 0,  1,  2,  3],
	   [ 4,  5,  6,  7],
	   [ 8,  9, 10, 11],
	   [12, 13, 14, 15]])

X[:, 3]
# 结果
array([ 3,  7, 11, 15])

X[:, 3] % 3 == 0
# 结果
array([ True, False, False,  True], dtype=bool)

X[X[:, 3] % 3 == 0, :]
# 结果
array([[ 0,  1,  2,  3],
	   [12, 13, 14, 15]])

Matplotlib

在Python中,除了有NumPy这种对数组操作的类库,还有一个类一个在机器学习中使用比较广泛的类库是Matplotlib,这是一个绘制二维图像的类库,我们来看一下:

# 首先导入matplotlib的类库
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt

# 创建数组x,元素从0到10,一共100个元素
x = np.linspace(0, 10, 100)
# 对x数组求sin,获得siny
siny = np.sin(x)

# 使用matplotlib将x数组和y数组中的元素绘制出来
plt.plot(x, y)
plt.show()

 

# 可以同时绘制两条线
cosy = np.cos(x)
plt.plot(x, siny)
plt.plot(x, cosy)
plt.show()

 

# 可以指定某条线的颜色
plt.plot(x, siny)
plt.plot(x, cosy, color="red")
plt.show()

 

# 可以指定线的样式
plt.plot(x, siny)
plt.plot(x, cosy, color="red", linestyle="--")
plt.show()

   

# 可以指定x轴,y轴的区间
plt.plot(x, siny)
plt.plot(x, cosy, color="red", linestyle="--")
plt.xlim(-5, 15)
plt.ylim(0, 1.5)
plt.show()

  

# 另一种指定x轴,y轴区间的方法
plt.plot(x, siny)
plt.plot(x, cosy, color="red", linestyle="--")
plt.axis([-1, 11, -2, 2])
plt.show()

 

# 给x轴和y轴加说明
plt.plot(x, siny)
plt.plot(x, cosy, color="red", linestyle="--")
plt.axis([-1, 11, -2, 2])
plt.xlabel("x axis")
plt.ylabel("y value")
plt.show()

 

# 加图例
plt.plot(x, siny, label="sin(x)")
plt.plot(x, cosy, color="red", linestyle="--", label="cos(x)")
plt.axis([-1, 11, -2, 2])
plt.xlabel("x axis")
plt.ylabel("y value")
plt.legend()
plt.show()

 

# 加标题
plt.plot(x, siny, label="sin(x)")
plt.plot(x, cosy, color="red", linestyle="--", label="cos(x)")
plt.axis([-1, 11, -2, 2])
plt.xlabel("x axis")
plt.ylabel("y value")
plt.legend()
plt.title("Welcome to ML!")
plt.show()

 

以上都是利用matplotlib画折线图,下面来看看如何画散点图:

plt.scatter(x, siny)
plt.show()

  

plt.scatter(x, siny)
plt.scatter(x, cosy)
plt.show()

 

x = np.random.normal(0, 1, 100)
y = np.random.normal(0, 1, 100)
plt.scatter(x, y)
plt.show()

# 设置点的透明度
plt.scatter(x, y, alpha=0.5)
plt.show()

 

基于Scikit Learn的数据探索

Scikit-learn是Python语言中专门针对机器学习应用而发展起来的一款开源框架,其中有一个模块叫Datasets,它提供了机器学习的一些常用的数据集以及产生数据集的方法,比如波士顿房价数据集、乳腺癌数据集、糖尿病数据集、手写字体数据集、鸢尾花数据集等等。这一小节我们就通过Scikit Learn的Datasets来初步对机器学习的数据进行探索。

我们使用NumPy和Matplotlib对Scikit Learn Datasets中的鸢尾花这个数据集进行探索:

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
# 我们只导入Scikit Learn中的datasets模块
from sklearn import datasets

# 加载鸢尾花数据集,获取到的iris的数据结构是一个字典
iris = datasets.load_iris()
# 看看字典的key都有什么
iris.keys()
# 结果
dict_keys(['data', 'target', 'target_names', 'DESCR', 'feature_names'])

从上面的示例可以看到鸢尾花这个字典一共包含五种信息,我们逐一来看看这五种信息:

# 先看一下DESCR信息,该信息解释了鸢尾花这个数据集
print(iris.DESCR)
# 结果
Iris Plants Database
====================

Notes
-----
Data Set Characteristics:
	:Number of Instances: 150 (50 in each of three classes)
	:Number of Attributes: 4 numeric, predictive attributes and the class
	:Attribute Information:
		- sepal length in cm
		- sepal width in cm
		- petal length in cm
		- petal width in cm
		- class:
				- Iris-Setosa
				- Iris-Versicolour
				- Iris-Virginica
	:Summary Statistics:

	============== ==== ==== ======= ===== ====================
					Min  Max   Mean    SD   Class Correlation
	============== ==== ==== ======= ===== ====================
	sepal length:   4.3  7.9   5.84   0.83    0.7826
	sepal width:    2.0  4.4   3.05   0.43   -0.4194
	petal length:   1.0  6.9   3.76   1.76    0.9490  (high!)
	petal width:    0.1  2.5   1.20  0.76     0.9565  (high!)
	============== ==== ==== ======= ===== ====================
.....
.....

DESCR详细的描述了鸢尾花这个数据集一共有150组数据,每组数据有4个特征,分别是萼片的长度和厚度、花瓣的长度和厚度,还有3种鸢尾花的类别以及这些数据的统计信息和详细的解释说明。

# 再来看看data
iris.data
# 结果
array([[ 5.1,  3.5,  1.4,  0.2],
	   [ 4.9,  3. ,  1.4,  0.2],
	   [ 4.7,  3.2,  1.3,  0.2],
	   [ 4.6,  3.1,  1.5,  0.2],
	   [ 5. ,  3.6,  1.4,  0.2],
	   [ 5.4,  3.9,  1.7,  0.4],
	   [ 4.6,  3.4,  1.4,  0.3],
	   [ 5. ,  3.4,  1.5,  0.2],
	   [ 4.4,  2.9,  1.4,  0.2],
	   [ 4.9,  3.1,  1.5,  0.1],
	   [ 5.4,  3.7,  1.5,  0.2],
	   [ 4.8,  3.4,  1.6,  0.2],
	   ...
	   ...
	   [ 5.9,  3. ,  5.1,  1.8]])

# 看看data这个数组的行列情况
iris.data.shape
# 结果
(150, 4)

可以看到data中的数据就是萼片长度、厚度,花瓣长度、厚度的值。是一个150行,4列的矩阵。

# feature_names的值就是4个特征的说明
iris.feature_names
# 结果
['sepal length (cm)',
 'sepal width (cm)',
 'petal length (cm)',
 'petal width (cm)']

 # target描述了每一行鸢尾花的数据是哪个类别的
 iris.target
 # 结果
 array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	   0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	   1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
	   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
	   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])

# target是一个一维数组
iris.target.shape
# 结果
(150,)

# target_names就是类别名称
iris.target_names
# 结果
array(['setosa', 'versicolor', 'virginica'],
	  dtype='            
关注
打赏
1663816507
查看更多评论
0.1755s