[自然语言处理基础]NumPy基本操作

什么是NumPy

NumPy 是 Python 中科学计算的基本包。它是一个 Python 库,提供多维数组对象、各种派生对象(如掩码数组和矩阵)以及用于对数组进行快速操作的各种例程,包括数学、逻辑、形状操作、排序、选择、I/O、离散傅里叶变换、基本线性代数、基本统计运算、随机模拟等等。

  • NumPy 数组在创建时具有固定大小,这与 Python 列表(可以动态增长)不同。更改数组的大小ndarray将创建新数组并删除原始数组。

  • NumPy 数组中的所有元素都必须是同一数据类型,因此在内存中的大小也相同。例外情况是:可以有(Python,包括 NumPy)对象数组,从而允许不同大小元素的数组。

  • NumPy 数组便于对大量数据进行高级数学和其他类型的运算。通常,与使用 Python 的内置序列相比,此类运算执行起来更高效,代码也更少。

import numpy as np #导入numpy库 

NumPy的创建

#创建ndarray数组
arr = np.array([1,2,3,4,5])
arr
array([1, 2, 3, 4, 5])
#创建ndarray数组float类型
arr= np.array([1,2,3,4,5],float)
arr
array([1., 2., 3., 4., 5.])
#创建多维数组
a=  np.array([(1,2,3),(4,5,6),(7,8,9)])
a
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])
#创建全0数组 
a1=np.zeros((2,3),dtype=np.float32)
a1
array([[0., 0., 0.],
       [0., 0., 0.]], dtype=float32)
#创建一个全是1的数组
a=np.ones((3,3))
a
array([[1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.]])
#创建一个全是3的数组
a3 = np.ones((3, 3)) * 3
a3
array([[3., 3., 3.],
       [3., 3., 3.],
       [3., 3., 3.]])
#创建一个等差数列,起始值为1,终止值为10,公差为0.5
a4 = np.arange(1, 10, 0.5)
a4
array([1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5, 5. , 5.5, 6. , 6.5, 7. ,
       7.5, 8. , 8.5, 9. , 9.5])
#创建单位矩阵(主对角线上的元素均为1)
a5 = np.eye(3)
a5 #one-hot编码
array([[1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])
#⽣成指定⻓度,在 【0,1) 之间平均分布的随机数组
a6 = np.random.random(5)    #模型运算参数的初始值
a6
array([0.87868421, 0.75007704, 0.11428473, 0.77664292, 0.62741277])
#⽣成指定⻓度,符合正态分布的随机数组,指定其均值为 0,标准差为 0.1 
a7 = np.random.normal(0,0.1,5)
a7
array([-0.02658837,  0.01492367, -0.0489801 , -0.10652186,  0.07516978])

NumPy数组的访问

和 list 的访问形式基本⼀致,⽀持切⽚操作,我们可以切⽚每⼀个维度,索引每⼀个维度

a8 = np.array([(1,2,3),(4,5,6),(7,8,9)])
print(a8[0]) #取第一行
print()
print(a8[:,1]) #取第二列,一位数组
print()
print(a8[:,:1]) #取第一列,二维数组结构
[1 2 3]

[2 5 8]

[[1]
 [4]
 [7]]

Numpy数组的遍历

#一维数组遍历
a9 = np.array([1,2,3,4,5])
for i in a9:
    print(i)
1
2
3
4
5
#多维数组遍历
a10 = np.array([(1,2,3),(4,5,6),(7,8,9)])
for i,j,k in a10:
    print(i*j*k) #计算每一行的乘积
print()
for i,j,k in a10:
    print(i,j,k)
6
120
504

1 2 3
4 5 6
7 8 9

NumPy数组的常用属性

⽐较常⽤的属性有:
ndarray.ndim : 数组的维度(数组轴的个数),等于秩
ndarray.shape : 数组的⼤⼩。为⼀个表⽰数组在每个维度上⼤⼩的整数元组。例如⼆维数组中,表⽰数组的ʼʼ ⾏数ʼʼ 和ʼʼ 列数ˮ
ndarray.size : 数组元素的总个数,等于 shape 属性中元组元素的乘积
ndarray.dtype : 表⽰数组中元素类型的对象

a11 = np.array([(1,2,3),(4,5,6),(7,8,9)])
print('ndim:',a11.ndim) #数组的维度
print('shape:',a11.shape) #数组的形状
print('size:',a11.size) #数组的元素个数
print('dtype:',a11.dtype) #数组的元素类型
ndim: 2
shape: (3, 3)
size: 9
dtype: int64

NumPy数组的基本操作

#in 检测数值是否在数组中
a12 = np.array([(1,2),(3,4)])
print(1 in a12)
print(5 in a12)
True
False
a13 = np.array([(1,2,3),(4,5,6)])
print((1,2,3) in a13)
print((2,3) in a13)  #比较的shape要一样,否则会广播报错
True
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[78], line 3
      1 a13 = np.array([(1,2,3),(4,5,6)])
      2 print((1,2,3) in a13)
----> 3 print((2,3) in a13)

ValueError: operands could not be broadcast together with shapes (2,3) (2,)
# reshape()函数改变数组的形状,但是元素个数要一致
a14 = np.arange(1,13)
print(a14)
print(a14.shape)
a14 = a14.reshape(3,4)  #维度大小的乘积 == 数组的元素个数
print(a14) #3行4列
print(a14.shape) #3行4列
a14 = a14.reshape(2,3,2)
print(a14) #2个3行2列的数组
print(a14.shape)

#应用:将一张图片的三维数组转换为一维数组
#图片的三维数组:(height,width,channel) -> (height*width*channel) 
[ 1  2  3  4  5  6  7  8  9 10 11 12]
(12,)
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]
(3, 4)
[[[ 1  2]
  [ 3  4]
  [ 5  6]]

 [[ 7  8]
  [ 9 10]
  [11 12]]]
