前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >AI入门之数据处理(Numpy指南)

AI入门之数据处理(Numpy指南)

作者头像
PhoenixZheng
发布2019-12-04 12:34:50
1K0
发布2019-12-04 12:34:50
举报

python中的数据操作基本都用numpy来做,在做深度学习的过程一定也绕不过numpy。这篇分几个部分介绍numpy · numpy array 的基本属性,包括 shape, size, dim, data type · 通过 index 获取 numpy array 的数据 · 分割 numpy array,获取 sub array · 变换 numpy array 的维度 · 合并 numpy array,合并多个数组

numpy array 属性

numpy array 有几个基本属性,分别是

shape, size, dim, data type

这里通过几个不同维度的数组来了解这几个属性。首先我们先随机生成几个不同维度的numpy array

代码语言:javascript
复制
import numpy as np
np.random.seed(0)  # seed for reproducibility

x1 = np.random.randint(10, size=6)  # One-dimensional array
x2 = np.random.randint(10, size=(3, 4))  # Two-dimensional array
x3 = np.random.randint(10, size=(3, 4, 5))  # Three-dimensional array

数组的三个属性分别表示的含义 ndim: 维度数量 shape: 每个维度的数量 size: 数组的总数量

代码语言:javascript
复制
print("x3 ndim: ", x3.ndim)
print("x3 shape:", x3.shape)
print("x3 size: ", x3.size)

得到 x3 ndim: 3 x3 shape: (3, 4, 5) x3 size: 60

另一个比较有用的属性是 dtype,代表数据的类型

代码语言:javascript
复制
print("dtype:", x3.dtype)

dtype: int64

数组下标

numpy的数组下标和其他语言的下标语法差不多,取对应index的值可以用过中括号来获取。假设 array([5, 0, 3, 3, 7, 9]) 为 x1

代码语言:javascript
复制
x1[0]

得到 5

numpy提供了一种方便的逆序index,用负值来获取从后往前的Index的数据

代码语言:javascript
复制
x1[-1]

得到 9. 需要注意逆序的起始位置不是0(这个很明显)

对于二维数组的情况,假设我们有个 x2,

代码语言:javascript
复制
array([[3, 5, 2, 4],
       [7, 6, 8, 8],
       [1, 6, 7, 7]])

[0, 0] 位置的值是3,通过

代码语言:javascript
复制
x2[0, 0]

可以获得。

代码语言:javascript
复制
x2[2, -1]

得到 7

修改数组的值也可以通过下标来操作

代码语言:javascript
复制
x2[0, 0] = 2
print(x2)

得到

代码语言:javascript
复制
array([[12,  5,  2,  4],
       [ 7,  6,  8,  8],
       [ 1,  6,  7,  7]])

但numpy的数据类型在初始化的时候就确定了,意味着当你想给它赋值不同的数据类型,numpy会自动静默转换。比如我们想把一个浮点类型赋值给 int 类型的 numpy

代码语言:javascript
复制
x1[0] = 3.14159
print(x1)

此时的 x1是

代码语言:javascript
复制
array([3, 0, 3, 3, 7, 9])
切割array,获取子串

中括号指定下标的方式可以获取某个下标对应的值,获取子串也可以通过这种方式,通过指定[起始点:终点:步进]可以得到对应子串,(:) 冒号符是用来分割起始点和终点和步进的。下面是具体的语法

代码语言:javascript
复制
x[start:stop:step]

这三个的默认值是 start = 0 stop = 维度对应的size step = 1

一维数组子串

先定义一个一维数组

代码语言:javascript
复制
x = np.arange(10)

现在x是

代码语言:javascript
复制
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

想获取前5个元素

代码语言:javascript
复制
x[:5] -> array([0, 1, 2, 3, 4])

获取从5到最后的元素

代码语言:javascript
复制
x[5:] -> array([5, 6, 7, 8, 9])

获取index 4 到 7 的元素,不包含[7]这个元素

代码语言:javascript
复制
x[4:7] -> array([4, 5, 6])

按步进为2获取元素

代码语言:javascript
复制
x[::2] -> array([0, 2, 4, 6, 8])

步进2,获取奇数元素

代码语言:javascript
复制
x[1::2] -> array([1, 3, 5, 7, 9])

除此之外,Numpy的子串操作还可以进行逆序操作,如从后向前步进n步取子串

代码语言:javascript
复制
x[::-1] -> array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])

这是取逆序

代码语言:javascript
复制
x[5::-2] -> array([5, 3, 1])
二维数组子串操作

二维数组的子串操作类似,下面举几个例子 首先定义个二维数组

代码语言:javascript
复制
x2 -> array([[12,  5,  2,  4],
       [ 7,  6,  8,  8],
       [ 1,  6,  7,  7]])

取第一维的前两个维度,每个维度取前三个元素做子串

代码语言:javascript
复制
x2[:2, :3] -> array([[12,  5,  2],
       [ 7,  6,  8]])

取第一维度前三个,每个维度步进2取子串

代码语言:javascript
复制
x2[:3, ::2] -> array([[12,  2],
       [ 7,  8],
       [ 1,  7]])

二维数组同样也可以反转

代码语言:javascript
复制
x2[::-1, ::-1] -> array([[ 7,  7,  6,  1],
       [ 8,  8,  6,  7],
       [ 4,  2,  5, 12]])
修改子串

通过子串操作拿到的子串实际上元素还处于原始数据维度中,如果对子串的数据进行修改,同样也会影响到原来的数据

代码语言:javascript
复制
x2 ->  [[12  5  2  4]
 [ 7  6  8  8]
 [ 1  6  7  7]]

现在取个子串

代码语言:javascript
复制
x2_sub = x2[:2, :2] -> [[12  5]
 [ 7  6]]

