Numpy基础
Numpy 是 Python 的一个科学计算包,包含了多维数组以及多维数组的操作
关于Numpy需要知道的几点:
NumPy 数组在创建时有固定的大小,不同于Python列表(可以动态增长)。更改ndarray的大小将创建一个新的数组并删除原始数据。
NumPy 数组中的元素都需要具有相同的数据类型,因此在存储器中将具有相同的大小。数组的元素如果也是数组(可以是 Python 的原生 array,也可以是 ndarray)的情况下,则构成了多维数组。
NumPy 数组便于对大量数据进行高级数学和其他类型的操作。通常,这样的操作比使用Python的内置序列可能更有效和更少的代码执行。
ndarray的内存结构
Numpy 的核心是ndarray
对象,这个对象封装了同质数据类型的n维数组。起名 ndarray
的原因就是因为是 n-dimension-array
的简写。
1 | import numpy as np |
我们来看一下ndarray
如何在内存中储存的:关于数组的描述信息保存在一个数据结构中,这个结构引用两个对象,一块用于保存数据的存储区域和一个用于描述元素类型的dtype
对象。
数据存储区域保存着数组中所有元素的二进制数据,dtype
对象则知道如何将元素的二进制数据转换为可用的值。数组的维数、大小等信息都保存在ndarray
数组对象的数据结构中。strides
中保存的是当每个轴的下标增加1时,数据存储区中的指针所增加的字节数。例如图中的strides
为12,4,即第0轴的下标增加1时,数据的地址增加12个字节:即a[1,0]的地址比a[0,0]的地址要高12个字节,正好是3个单精度浮点数的总字节数;第1轴下标增加1时,数据的地址增加4个字节,正好是单精度浮点数的字节数。
Numpy数组初始化
可以调用np.array去从list初始化一个数组:
1 | a = np.array([1, 2, 3]) # 1维数组 |
<class 'numpy.ndarray'> (3,) 1 2 3
[5 2 3]
1 | b = np.array([[1,2,3],[4,5,6]]) # 2维数组 |
[[1 2 3]
[4 5 6]]
1 | print(b.shape) #可以看形状(非常常用!) |
(2, 3)
1 2 4
一些内置的创建数组的函数
1 | a = np.zeros((2,2)) # 创建2x2的全0数组 |
[[ 0. 0.]
[ 0. 0.]]
1 | b = np.ones((1,2)) # 创建1x2的全1数组 |
[[ 1. 1.]]
1 | c = np.full((2,2), 7) # 定值数组 |
[[7 7]
[7 7]]
1 | d = np.eye(2) # 对角矩阵(对角元素为1) |
[[ 1. 0.]
[ 0. 1.]]
1 | e = np.random.random((2,2)) # 2x2的随机数组(矩阵) |
[[ 0.72776966 0.94164821]
[ 0.04652655 0.2316599 ]]
1 | f = np.empty((2,3,2)) # empty是未初始化的数据,默认为0 |
[[[ 0. 0.]
[ 0. 0.]
[ 0. 0.]]
[[ 0. 0.]
[ 0. 0.]
[ 0. 0.]]]
(2, 3, 2)
1 | g = np.arange(15) # 用arange可以生成连续的一串元素 |
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]
(15,)
Numpy数组数据类型
我们可以用dtype来看numpy数组中元素的类型:
1 | x = np.array([1, 2]) # numpy构建数组的时候自己会确定类型 |
int64 float64 int64
使用astype复制数组并转换数据类型
1 | int_arr = np.array([1,2,3,4,5]) |
int32
float64
使用astype将float转换为int时小数部分被舍弃
1 | float_arr = np.array([3.7, -1.2, -2.6, 0.5, 12.9, 10.1]) |
[ 3 -1 -2 0 12 10]
使用astype把字符串转换为数组,如果失败抛出异常。
1 | str_arr = np.array(['1.25', '-9.6', '42'], dtype = np.string_) |
[ 1.25 -9.6 42. ]
astype使用其它数组的数据类型作为参数
1 | int_arr = np.arange(10) |
[ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]
0 1
Numpy的复制和视图
当计算和操作数组时,它们的数据有时被复制到新的数组中,有时不复制。这里我们做个区分。
完全不复制
简单赋值不会创建数组对象或其数据的拷贝。
1 | a = np.arange(6) |
[0 1 2 3 4 5]
3169669797808
3169669797808
(3, 2)
视图或浅复制
不同的数组对象可以共享相同的数据。view
方法创建一个新数组对象,该对象看到相同的数据。与前一种情况不同,新数组的维数更改不会更改原始数据的维数,但是新数组数据更改后,也会影响原始数据。
1 | a = np.arange(6) |
False
True
False
(6,)
[ 0 1234 2 3 4 5]
深复制
copy
方法生成数组及其数据的完整拷贝。
1 | a = np.arange(6) |
False
False
[0 1 2 3 4 5]
Numpy数组取值和赋值
切片
1 | import numpy as np |
[[2 3]
[6 7]]
1 | # 创建3x4的2维数组/矩阵 |
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
多维数组可以从各个维度同时切片
1 | row_r1 = a[1, :] # 第2行,但是得到的是1维输出(列向量) |
[5 6 7 8] (4,)
[[5 6 7 8]] (1, 4)
[[5 6 7 8]] (1, 4)
1 | # 试试在第2个维度上切片也一样的: |
[ 2 6 10] (3,)
[[ 2]
[ 6]
[10]] (3, 1)
自由地取值和组合
1 | a = np.array([[1,2], [3, 4], [5, 6]]) |
[1 4 5]
[1 4 5]
1 | # 再来熟悉一下 |
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]]
1 | # 用下标生成一个向量 |
[ 1 6 7 11]
1 | # 既然可以取出来,我们当然可以对这些元素操作 |
[[11 2 3]
[ 4 5 16]
[17 8 9]
[10 21 12]]
用条件判定去取值
1 | a = np.array([[1,2], [3, 4], [5, 6]]) |
[[False False]
[ True True]
[ True True]]
1 | # 用刚才的布尔型数组作为下标就可以去除符合条件的元素啦 |
[3 4 5 6]
[3 4 5 6]
总结
Numpy的基本数学运算
逐元素运算
1 | x = np.array([[1,2],[3,4]], dtype=np.float64) |
[[ 6. 8.]
[ 10. 12.]]
[[ 6. 8.]
[ 10. 12.]]
[[-4. -4.]
[-4. -4.]]
[[-4. -4.]
[-4. -4.]]
[[ 5. 12.]
[ 21. 32.]]
[[ 5. 12.]
[ 21. 32.]]
[[ 0.2 0.33333333]
[ 0.42857143 0.5 ]]
[[ 0.2 0.33333333]
[ 0.42857143 0.5 ]]
[[ 1. 1.41421356]
[ 1.73205081 2. ]]
整体运算
NumPy计算乘积的函数:dot,inner,outer
- dot : 对于两个一维的数组,计算的是这两个数组对应下标元素的乘积和(数学上称之为内积);对于二维数组,计算的是两个数组的矩阵乘积;对于多维数组,它的通用计算公式如下,即结果数组中的每个元素都是:数组a的最后一维上的所有元素与数组b的倒数第二位上的所有元素的乘积和
- inner : 和dot乘积一样,对于两个一维数组,计算的是这两个数组对应下标元素的乘积和;对于多维数组,它计算的结果数组中的每个元素都是:数组a和b的最后一维的内积,因此数组a和b的最后一维的长度必须相同
- outer : 只按照一维数组进行计算,如果传入参数是多维数组,则先将此数组展平为一维数组之后再进行运算。outer乘积计算的列向量和行向量的矩阵乘积:
1 | a = np.arange(12).reshape(2,3,2) |
(2, 3, 2, 3)
True
True
True
True
(2, 3, 2, 3)
True
True
True
[[ 4 5 6 7]
[ 8 10 12 14]
[12 15 18 21]]
求向量内积
1 | v = np.array([9,10]) |
219
219
矩阵的乘法
1 | v = np.array([9,10]) |
[ 29. 67.]
[ 29. 67.]
[ 29. 67.]
转置
1 | x = np.array([[1,2],[3,4]], dtype=np.float64) |
[[ 1. 2.]
[ 3. 4.]]
[[ 1. 3.]
[ 2. 4.]]
[1 2 3]
[1 2 3]
[[1 2 3]]
[[1]
[2]
[3]]
高维tensor转置
1 | arr = np.arange(16).reshape((2, 2, 4)) |
[[[ 0 1 2 3]
[ 4 5 6 7]]
[[ 8 9 10 11]
[12 13 14 15]]]
1 | print(arr.transpose((1,0,2))) |
[[[ 0 1 2 3]
[ 8 9 10 11]]
[[ 4 5 6 7]
[12 13 14 15]]]
1 | print(arr.swapaxes(1,2)) |
[[[ 0 4]
[ 1 5]
[ 2 6]
[ 3 7]]
[[ 8 12]
[ 9 13]
[10 14]
[11 15]]]
Numpy的统计特性
- np.sum(),返回求和
- np.mean(),返回均值
- np.max(),返回最大值
- np.min(),返回最小值
- np.ptp(),数组沿指定轴返回最大值减去最小值,即(max-min)
- np.std(),返回标准偏差(standard deviation)
- np.var(),返回方差(variance)
- np.cumsum(),返回累加值
- np.cumprod(),返回累乘积值
举例
1 | x = np.array([[1,2],[3,4]]) |
[[1 2]
[3 4]]
10
[4 6]
[3 7]
2.5
[ 2. 3.]
[ 1.5 3.5]
4
1
[ 1. 1.]
[ 0.25 0.25]
[[1 2]
[4 6]]
[[ 1 2]
[ 3 12]]
Numpy数组排序
一维数组的排序
1 | arr = np.random.randn(8) |
[ 0.70150419 -0.88493701 0.37449618 -0.42676191 1.52654468 -1.79515205
0.05635219 0.80712566]
[-1.79515205 -0.88493701 -0.42676191 0.05635219 0.37449618 0.70150419
0.80712566 1.52654468]
二维数组也可以在某些维度上排序
1 | arr = np.random.randn(5,3) |
[[-0.51135747 -0.0355637 0.38398028]
[-1.44309081 1.31425286 0.16295143]
[-0.54112556 -1.07293118 0.55690543]
[ 0.55382507 0.79843566 -1.29064181]
[ 0.69978121 0.24467205 0.13107927]]
[[-0.51135747 -0.0355637 0.38398028]
[-1.44309081 0.16295143 1.31425286]
[-1.07293118 -0.54112556 0.55690543]
[-1.29064181 0.55382507 0.79843566]
[ 0.13107927 0.24467205 0.69978121]]
找出排序后位置在5%的数字
1 | large_arr = np.random.randn(1000) |
-1.65535730932
Broadcasting(广播)
应用场景:要用小的矩阵去和大的矩阵做一些操作,但是希望小矩阵能循环和大矩阵的那些块做一样的操作。
举例
- 一个矩阵的每一行都加上一个向量
1 | x = np.array([[1,2,3], [4,5,6]]) |
[[2 4 6]
[5 7 9]]
1 | x = np.array([[1,2,3], [4,5,6]]) # 2x3的 |
[[ 5 6 7]
[ 9 10 11]]
- 逐元素运算
1 | x = np.array([[1,2,3], [4,5,6]] |
[[ 2 4 6]
[ 8 10 12]]
可广播条件
- 数组拥有相同形状。
- 数组拥有相同的维数,每个维度拥有相同长度,或者长度为 1。
- 数组拥有极少的维度,可以在其前面追加长度为 1 的维度,使上述条件成立。
广播规则
- 让所有输入数组都向其中shape最长的数组看齐,shape中不足的部分都通过在前面加1补齐
- 输出数组的shape是输入数组shape的各个轴上的最大值
- 如果输入数组的某个轴和输出数组的对应轴的长度相同或者其长度为1时,这个数组能够用来计算,否则出错
- 当输入数组的某个轴的长度为1时,沿着此轴运算时都用此轴上的第一组值
总结
一些更高级的ndarray处理
where和一些其他的逻辑运算
np.where(cond,x,y):满足条件(cond)输出x,不满足输出y
1 | x_arr = np.array([1.1, 1.2, 1.3, 1.4, 1.5]) |
[ 1.1 2.2 1.3 1.4 2.5]
1 | arr = np.random.randn(4,4) |
[[ -1.10484247e+00 -3.82422727e-01 -3.24361549e-01 1.21286234e+00]
[ 1.54499855e-01 -4.77728163e-04 1.44621074e+00 -2.64241611e-03]
[ 1.36394862e+00 6.96638259e-02 -2.75237740e-01 -3.32892881e-01]
[ -1.37165175e+00 1.79997993e-01 -1.13509664e-01 1.88373639e+00]]
[[-2 -2 -2 2]
[ 2 -2 2 -2]
[ 2 2 -2 -2]
[-2 2 -2 2]]
[[ -1.10484247e+00 -3.82422727e-01 -3.24361549e-01 2.00000000e+00]
[ 2.00000000e+00 -4.77728163e-04 2.00000000e+00 -2.64241611e-03]
[ 2.00000000e+00 2.00000000e+00 -2.75237740e-01 -3.32892881e-01]
[ -1.37165175e+00 2.00000000e+00 -1.13509664e-01 2.00000000e+00]]
np.where可以嵌套使用
1 | cond_1 = np.array([True, False, True, True, False]) |
[1 2 1 0 3]
1 | arr = np.random.randn(10) |
[ 0.27350655 -1.51093462 0.26835915 -0.45991855 1.34450904 -1.86871203
0.04308971 1.69640444 -0.02191351 -0.43875275]
5
1 | bools = np.array([False, False, True, False]) |
True
False
reshape(数组变形)
numpy可以很容易地把一维数组转成二维数组,三维数组。
1 | import numpy as np |
(4,2):
[[0 1]
[2 3]
[4 5]
[6 7]]
(2,2,2):
[[[0 1]
[2 3]]
[[4 5]
[6 7]]]
-1( 维度自动推算)
如果我们在某一个维度上写上-1,numpy会帮我们自动推导出正确的维度
1 | arr = np.arange(15) |
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]
[12 13 14]]
(5, 3)
ravel(拉平数组)
1 | # 高维数组用ravel来拉平成为一维数组 |
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]
concatenate(连接数组)
1 | arr1 = np.array([[1, 2, 3], [4, 5, 6]]) |
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]]
[[ 1 2 3 7 8 9]
[ 4 5 6 10 11 12]]
连接的另一种表述垂直stack
与水平stack
1 | print(np.vstack((arr1, arr2))) # 垂直堆叠 |
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]]
[[ 1 2 3 7 8 9]
[ 4 5 6 10 11 12]]
split(拆分数组)
1 | arr = np.random.rand(5,5) |
[[ 0.08218151 0.25291976 0.990262 0.74980044 0.92433676]
[ 0.57215647 0.88759783 0.67939949 0.18618301 0.64810013]
[ 0.21424794 0.5812622 0.33170632 0.40780156 0.00946797]
[ 0.46223634 0.53574553 0.25289433 0.33226224 0.26110024]
[ 0.81823359 0.98863697 0.13713923 0.3520669 0.38301044]]
1 | first, second, third = np.split(arr, [1,3], axis = 0) # 按行拆分 |
[[ 0.08218151 0.25291976 0.990262 0.74980044 0.92433676]]
[[ 0.57215647 0.88759783 0.67939949 0.18618301 0.64810013]
[ 0.21424794 0.5812622 0.33170632 0.40780156 0.00946797]]
[[ 0.46223634 0.53574553 0.25289433 0.33226224 0.26110024]
[ 0.81823359 0.98863697 0.13713923 0.3520669 0.38301044]]
1 | first, second, third = np.split(arr, [1, 3], axis = 1) # 按列拆分 |
[[ 0.08218151]
[ 0.57215647]
[ 0.21424794]
[ 0.46223634]
[ 0.81823359]]
[[ 0.25291976 0.990262 ]
[ 0.88759783 0.67939949]
[ 0.5812622 0.33170632]
[ 0.53574553 0.25289433]
[ 0.98863697 0.13713923]]
[[ 0.74980044 0.92433676]
[ 0.18618301 0.64810013]
[ 0.40780156 0.00946797]
[ 0.33226224 0.26110024]
[ 0.3520669 0.38301044]]
堆叠辅助
1 | arr = np.arange(6) |
[[ 0. 1. ]
[ 2. 3. ]
[ 4. 5. ]
[ 0.04811148 -1.93674347]
[ 1.19646481 0.17346639]
[-1.4388562 -1.41584843]]
[[ 0. 1. 0. ]
[ 2. 3. 1. ]
[ 4. 5. 2. ]
[ 0.04811148 -1.93674347 3. ]
[ 1.19646481 0.17346639 4. ]
[-1.4388562 -1.41584843 5. ]]
[[ 1 -10]
[ 2 -9]
[ 3 -8]
[ 4 -7]
[ 5 -6]]
repeat(数组重复)
repeat(a,repeats, axis=None)
- 按元素重复
1 | arr = np.arange(3) |
[0 0 0 1 1 1 2 2 2]
[0 0 1 1 1 2 2 2 2]
- 指定axis来重复
1 | arr = np.arange(4) |
[[ 0.468845 0.43227877]
[ 0.13822954 0.14501615]]
1 | print(arr.repeat(2, axis=0)) |
[[ 0.468845 0.43227877]
[ 0.468845 0.43227877]
[ 0.13822954 0.14501615]
[ 0.13822954 0.14501615]]
[[ 0.468845 0.468845 0.43227877 0.43227877]
[ 0.13822954 0.13822954 0.14501615 0.14501615]]
tile(按规则重复数组)
tile通过重复给定的次数来构造数组。tile(A, reps):初始数组是A,重复规则是reps。reps表示数组A需要重复的次数、结果的行数。
1 | arr = np.arange(4).reshape((2, 2)) |
[[0 1 0 1]
[2 3 2 3]]
[[0 1 0 1 0 1]
[2 3 2 3 2 3]
[0 1 0 1 0 1]
[2 3 2 3 2 3]]
numpy的文件输入输出
读取csv文件作为数组
1 | import numpy as np |
[[ 0.580052 0.18673 1.040717 1.134411]
[ 0.194163 -0.636917 -0.938659 0.124094]
[-0.12641 0.268607 -0.695724 0.047428]
[-1.484413 0.004176 -0.744203 0.005487]
[ 2.302869 0.200131 1.670238 -1.88109 ]
[-0.19323 1.047233 0.482803 0.960334]]
数组文件读写
1 | arr = np.arange(10) |
1 | print(np.load('some_array.npy')) |
[0 1 2 3 4 5 6 7 8 9]
多个数组可以一起压缩存储
1 | arr2 = np.arange(15).reshape(3,5) |
1 | arch = np.load('array_archive.npz') |
[0 1 2 3 4 5 6 7 8 9]
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]]
用numpy写一个softmax
步骤:
- 数据预处理
- 计算exponential
- 每行求和
- 每一行除以计算的和
1 | import numpy as np |
[[ 1002.4195769 1000.59428635 1004.19947044 1009.17641327
1004.89329928 1001.02496808 1007.79619575 1005.61568017
1009.28511386 1000.11608716]
[ 1002.9870141 1005.59523328 1001.99337934 1008.79319814
1004.78921679 1003.91814186 1009.38777432 1005.20436416
1009.27099589 1008.69823987]
[ 1006.68713949 1009.02893339 1008.2656608 1002.27620211 1009.2256124
1004.14144532 1007.09728075 1006.21626467 1004.60860132
1004.51547132]
[ 1005.57757481 1001.6026775 1004.79229078 1004.28025577
1008.68219699 1005.6379599 1008.07958879 1006.35060616
1009.03418483 1003.50279599]
[ 1003.22924339 1006.62272977 1008.5591972 1009.72498967
1004.49414198 1004.21450523 1008.32652935 1000.90418303
1009.24606203 1001.27113066]
[ 1006.84865072 1005.24619541 1000.04356362 1003.38870582
1008.59759772 1008.80052236 1007.92905671 1006.16987466 1002.3761379
1001.55941284]
[ 1006.80724007 1004.46597582 1003.25453387 1008.55713243
1009.19618236 1002.06897172 1004.69874948 1006.51535711
1005.23735087 1006.85265988]
[ 1002.22993628 1000.59475018 1007.52711923 1000.36311206
1008.22254861 1003.94553055 1004.23517969 1005.26438502
1006.39421888 1005.22133756]
[ 1006.92863693 1003.23688304 1007.11513614 1003.28880837
1009.11093137 1006.35136574 1002.04684923 1001.13114541
1008.50487627 1008.67481458]
[ 1002.65347387 1001.90472796 1004.02149562 1009.63548587
1009.16220671 1006.39781332 1008.1526219 1003.57220839
1008.60930803 1004.41645034]]
直接对m进行e指数运算会产生上溢
1 | print(np.exp(m)) |
[[ inf inf inf inf inf inf inf inf inf inf]
[ inf inf inf inf inf inf inf inf inf inf]
[ inf inf inf inf inf inf inf inf inf inf]
[ inf inf inf inf inf inf inf inf inf inf]
[ inf inf inf inf inf inf inf inf inf inf]
[ inf inf inf inf inf inf inf inf inf inf]
[ inf inf inf inf inf inf inf inf inf inf]
[ inf inf inf inf inf inf inf inf inf inf]
[ inf inf inf inf inf inf inf inf inf inf]
[ inf inf inf inf inf inf inf inf inf inf]]
G:\Anaconda3\lib\site-packages\ipykernel_launcher.py:1: RuntimeWarning: overflow encountered in exp
"""Entry point for launching an IPython kernel.
寻找每一行的最大值
1 | #按列取最大值(即取每一行的最大值) |
[[ 1009.28511386]
[ 1009.38777432]
[ 1009.2256124 ]
[ 1009.03418483]
[ 1009.72498967]
[ 1008.80052236]
[ 1009.19618236]
[ 1008.22254861]
[ 1009.11093137]
[ 1009.63548587]] (10, 1)
通过广播的方式将每行数据减去对应行的最大值
1 | # 采用广播的方式进行减法操作 |
[[-6.86553696 -8.69082751 -5.08564343 -0.1087006 -4.39181458 -8.26014579
-1.48891811 -3.66943369 0. -9.16902671]
[-6.40076022 -3.79254104 -7.39439498 -0.59457618 -4.59855753 -5.46963247
0. -4.18341016 -0.11677843 -0.68953445]
[-2.5384729 -0.19667901 -0.95995159 -6.94941029 0. -5.08416708
-2.12833165 -3.00934773 -4.61701107 -4.71014107]
[-3.45661002 -7.43150733 -4.24189405 -4.75392907 -0.35198784 -3.39622493
-0.95459604 -2.68357867 0. -5.53138884]
[-6.49574628 -3.1022599 -1.16579247 0. -5.23084769 -5.51048445
-1.39846033 -8.82080664 -0.47892764 -8.45385902]
[-1.95187164 -3.55432696 -8.75695874 -5.41181655 -0.20292464 0.
-0.87146565 -2.63064771 -6.42438446 -7.24110952]
[-2.3889423 -4.73020655 -5.94164849 -0.63904993 0. -7.12721064
-4.49743288 -2.68082526 -3.95883149 -2.34352249]
[-5.99261232 -7.62779843 -0.69542937 -7.85943655 0. -4.27701805
-3.98736891 -2.95816359 -1.82832972 -3.00121104]
[-2.18229443 -5.87404833 -1.99579523 -5.82212299 0. -2.75956563
-7.06408214 -7.97978595 -0.6060551 -0.43611679]
[-6.982012 -7.73075791 -5.61399025 0. -0.47327916 -3.23767255
-1.48286397 -6.06327748 -1.02617783 -5.21903553]]
求预处理后的e指数
1 | #求预处理后的e指数 |
[[ 1.04312218e-03 1.68120847e-04 6.18490628e-03 8.96998943e-01
1.23782475e-02 2.58621284e-04 2.25616615e-01 2.54909015e-02
1.00000000e+00 1.04217895e-04]
[ 1.66029460e-03 2.25382585e-02 6.14688467e-04 5.51796380e-01
1.00663457e-02 4.21278021e-03 1.00000000e+00 1.52464260e-02
8.89782323e-01 5.01809632e-01]
[ 7.89869284e-02 8.21454272e-01 3.82911421e-01 9.59200640e-04
1.00000000e+00 6.19404411e-03 1.19035722e-01 4.93238409e-02
9.88228942e-03 9.00350735e-03]
[ 3.15364890e-02 5.92294057e-04 1.43803289e-02 8.61776882e-03
7.03288672e-01 3.34994945e-02 3.84967625e-01 6.83182276e-02
1.00000000e+00 3.96048477e-03]
[ 1.50984802e-03 4.49475108e-02 3.11675571e-01 1.00000000e+00
5.34898908e-03 4.04414773e-03 2.46976935e-01 1.47629228e-04
6.19447308e-01 2.13076561e-04]
[ 1.42008035e-01 2.86006179e-02 1.57362462e-04 4.46352464e-03
8.16339758e-01 1.00000000e+00 4.18337963e-01 7.20317916e-02
1.62153108e-03 7.16516327e-04]
[ 9.17266523e-02 8.82464816e-03 2.62769434e-03 5.27793627e-01
1.00000000e+00 8.02955997e-04 1.11375513e-02 6.85065952e-02
1.90854027e-02 9.59889224e-02]
[ 2.49713221e-03 4.86731255e-04 4.98860204e-01 3.86091355e-04
1.00000000e+00 1.38840018e-02 1.85484526e-02 5.19141655e-02
1.60681727e-01 4.97268106e-02]
[ 1.12782462e-01 2.81146852e-03 1.35905535e-01 2.96131163e-03
1.00000000e+00 6.33192663e-02 8.55279590e-04 3.42312686e-04
5.45498570e-01 6.46542214e-01]
[ 9.28433319e-04 4.39111184e-04 3.64648989e-03 1.00000000e+00
6.22956140e-01 3.92551533e-02 2.26986674e-01 2.32676246e-03
3.58374111e-01 5.41254683e-03]] (10, 10)
将求指数后的数据按列加和(每行求和),然后将一维数据(10,)reshape成(10,1)
1 | m_exp_row_sum = m_exp.sum(axis = 1).reshape(10,1) |
[[ 2.1682437 ]
[ 2.99772713]
[ 2.47775123]
[ 2.24916138]
[ 2.23431102]
[ 2.4842771 ]
[ 1.82649405]
[ 1.79698532]
[ 2.51101842]
[ 2.26032542]] (10, 1)
每行的数据除以对应行e指数求和
1 | m_softmax = m_exp / m_exp_row_sum |
[[ 4.81090841e-04 7.75378004e-05 2.85249591e-03 4.13698398e-01
5.70888203e-03 1.19276853e-04 1.04055008e-01 1.17564744e-02
4.61202771e-01 4.80655820e-05]
[ 5.53851145e-04 7.51844898e-03 2.05051507e-04 1.84071584e-01
3.35799265e-03 1.40532478e-03 3.33586066e-01 5.08599528e-03
2.96818985e-01 1.67396701e-01]
[ 3.18784741e-02 3.31532183e-01 1.54539898e-01 3.87125483e-04
4.03591769e-01 2.49986522e-03 4.80418376e-02 1.99066962e-02
3.98841067e-03 3.63374146e-03]
[ 1.40214434e-02 2.63339955e-04 6.39364033e-03 3.83154756e-03
3.12689288e-01 1.48942156e-02 1.71160517e-01 3.03749780e-02
4.44610159e-01 1.76087176e-03]
[ 6.75755530e-04 2.01169445e-02 1.39495159e-01 4.47565264e-01
2.39402171e-03 1.81002005e-03 1.10538297e-01 6.60737144e-05
2.77243098e-01 9.53656673e-05]
[ 5.71627193e-02 1.15126521e-02 6.33433613e-05 1.79670965e-03
3.28602537e-01 4.02531586e-01 1.68394243e-01 2.89950713e-02
6.52717479e-04 2.88420453e-04]
[ 5.02200663e-02 4.83146833e-03 1.43865475e-03 2.88965424e-01
5.47496993e-01 4.39615994e-04 6.09777585e-03 3.75071549e-02
1.04492006e-02 5.25536464e-02]
[ 1.38962304e-03 2.70859896e-04 2.77609505e-01 2.14855041e-04
5.56487574e-01 7.72627449e-03 1.03219834e-02 2.88895880e-02
8.94173844e-02 2.76723522e-02]
[ 4.49150276e-02 1.11965269e-03 5.41236712e-02 1.17932692e-03
3.98244789e-01 2.52165679e-02 3.40610640e-04 1.36324243e-04
2.17241963e-01 2.57482067e-01]
[ 4.10752058e-04 1.94269011e-04 1.61325881e-03 4.42414172e-01
2.75604625e-01 1.73670361e-02 1.00422121e-01 1.02939269e-03
1.58549786e-01 2.39458743e-03]]
验证一下,对输出值进行按列求和,每行结果应该均为1
1 | print(m_softmax.sum(axis=1)) |
[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]