机器学习入门 3-5 Numpy数组(和矩阵)的基本操作

2022-05-25 13:59:42 浏览数 (1)

首先导入 numpy 包

代码语言:javascript复制
import numpy as np

通过 arange 函数创建一个一维数组 x

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

'''
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
'''

使用 reshape 方法将一维数组转换为 3x5 的二维数组 X

代码语言:javascript复制
X = np.arange(15).reshape(3, 5)
print(X)

'''
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])
'''

基本属性

ndim 属性查看数组的维度

代码语言:javascript复制
print(x.ndim) # 1 
print(X.ndim) # 2

shape 属性查看数组的维度,返回值是一个元组,元组中对应位置的值为数组中对应维度的元素个数。

代码语言:javascript复制
print(x.shape) # (10,)
print(X.shape) # (3, 5)

size 属性查看数组中的元素个数

代码语言:javascript复制
print(x.size) # 10
print(X.size) # 15 (3 x 5)

numpy.array 的数据访问

代码语言:javascript复制
print(x)

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

'''
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])
'''
代码语言:javascript复制
# [][]同样可以访问,但是 numpy 不建议这样写
print(X[0][0]) # 0
# 推荐写法如下,与 X[(0,0)] 等价
print(X[0, 0]) # 0

一维数组的切片操作可以参考 Python 中对列表的切片操作

代码语言:javascript复制
print(x)

'''
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
'''

print(x[0:5])

'''
array([0, 1, 2, 3, 4])
'''

print(x[:5])

'''
array([0, 1, 2, 3, 4])
'''

print(x[5:])

'''
array([5, 6, 7, 8, 9])
'''

print(x[::2])

'''
array([0, 2, 4, 6, 8])
'''

print(x[::-1])

'''
array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
'''

numpy 支持二维数组的切片操作,甚至更高维度

代码语言:javascript复制
print(X)

'''
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])
'''

# 输出二维数组的前两行前三列
print(X[:2, :3])

'''
array([[0, 1, 2],
       [5, 6, 7]])
'''


代码语言:javascript复制
# 与X[:2, :3]不等价
print(X[:2][:3])

'''
array([[0, 1, 2, 3, 4],
      [5, 6, 7, 8, 9]])
'''

X[:2][:3]X[:2, :3] 不等价,如果是 X[:2][:3],程序会先执行 X[:2],也就是输出 X 的前两行元素,X[:2] 返回的是一个新的二维数组 new_X,而接下来相当于执行 new_X[:3],输出 new_X 的前三行。

  • X[:2][:3] 等价于 new_X = X[:2]new_X[:3]

这也是为什么推荐使用 X[0, 0] 而不是 X[0][0] 的原因。

子数组与原数组

在 Python 中对列表进行切片实际上创建了新的列表,而 Numpy 优先考虑效率,所以在 numpy 中,如果修改了子数组,那么相应的原数组也会发生改变,反之亦然。(切片的子数组通过引用与原数组建立联系,而不是创建新的数组)

代码语言:javascript复制
# 通过切片生成子数组
subX = X[:2, :3]
print(subX)

'''
array([[0, 1, 2],
       [5, 6, 7]])
'''

# 修改子数组
subX[0, 0] = 100
print(subX)

'''
array([[100,   1,   2],
       [  5,   6,   7]])
'''

# 原数组也发生了改变
print(X)

'''
array([[100,   1,   2,   3,   4],
       [  5,   6,   7,   8,   9],
       [ 10,  11,  12,  13,  14]])
'''

如果我们需要创建一个与原数组不相关的子数组呢?可以使用 .copy() 方法。

代码语言:javascript复制
subX = X[:2, :3].copy()
print(subX)

'''
array([[0, 1, 2],
       [5, 6, 7]])
'''

# 此时再修改子数组
subX[0, 0] = 100
print(subX)

'''
array([[100,   1,   2],
       [  5,   6,   7]])
'''

# 原数组不会发生变化了
print(X)

'''
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])
'''

Reshape

通过 reshape 函数修改数组的形状,需要注意调用 reshape 方法是没有改变原数组自身的。

代码语言:javascript复制
print(x.shape) # (10,)
print(x.ndim) # 1
print(x.reshape(2, 5))

'''
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])
'''

# 没有改变原数组
print(x)

'''
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
'''

# 可以通过使用修改后的数组,可以将其赋值给新变量
A = x.reshape(2, 5)
B = x.reshape(1, 10)

print(B)

'''
array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])
'''
print(B.ndim) # 2
print(B.shape) # (1, 10)

如果只想指定某个维度,其余维度由程序自动推断,可以使用 -1

代码语言:javascript复制
print(x.reshape(10, -1))

'''
array([[0],
       [1],
       [2],
       [3],
       [4],
       [5],
       [6],
       [7],
       [8],
       [9]])
'''

print(x.reshape(2, -1))

'''
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])
'''

# 如果指定3行,其余维度不是整数,会抛出异常
print(x.reshape(3, -1))

'''
ValueError: cannot reshape array of size 10 into shape (3,newaxis)
'''

References:

  1. Python3入门机器学习 经典算法与应用: https://coding.imooc.com/class/chapter/169.html#Anchor

0 人点赞