然后修改子串的值

代码语言:javascript
复制
x2_sub[0, 0] = 99
x2_sub -> [[99  5]
 [ 7  6]]

此时原始数组的数据也会发生改变

代码语言:javascript
复制
x2 -> [[99  5  2  4]
 [ 7  6  8  8]
 [ 1  6  7  7]]

那么如何在不影响原始数据的情况下生成一个新的子串来修改呢

创建数组副本

我们先创建一个原始二维数据

代码语言:javascript
复制
x2 ->  [[99  5  2  4]
 [ 7  6  8  8]
 [ 1  6  7  7]]

现在还是取 [:2, :2] 作为子串,但这里用 copy 的方式生成一个独立副本

代码语言:javascript
复制
x2_sub_copy = x2[:2, :2].copy()
x2_sub_copy -> [[99  5]
 [ 7  6]]

然后对它进行修改,

代码语言:javascript
复制
x2_sub_copy[0, 0] = 42
x2_sub_copy ->[[42  5]
 [ 7  6]]

现在查看原始数据,

代码语言:javascript
复制
x2 -> [[99  5  2  4]
 [ 7  6  8  8]
 [ 1  6  7  7]]

x2的[0, 0]并没有发生改变,还是99

维度变换

维度变换是 numpy 数组中用的最多的一个操作,经常用来对输入数据进行维度转换,比如我们有一个三通道的5x5图片,用numpy表示是

代码语言:javascript
复制
image.shape = (5, 5, 3)

如果想把三个通道合并为一个,可以通过reshape进行操作

代码语言:javascript
复制
image.reshape((15, 5, 1))

结果会把三通道的数据压缩成单通道。

再一个例子,先定义个3x3的1~9数组

代码语言:javascript
复制
grid = np.arange(1, 10)
grid -> array([1, 2, 3, 4, 5, 6, 7, 8, 9])

grid = grid.reshape((3, 3))
grid -> [[1 2 3]
 [4 5 6]
 [7 8 9]]

定义的时候数组长度也就是size,必须能够塞进所定义的维度里也就是3x3, 不然reshape的时候会失败。

另一种转换维度的方法是用上面切割子串的 (:) 操作符, 比如我们有一个一维数组,想转换成二维数组,

代码语言:javascript
复制
x = np.array([1,2,3])

numpy提供了个关键词 newaxis,可以在进行子串切割的时候指定新增维度,如使用reshape可以这么写

代码语言:javascript
复制
x = x.reshape((1,3))
x.shape -> (1, 3)

使用 newaxis 可以这么写,也有一样的效果

代码语言:javascript
复制
x = x[np.newaxis, :]
x.shape -> (1, 3)
数组拼接

数组拼接也是常见操作之一,一般有两种情况,同样维度的数组合并,和维度不一样的数组合并。对于这两种情况,有两种不同的合并操作 · np.concatenate · np.vstack , np.hstack vstack和hstack分别表示 vertical和 horizontal,在两个不同维度上合并。

合并相同维度数组
代码语言:javascript
复制
grid = np.arange(0, 6)
grid = grid.reshape((2,3))
grid -> array([[0, 1, 2],
       [3, 4, 5]])

用concatenate合并

代码语言:javascript
复制
grid = np.concatenate([grid,grid])
grid -> array([[0, 1, 2],
       [3, 4, 5],
       [0, 1, 2],
       [3, 4, 5]])
       
grid.shape = (4,3)
合并不同维度数组

合并一个一维数组和一个二维数组,

代码语言:javascript
复制
x = np.array([1, 2, 3])
grid = np.array([[9, 8, 7],
                 [6, 5, 4]])

合并不同维度数组的前提是在长度一样的维度上进行合并,上面这个需要在 vstack上合并(有点别扭,verticale是垂直方向,跟数组的书写方向习惯不一样)

代码语言:javascript
复制
merge = np.vstack([x, grid])
merge -> array([[1, 2, 3],
       [9, 8, 7],
       [6, 5, 4]])

在hstack方向合并

代码语言:javascript
复制
y = np.array([[99],[99]])
merge = np.hstack([grid, y])
merge -> array([[ 9,  8,  7, 99],
       [ 6,  5,  4, 99]])
拆分数组

既然能合并数组,那么数组也可以拆分,以一个一维数组为例

代码语言:javascript
复制
 x = np.arange(0,7)
 x -> array([0, 1, 2, 3, 4, 5, 6])

在index为3和5进行拆分

代码语言:javascript
复制
 x1,x2,x3 = np.split(x, [3,5])
 print(x1,x2,x3)

会得到

代码语言:javascript
复制
>>> x1
array([0, 1, 2])
>>> x2
array([3, 4])
>>> x3
array([5, 6])

同样也可以对多维数组在不同的维度上拆分,

代码语言:javascript
复制
grid = np.arange(16).reshape((4, 4))
grid -> array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])

用 vsplit 拆分

代码语言:javascript
复制
upper, lower = np.vsplit(grid, [2])
upper -> [[0 1 2 3]
 [4 5 6 7]]
 
lower -> [[ 8  9 10 11]
 [12 13 14 15]]

用 hstack 进行拆分

代码语言:javascript
复制
left, right = np.hsplit(grid, [2])
left -> [[ 0  1]
 [ 4  5]
 [ 8  9]
 [12 13]]
 
right -> [[ 2  3]
 [ 6  7]
 [10 11]
 [14 15]]
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Android每日一讲 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • numpy array 属性
  • 数组下标
  • 切割array,获取子串
    • 一维数组子串
      • 二维数组子串操作
        • 修改子串
        • 创建数组副本
        • 维度变换
        • 数组拼接
          • 合并相同维度数组
            • 合并不同维度数组
            • 拆分数组
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档