numpy中维度的正确理解姿势

作者:千千Sama
原文地址:https://blog.****.net/lllxxq141592654/article/details/83011056



前言

在使用numpy的时候,有时候会遇到这样的问题:

  • 为什么数学里的向量在numpy中需要用两个[]括起来?如[[1 2 3]]
  • 维度为(2,3,4)的矩阵是什么鬼?
  • 什么?还有维度为(3,)的矩阵?
    如果你有这样的问题,说明对numpy中矩阵的准确表达不够理解,下面就来为你排忧解难!

理解numpy矩阵维度的正确姿势

我们在线性代数中最常见到的矩阵入手,就是类似这样的了:
147258369[123456789][1amp;2amp;34amp;5amp;67amp;8amp;9]⎡⎣⎢147258369⎤⎦⎥[123456789] \left[\begin{matrix}1 & 2 & 3 \\4 & 5 & 6 \\7 & 8 & 9\end{matrix}\right]147
是一个3×1的矩阵,所以在numpy中的表达应该是

[[1 2 3]]
  • 1

它的shape也即(3,1)

因为需要用两个坐标信息索引某一元素,所以它的维数也为2
numpy中维度的正确理解姿势

以上就是矩阵和向量在numpy中的正确表达。


我们已经把最常见的掌握好了,现在来探索一下更复杂的情况。
有人可能见过这样的shape:(3,),也见过这样的numpy表达[1,2,3](注意只有一对括号)。这是怎么回事呢?
原来,如果我们没有给numpy指定列信息(也即第二维),那么它的shape就是(3,),其实上面的[1,2,3]就是shape为(3,)的一个例子。
注意:形如[1,2,3]这样的东西看似是个数学中的向量,其实并不是!不要下意识的认为它就是个向量,numpy是不这么认的!
那它到底是什么呢?它只是几个数,用一个维度排列起来。

因为索引某个具体元素只需要一个坐标信息,所以[1,2,3]的维数是1.
numpy中维度的正确理解姿势

最后看维度为(2,3,4)的矩阵。
通过上面的讲解,我们明白可以把维度类比为坐标轴,那么维度为(2,3,4)的矩阵就好理解了,一张图即可

因为索引某个具体元素需要行,列,高,3个坐标信息,所以矩阵的维数是3,。
numpy中维度的正确理解姿势

举个具体例子

[[[ 1  2  3  4]
  [ 5  6  7  8]
  [ 9 10 11 12]]

[[13 14 15 16]
[17 18 19 20]
[21 22 23 24]]]

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

关于矩阵的axis

矩阵的axis的规定是这样的——维度中的第一个定义为axis=0,第二个axis=1,以此类推。
例如,维度为(1,3)的矩阵,它的axis有2个,第一个1代表的那个轴,第二个是3代表的那个轴
维度为(2,3,4)的矩阵,它的axis有3个,第一个2代表的那个轴,第二个是3代表的那个轴,第三个是4代表的那个轴。
我们用numpy.sum求和函数来做实验
官网手册的用法是

numpy.sum(a, axis=None, dtype=None, out=None, keepdims=<class numpy._globals._NoValue>)
  • 1

这里我们只看axis这个参数。
根据上面说的axis的含义,矩阵
147258369[123456789][1amp;2amp;34amp;5amp;67amp;8amp;9]⎡⎣⎢147258369⎤⎦⎥[123456789] \left[\begin{matrix}1 &amp;amp; 2 &amp;amp; 3 \\4 &amp;amp; 5 &amp;amp; 6 \\7 &amp;amp; 8 &amp;amp; 9\end{matrix}\right][121518]
需要指定axis=0

import numpy as np
a=np.arange(1,10).reshape(3,3)
print(a)
print(np.sum(a,axis=0))
  • 1
  • 2
  • 3
  • 4
[[1 2 3]
[4 5 6]
[7 8 9]]
[12 15 18]
  • 1
  • 2
  • 3
  • 4

再举个例子,矩阵

[[[ 1  2  3  4]
  [ 5  6  7  8]
  [ 9 10 11 12]]

[[13 14 15 16]
[17 18 19 20]
[21 22 23 24]]]

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

若指定axis=0进行求和,结果应该是什么样的呢?
提示,想一下这张图

numpy中维度的正确理解姿势

它的axis=0的轴对应的是2代表的那个维度,也即图中的高,沿着这个轴对矩阵进行求和,其实就是把两个(3×4)的矩阵合并,那么答案就很明显了

import numpy as np
a=np.arange(1,25).reshape(2,3,4)
print(a)
print("--------------")
print(np.sum(a,axis=0))
  • 1
  • 2
  • 3
  • 4
  • 5
[[[ 1  2  3  4]
  [ 5  6  7  8]
  [ 9 10 11 12]]

[[13 14 15 16]
[17 18 19 20]
[21 22 23 24]]]
--------------
[[14 16 18 20]
[22 24 26 28]
[30 32 34 36]]

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

同理,axis=1,axis=2的时候答案是什么呢?
axis=1

[[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]

[[13 14 15 16]
[17 18 19 20]
[21 22 23 24]]]
--------------
[[15 18 21 24]
[51 54 57 60]]

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

axis=2

[[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]

[[13 14 15 16]
[17 18 19 20]
[21 22 23 24]]]
--------------
[[10 26 42]
[58 74 90]]

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

写在最后

关于axis的内容,其实在写的时候留了个小陷阱——求和后维度貌似少了一维,比如3阶矩阵,按行按列求和后是个向量,应该也是两对[]呀,怎么变成一个了?这就涉及到numpy的另一个参数了——keepdims。如果你不会用这个参数,请参见numpy中keepdims的理解

        </div>
					<link href="https://****img.cn/release/phoenix/mdeditor/markdown_views-a47e74522c.css" rel="stylesheet">
            </div>
								
				<script>
					(function(){
						function setArticleH(btnReadmore,posi){
							var winH = $(window).height();
							var articleBox = $("div.article_content");
							var artH = articleBox.height();
							if(artH > winH*posi){
								articleBox.css({
									'height':winH*posi+'px',
									'overflow':'hidden'
								})
								btnReadmore.click(function(){
									if(typeof window.localStorage === "object" && typeof window.****.anonymousUserLimit === "object"){
										if(!window.****.anonymousUserLimit.judgment()){
											window.****.anonymousUserLimit.Jumplogin();
											return false;
										}else if(!currentUserName){
											window.****.anonymousUserLimit.updata();
										}
									}
									
									articleBox.removeAttr("style");
									$(this).parent().remove();
								})
							}else{
								btnReadmore.parent().remove();
							}
						}
						var btnReadmore = $("#btn-readmore");
						if(btnReadmore.length>0){
							if(currentUserName){
								setArticleH(btnReadmore,3);
							}else{
								setArticleH(btnReadmore,1.2);
							}
						}
					})()
				</script>