numpy小结

本文介绍了NumPy的基础知识,包括如何将列表和元组转换为数组,创建数值数组的方法如arange和linspace,以及Ndarray对象的属性和操作。还讨论了数组的切片、多维下标、转置、随机数生成以及矩阵的乘法和逆矩阵计算。重点强调了np.array()和np.asarray()的区别以及矩阵乘法规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

NumPy是Numerical Python的缩写。numerical :relating to numbers; expressed in numbers

初识numpy——列表/元组转为数组

import numpy as np

list_demo = [1, 2, 3, 4]
a = np.array(list_demo)
print(a)

tuple_demo = ('1', '2', '3', '4')
b = np.asarray(tuple_demo)
print(b)

list_tuple = [('胡桃', '可莉', '纳西妲'), ('7.15', '7.27', '10.27')]
c = np.asarray(list_tuple)
print(c)

输出

[1 2 3 4]
['1' '2' '3' '4']
[['胡桃' '可莉' '纳西妲']
 ['7.15' '7.27' '10.27']]

第三个的输出:将列表转换为NumPy数组时,NumPy会将列表中的元组视为一个整体,并将该整体作为数组的一个元素。

初识numpy——创建数值数组

array1 = np.arange(0, 10, 2, int)
print(array1)

array2 = np.arange(0, 1, 0.2, float)
print(array2)

array3 = np.linspace(0, 1, num=5, endpoint=False, retstep=True)
print(array3)

输出

[0 2 4 6 8]
[0.  0.2 0.4 0.6 0.8]
(array([0. , 0.2, 0.4, 0.6, 0.8]), 0.2)

函数arange用于创建一个等差数列的一维数组,参数包括起始值、结束值(不包含在数组中)、步长和数据类型,其中起始值默认0,步长默认为1,数据类型参数可省略。

函数linspace用于在一定范围内生成等间隔的数值序列,其中参数num表示生成数组的元素个数,endpoint表示是否包含结束点,retstep表示是否返回步长。

其他方法:

ones(shape,dtype):指定数组的形状,生成一个包含全1元素的数组。数据类型为dtype,可省略。

eye(N):指定方阵的大小N,生成一个单位矩阵。

zeros(shape,dtype):指定数组的形状,生成一个包含全0元素的数组。数据类型为dtype,可省略。

注:dtype可省略,shape可以只有一个,默认为行数。

比如

print(np.eye(2))
print(np.ones((3, 2)))
print(np.zeros((3, 2)))

输出

[[1. 0.]
 [0. 1.]]
[[1. 1.]
 [1. 1.]
 [1. 1.]]
[[0. 0.]
 [0. 0.]
 [0. 0.]]

注意到这里的ones与zeros都是用的((a,b)),不要只打一个括号。

事实上有eye(N, M=None, k=0, dtype=float),这个比较复杂,单独说。它创建一个大小为(N, M)的二维数组,其中“对角线”上的元素为1,其他元素为0。偏移量k表示“对角线”向右的偏移量。比如:

e = np.eye(5, 6, -1, int)
print(e)

输出

[[0 0 0 0 0 0]
 [1 0 0 0 0 0]
 [0 1 0 0 0 0]
 [0 0 1 0 0 0]
 [0 0 0 1 0 0]]

-1表示向左偏移1。

Ndarray对象

Ndarray对象是NumPy库中的多维数组对象,集合了N个类型相同的数据,shape与dtype分别反应了数组维度与数据类型情况。创建Ndarray可以用array()方法,上文已经使用过了。原来是嵌套格式的序列会被转换成多维数组。

对Ndarray对象使用.ndim.dtype可以获取数组维度数与数据类型,用.shape.size可以获取大小(行,列)与元素数量,用. itemsize可以获取元素的字节数。

从外向里依次“剥皮”,也就是去掉[],就分别是数组的第1,2,3,......维度,对应的是shape[0],shape[1],shape[2]…。而shape[n]的值的计算方法是:去掉外面的中括号之后,内部的最大的中括号有几个。

比如下文中去掉最外面的[]后,得到的单位体的个数表示第0个维度(axis=0)的大小,剩下的是[[1, 2, 3, 4],[1, 2, 3, 4],[1, 2, 3, 4]],只有一个括号,所以shape[0]为1。

接着去掉[]后,剩下[1, 2, 3, 4],[1, 2, 3, 4],[1, 2, 3, 4],有三个括号,所以shape[1]为3。

然后内部元素是4个,shape[2]为4。