(2, 3, 2)
#转置tanspose()函数 交换数组的维度(可以直接.T)
a15 = np.array([(1,2,3),(4,5,6)])
print(a15.transpose())
print()
print(a15.T)
[[1 4]
 [2 5]
 [3 6]]

[[1 4]
 [2 5]
 [3 6]]
#flatten()函数 将多维数组转换为一维数组,注意每个元组的长度是相同的,返回的是一个新的数组
a16 = np.array([(1,2,3),(4,5,6),(7,8,9)])
print(a16.flatten())
[1 2 3 4 5 6 7 8 9]
#newaxis()函数 为数组增加一个维度
a17 = np.array([1,2,3])
print(a17)
print(a17.shape)
print()
print(a17[np.newaxis,:])
print(a17[np.newaxis,:].shape)
print()
print(a17[:,np.newaxis])
print(a17[:,np.newaxis].shape)
[1 2 3]
(3,)

[[1 2 3]]
(1, 3)

[[1]
 [2]
 [3]]
(3, 1)

NumPy数组的数学操作

加减乘除

*星乘表示对应元素相乘,矩阵乘法使用dot()函数
点乘表示求矩阵内积
二维数组称为矩阵积(mastrix product)

a18 = np.ones((2,2))
b18 = np.array([(-1,1),(-1,1)])
print(a18)
print()
print(b18)
[[1. 1.]
 [1. 1.]]

[[-1  1]
 [-1  1]]
#数组的加法 
a18 + b18
array([[0., 2.],
       [0., 2.]])
#数组的减法
a18 - b18
array([[2., 0.],
       [2., 0.]])
#数组的对应元素乘法
a18 * b18
array([[-1.,  1.],
       [-1.,  1.]])
#数组的矩阵乘法
a18.dot(b18)
array([[-2.,  2.],
       [-2.,  2.]])
#数组的除法
a18 / b18
array([[-1.,  1.],
       [-1.,  1.]])

求和、求积

a19 = np.array([1,2,1])
print(a19.sum())
a19.shape #一维数组的shape是一个元组
4
    (3,)
print(a19.prod()) #数组元素的乘积 
2

平均数、方差、标准差、最大值、最小值、最大值索引、最小值索引

a20 = np.array([5,3,1]) #创建一个数组
print("mean:",a20.mean()) #计算数组的平均值
print("var:", a20.var()) #计算数组的方差
print("std:", a20.std()) #计算数组的标准差
print("max:", a20.max()) #计算数组的最大值
print("min:", a20.min()) #计算数组的最小值
print("argmax:", a20.argmax()) #返回数组最大值的索引
print("argmin:", a20.argmin()) #返回数组最小值的索引
mean: 3.0
var: 2.6666666666666665
std: 1.632993161855452
max: 5
min: 1
argmax: 0
argmin: 2
#排序
a21 = np.array([3,1,2,4,5])
print(np.sort(a21)) #对数组进行排序
print(np.argsort(a21)) #返回排序后的索引
print(a21) #原数组不变
[1 2 3 4 5]
[1 2 0 3 4]
[3 1 2 4 5]

数组、矩阵、维度之间的关系

  • 数组、矩阵:数据组织结构形式(班级-座位)
  • 维度:类似通讯地址,省-市-区 (每个维度都有含义)

矩阵是数组的一种特例,专指二维结构。数组则是一个更通用的概念,可以具有任意维度。

NumPy线性代数