list_demo = [[[1, 2, 3, 4],[1, 2, 3, 4],[1, 2, 3, 4]]]
a = np.array(list_demo)
print(a.ndim)
print(a.dtype)
print(a.shape)

输出

3
int32
(1, 3, 4)

上文提及了参数axis,该参数在sum求和里比较重要:

print(a.sum(axis=0))
print(a.sum(axis=1))
print(a.sum(axis=2))

输出

[[1 2 3 4]
 [1 2 3 4]
 [1 2 3 4]]
[[ 3  6  9 12]]
[[10 10 10]]

其中axis=0说明去掉一个[],这时候shape[0]=1,此时就是一个数组,sum运算后还是该数组。axis=1说明去掉两层[],这时候shape[1]=3,此时就是三个数组[1,2,3,4],将这三个数组相加得到sum。axis=2说明去掉三层[],这时候shape[2]=4,将1,2,3,4相加就是10。

现在应该大致明白了计算方法,下面来谈谈这个输出里面的[]个数如何确定。因为shape[0]=1的时候不方便观察和(因为axis==0时没有相加过程),所以这里取shape[0]=2的一个数组,比如shape=(2,4,3)。比如

arr = [[[5, 0, 3], [3, 7, 3], [5, 2, 4], [7, 6, 8]], [[8, 1, 6], [7, 7, 8], [1, 5, 8], [4, 3, 0]]]
arr = np.asarray(arr)
print(arr, end='\n\n')
print(arr.sum(axis=0), end='\n\n')
print(arr.sum(axis=1), end='\n\n')
print(arr.sum(axis=2), end='\n\n')

输出

[[[5 0 3]
  [3 7 3]
  [5 2 4]
  [7 6 8]]

 [[8 1 6]
  [7 7 8]
  [1 5 8]
  [4 3 0]]]

[[13  1  9]
 [10 14 11]
 [ 6  7 12]
 [11  9  8]]

[[20 15 18]
 [20 16 22]]

[[ 8 13 11 21]
 [15 22 14  7]]

axis=0时,去掉最外层的[],此时两个[[…]]的数组相加。

axis=1时,去掉中间的[],此时[[[…]]]变为[[…]](但这与axis=0的时候的[[…]]是不一样的,因为去掉的那个[]不一样)。

axis-2时,去掉最内层的[],此时是数字元素之间的相加了。

显式转换

arr = [[0.0, 1.0, 1.1], [-1.5, 1.5, -1.6]]
arr = np.array(arr)
print(arr)
print(arr.astype(np.int32))
输出
[[ 0.   1.   1.1]
 [-1.5  1.5 -1.6]]
[[ 0  1  1]
 [-1  1 -1]]

这里类型转化的时候的小数点是被截断的。

数组的操作

NumPy数组与普通的列表的操作差不多,这里仅说明一些比较重要的。

使用切片修改原数据

arr = [1, 2, 3, 4, 5]
arr = np.array(arr)
arr_slice = arr[2:4]  # 截取的是元素3,4
arr_slice[1] = 44  # 把截取的元素中的第二个(这里是4)改为44
print(arr)
输出[ 1  2  3 44  5]

如果想要arr_slice里的元素全部更改,可以用arr_slice[:]=44,不要忘记:了。

多维下标索引

和C里面的基本一样,比如

arr = [[1, 2, 3], [4, 5, 6]]
arr = np.array(arr)
print(arr[0], end='\t')
print(arr[0][1], end='\t')
print(arr[0, 1])
输出[1 2 3]	2	2

但是,如果需要的是某一部分的元素,难度比较大,需要索引与切片结合。比如

print(arr[:1, 2:])
输出[[3]]

这里输出的是行为:1,列为2:的元素。切片:1表示结束位置为1且不包括1,2:表示起始位置为2且包括2。又如

print(arr[1:, 1:2])
print(arr[:, 1:])

输出

[[5]]
[[2 3]
 [5 6]]

亦可对切片赋值:

arr[:, 1:] = 0
print(arr)
输出
[[1 0 0]
[4 0 0]]

转置

arr = [[1, 2, 3], [4, 5, 6]]
arr = np.array(arr)
print(arr.T)
print(arr.transpose())

输出均为

[[1 4]
 [2 5]
 [3 6]]
arr = np.arange(32).reshape((2, 4, 4))
print(arr)
print(arr.shape)
print(arr.transpose(1, 0, 2))
print(arr.transpose(1, 0, 2).shape)

输出

[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]
  [12 13 14 15]]

 [[16 17 18 19]
  [20 21 22 23]
  [24 25 26 27]
  [28 29 30 31]]]