有关线性代数的运算均在 numpy.linalg 中
矩阵 (matrix) 是 array 的分⽀,matrix 和 array 在很多时候都是通⽤的,⽤哪⼀个都⼀样。官⽅建议⼤家如果两个可以通⽤,那就选择 array,因为 array 更灵活,速度更快。
array 的优势就是不仅仅表⽰⼆维,还能表⽰ 3、4、5… 维,⽽且在⼤部分 Python程序⾥,array 也是更常⽤的。
dot:矩阵乘法,对于两个⼀维的数组,计算的是这两个数组对应下标元素的乘积和(数学上称之为内积)
对于⼆维数组,计算的是两个数组的矩阵乘积
对于多维数组,它的通⽤计算公式如下,即结果数组中的每个元素都是:数组 a 的最后⼀维上的所有元素与数组 b 的倒数第⼆位上的所有元素的乘积和:

dot(a, b)[i,j,k,m] = sum(a[i,j,:] * b[k,:,m])

import numpy as np
# 定义两个简单的矩阵
m1 = np.array([[1, 2], [3, 4]], dtype=np.float32)
m2 = np.array([[5, 6], [7, 8]], dtype=np.float32)
# 使⽤ np.dot 进⾏矩阵乘法
result_dot = np.dot(m1, m2)

# 使⽤ @ 运算符进⾏矩阵乘法
result_at = m1 @ m2
print("矩阵 1:")
print(m1)
print("矩阵 2:")
print(m2)
print('-----------------------')
print("使⽤ np.dot 得到的矩阵乘法结果:")
print(result_dot)
print("使⽤ @ 运算符得到的矩阵乘法结果:")
print(result_at)
# 创建⼀个全零矩阵,⽤于存储⼿动推演的结果
# 结果矩阵的⾏数等于 matrix1 的⾏数,列数等于 matrix2 的列数
manual_result = np.zeros((m1.shape[0], m2.shape[1]), dtype=np.float32)
print('-----------------------')
print("⼿动推演过程:")
# 外层循环:遍历 matrix1 的每⼀⾏
# i 表⽰结果矩阵的⾏索引
for i in range(m1.shape[0]):
    # 中层循环:遍历 matrix2 的每⼀列
    # j 表⽰结果矩阵的列索引
    for j in range(m2.shape[1]):
        # 初始化当前位置的结果为 0
        manual_result[i, j] = 0
        # 内层循环:计算 matrix1 的第 i ⾏与 matrix2 的第 j 列对应元素的乘积之和
        # k 表⽰参与乘法运算的元素索引
        for k in range(m1.shape[1]):
            # 打印当前正在计算的元素
            print(f"{m1[i, k]} * {m2[k, j]} = {m1[i, k] * m2[k, j]}")
            # 将 matrix1 的第 i ⾏第 k 列元素与 matrix2 的第 k ⾏第 j 列元素相乘,并累
            manual_result[i, j] += m1[i, k] * m2[k, j]
            # 打印当前位置计算完成后的结果
            print(f"结果矩阵[{i+1},{j+1}]:{manual_result[i, j]}\n")
print("⼿动推演结果:")
print(manual_result)
矩阵 1:
[[1. 2.]
 [3. 4.]]
矩阵 2:
[[5. 6.]
 [7. 8.]]
-----------------------
使⽤ np.dot 得到的矩阵乘法结果:
[[19. 22.]
 [43. 50.]]
使⽤ @ 运算符得到的矩阵乘法结果:
[[19. 22.]
 [43. 50.]]
-----------------------
⼿动推演过程:
1.0 * 5.0 = 5.0
结果矩阵[1,1]:5.0

2.0 * 7.0 = 14.0
结果矩阵[1,1]:19.0

1.0 * 6.0 = 6.0
结果矩阵[1,2]:6.0

2.0 * 8.0 = 16.0
结果矩阵[1,2]:22.0

3.0 * 5.0 = 15.0
结果矩阵[2,1]:15.0

4.0 * 7.0 = 28.0
结果矩阵[2,1]:43.0

3.0 * 6.0 = 18.0
结果矩阵[2,2]:18.0

4.0 * 8.0 = 32.0
结果矩阵[2,2]:50.0

⼿动推演结果:
[[19. 22.]
 [43. 50.]]

NumPy广播机制

⼴播 (Broadcast) 是 numpy 对不同形状 (shape) 的数组进⾏数值计算的⽅式,对数组的算术运算通常在相应的元素上进⾏。如果两个数组 a 和 b 形状相同,即满⾜

a.shape == b.shape

那么 a*b 的结果就是 a 与 b 数组对应位相乘。这要求维数相同,且各维度的⻓度相同。

a21 = np.array([1,2,3])
b21= np.array([4,5,6])
a21 + b21
array([5, 7, 9])
#当运算中的 2 个数组的形状不同时,numpy 将⾃动触发⼴播机制
a22 = np.array([(1,2), (2,2), (3,3), (4,4)]) #shape(4,2)
b22 = np.array([-1,1]) #shape(2,) -> shape(1,2) -> shape(4,2) 
a22 + b22
array([[0, 3],
       [1, 3],
       [2, 4],
       [3, 5]])

你可能感兴趣的:(自然语言处理NLP,自然语言处理,numpy,python,conda,人工智能,机器学习,深度学习)