(2, 4, 4)
[[[ 0  1  2  3]
  [16 17 18 19]]

 [[ 4  5  6  7]
  [20 21 22 23]]

 [[ 8  9 10 11]
  [24 25 26 27]]

 [[12 13 14 15]
  [28 29 30 31]]]
(4, 2, 4)

这里(1,0,2)表示第一个维度(0)与第二个维度(1)交换,第三个维度(2)不变。也就是shape从(2,4,4)变为(4,2,4)。之前axis=0的维度里0123后面的是16171819,所以现在axis=1的维度里0123后面的是16171819,以此类推。

生成随机数组

print(np.random.randn(3,4))
print(np.random.choice([10,20,30]))
print(np.random.beta(1,5,10))

np.random.randn函数生成的是服从标准正态分布N~(0,1)的随机数。

np.random.choice从给的的数组里随机选一个元素。

np.random.beta是一个使用beta分布生成随机数的函数。前两个参数是beta分布的形状参数,第三个参数表示生成的随机数的数量。

Beta分布是一种连续型概率密度分布,表示为x~Beta(a,b),由两个参数决定,称为形状参数。由于其定义域为(0,1),一般被用于建模伯努利试验事件成功的概率的概率分布:为了测试系统的成功概率,我们做n次试验,统计成功的次数k,于是很直观地就可以计算出。然而由于系统成功的概率是未知的,这个公式计算出的只是系统成功概率的最佳估计。也就是说实际上也可能为其它的值,只是为其它的值的概率较小。因此我们并不能完全确定硬币出现正面的概率就是该值,所以也是一个随机变量,它符合Beta分布,其取值范围为01

print(np.random.rand(2,4))
print(np.random.rand())
print(np.random.randint(1,10,3))

np.random.rand生成0~1的随机数

np.random.randint(1,10,3)生成1~10之间的长度为3的随机整数数组

np.array()np.asarray()的区别

import numpy as np

arr1 = np.ones((3, 3))
arr2 = np.array(arr1)
arr3 = np.asarray(arr1)
arr1[1] = 2
print('arr1:\n', arr1)
print('arr2:\n', arr2)
print('arr3:\n', arr3)

输出

arr1:
 [[1. 1. 1.]
 [2. 2. 2.]
 [1. 1. 1.]]
arr2:
 [[1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]]
arr3:
 [[1. 1. 1.]
 [2. 2. 2.]
 [1. 1. 1.]]

发现arr3被arr1改了,这是因为:

np.array(默认情况下)将会copy该对象,而np.asarray 除非必要,否则不会copy该对象。(必要的意思是数据源是ndarray类型时,不会copy)。也就是说array和asarray都可以将结构数据转化为ndarray,但是主要区别就是当数据源是ndarray时,array仍然会copy出一个副本,占用新的内存,但asarray不会。

矩阵的乘法——星乘*与点乘dot

1.星乘*

①同型矩阵(哈达玛积)。对应位置的元素相乘

,如:

 

②不同型,但两个矩阵行数相等,其中一个矩阵列数为1。单列矩阵的列与另一个矩阵的列分别相乘:

 

2.点乘dot

就是线代里的矩阵乘法

比如,

import numpy as np

a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
c = np.array([[1], [2]])
print(a * b, '\n')
print(c * b, '\n')
print(b * c, '\n')
print(np.dot(a, b))

输出

[[ 5 12]
 [21 32]] 

[[ 5  6]
 [14 16]] 

[[ 5  6]
 [14 16]] 

[[19 22]
 [43 50]]

矩阵的逆矩阵:

与线代的定义一样,,比如:

import numpy as np

a = np.array([[1, 2], [3, 4]])
a_inv = np.linalg.inv(a)
print(a_inv)
print(np.dot(a, a_inv))

 输出

[[-2.   1. ]
 [ 1.5 -0.5]]
[[1.0000000e+00 0.0000000e+00]
 [8.8817842e-16 1.0000000e+00]]

inv是inverse的缩写:相反的,倒转的;颠倒的,逆的

linalg是numpy库中的线性代数模块,可以用于进行矩阵和向量的运算,linalg是linear algebra(线性代数)的缩写。

这里有烦人的浮点数,可以这样修改代码:

a_dot_a_inv = np.dot(a, a_inv)
a_dot_a_inv = np.round(a_dot_a_inv).astype(int)  # 将a_dot_a_inv中的元素四舍五入为整数
print(a_dot_a_inv)

输出

[[1 0]
 [0 1]]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值