线性代数

好勒,非常感谢道友的知识分享! :handshake:

运行A/A.sum(axis=1),看看会发生什么。你能分析原因吗?
如果n!=m的话报错,n==m的话,对每一列相除对应的值

2022-05-15T16:00:00Z

C.sum(axis=2)很好理解。但是要计算C.sum(axis=0)时,可以写出C[0],C[1],用C[0]+C[1]。这是个人理解。但是碰到axis=1的时候,这种方法理解起来又出现了新的问题。比入到底应该 C[0][0]+C[0][1]+C[0][2];还是应该 C[0][0]+C[0][1]+C[0][2]+ C[1][0]+C[1][1]+C[1][2]。
对于大于等于三维的张量,不同维度的相加有没有更好的理解方法??

有了新的理解。C.sum(axis=1)就是找到C的第二维的数据,如果该维度的数值是3,那么就把第二维的数据3个3个加在一起。同理其他维度也是如此。
如果有更简单的理解方法请大神们指教!

这个地方的axis=0我理解的就是让0这个维度消失,也就是让行消失,按列来进行求和

tips:
1.还是建议在学习之前把整个知识点绘图为思维导图
2.对于学习是很容易忘记的,确定要进入该行业,对于知识点在大脑清晰的脉络还是非常importance
3.This is perfect deep learn’s book ,I have interesting in dl field

axis=0 ,可以理解为按行的方向进行压缩,那么就等价于按列求和,axis=1 理解为按列的方向进行压缩。不过如果维度过多axis=2,3这种,就不太好等价为按什么进行求和了

翻了翻文档才明白shape右对齐是将两个shape摆在一起,如下:

(4,3)
  (3)

特意将3对齐,剩下的4为多出来的维度叫“头部维度”?只有3那列为“尾部维度”?尾部维度相同可以广播

Python里axis=0,是指运算沿着 ↓ 方向(向下)进行的;
axis=1,是指运算沿着 → 方向(向右)进行的。

拿sum函数举例,sum(axis=0)的结果就是把每一列求和再呈现出来,
sum(axis=1)的结果就是把每一行求和;
加上参数keepdims=True会更清晰

1,2,3:用线性代数证明。
4.答:输出是2。
5.答:是的。对应于形状中第一个轴的长度。
6.答:发生错误,因为形状不符合广播机制。广播机制是从形状尾部开始进行匹配,因此如果是A/A.sum(axis=1, keepdim=True),此时两者形状为(5, 4)和(5, 1),可以进行广播。
7.答:分别在轴0,1,2上降维,形状分别为(3, 4)、(2, 4)、(2, 3)。
8.答:均为一个标量。

一点发现:2.3.10中的范数计算函数使用的是torch.norm(),但是在2.3.13的练习第8题中使用的是torch.linalg.norm()。建议统一采用torch.linalg.norm()。理由是通过查看torch.norm()官方文档说明(运行help(torch.norm)),发现torch.norm已经过时并可能在未来PyTorch版本中被移除,官方建议采用替代采用torch.linalg.norm,具体信息如下图所示:

0代表行的维度“消失了”,故只剩下一行,也就是列和;
1代表列的维度“消失了”,故只剩下一列,也就是行和;
为什么0代表方向,1代表类方向?
因为(m,n)表示m行n列,而这个二元坐标里,第0个元素代表行,第1个元素代表列。同理,三维张量坐标同理,在三元坐标(a,m,n),此时行方向应该是1,列方向应该是2

大佬你好,想知道笔记是怎么做的,非常美观欸

长度不匹配所以无法广播,可以看之前广播机制的原则,会发现A是方阵满足,右对齐,大小一致,不是方阵由于是对axis=1求和,再右对齐(axis=0和axis=1)大小必然不同,所以会报错,如果A/A.sum(axis=[0])不管A是什么形状都可以满足广播

你可以理解成最后求和之后消失的维度,比如axis=1就是维度为1会消失,书上没问题

行列相等的话,是ok的。A.sum(axis = 1)会使得轴1坍缩,当轴0和轴1的长度不同,是没法计算的。
行列相等时,可以根据上一节讲的广播进行运算。

其实可以总结广播的条件是:
看形状,轴数相等,且每个对应轴的长度相等或=1

另外一提,pytorch在进行矩阵乘法时除了可以用torch.mm(A, B)外,还可以A @ B,后面这种写法比较少见,但是简洁。

In [24]: A
Out[24]:
tensor([[ 0.,  1.,  2.,  3.],
        [ 4.,  5.,  6.,  7.],
        [ 8.,  9., 10., 11.],
        [12., 13., 14., 15.],
        [16., 17., 18., 19.]])

In [25]: B
Out[25]:
tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]])

In [26]: torch.mm(A, B)
Out[26]:
tensor([[ 6.,  6.,  6.],
        [22., 22., 22.],
        [38., 38., 38.],
        [54., 54., 54.],
        [70., 70., 70.]])

In [27]: A @ B
Out[27]:
tensor([[ 6.,  6.,  6.],
        [22., 22., 22.],
        [38., 38., 38.],
        [54., 54., 54.],
        [70., 70., 70.]])

1.使用数学方法证明A = (A’)’ 即可,比较简单,不重复赘述
2.同上,使用数学方法证明 (A + B)’ = A’ + B’即可
3.同上,对于n*n方阵中的任一下标i,j元素,都可证明 Aij + Aji = Aij + Aji = Bij = Bji。其中B = A + A’
4.len(X)输出的是2
5.与4相同,一起解释。假设X为四维张量,当张量X 的shape为 m * n * q * l 时,len(X)的长度为m,对应dim=0的长度,即shape[0]的大小
6.运行 A/A.sum(axis=1) 会报错,报错原因如下:
  假设A是shape为 m * n * q 的三维张量
  则A.sum(axis=1)的 shape 为 m * q 的二维张量
  我们知道,进行/运算时,要保证shape的大小是一致的,所以上式在运行时报错。
7. shape为(2,3,4)的形状,在dim=0时的输出shape为 (3,4),在dim=1时的输出shape为(2,4),在dim=2时的输出shape为(2,3)
8.提供一个四维的张量,经计算,输出的是一个标量,为L2范数,如下例子证明:
pic3

import torch


# x = torch.tensor(2.0)
# y = torch.tensor(3.0)
# print("x==y", x == y)
# y = x.clone()
# print("a copy to b", y)
# print("x*y", torch.mul(x, y), x * y)
# print("x/y", torch.div(x, y), x / y)
# print("x+y", torch.add(x, y), x + y)
# print("x**y", torch.pow(x, y), x ** y)
# 
# print(torch.arange(4))
# print(torch.arange(16).view(2, 2, 4))
# print("--")
# x = torch.randn(2, 2)
# print("x value is ", x)
# print("x.sum to size to 1", x.sum(axis=[0, 1]), x.sum(axis=[1, 0]))
# print("--")
# print(x[1], len(x), x.shape, x.T)
# 
# print(torch.arange(20).reshape(4, 5), torch.arange(20).view(1, 20))
# print("--")
# u = torch.tensor([3.0, -3.0])
# print(torch.norm(u))

def test_demo1():
    print("test demo first")
    x = torch.randn(2, 2)
    y = x.clone()
    print(x)
    print("copy x to y ", y)
    x = x.reshape(1, 4).reshape(2, 2)
    print("x.reshape.reshape valuw same ?", x == y)


def test_demo2():
    print("test demo second")
    x, y = torch.randn(2, 2), torch.randn(2, 2)
    print(f"x value is \n{x}\n\ny value is \n{y}\n")
    _sum = torch.add(x, y)
    print("x add y value is\n", _sum)
    _sum2 = _sum.view(1, 4).view(1, 4)
    print("sum value is same ?\n", _sum2 == torch.add(x.view(1, 4), y.view(1, 4)))


def test_demo3():
    """
    如果矩阵 a 是对称的,则矩阵 a^T + a 也一定是对称的。但如果矩阵 a 不对称,那么矩阵 a^ T + a  就一般不是对称的。
    """
    print("test demo third")
    x = torch.randn(1, 5)
    y = x.view(5, 1)
    print(f"the sum value is\n {torch.add(x, y).numpy()}")
    

def test_demo4():
    print("test demo forth")
    x = torch.randn(2, 3, 4)
    print("x value is\n", x)
    print("x len is \n", len(x))
    

def test_demo5():
    print("test demo 5")
    x = torch.randn(3, 3)
    print(f"x value is \n{x.numpy()}\nlen(x) value is\n {len(x)}")
    
    
def test_demo6():
    print("test demo 6")
    x = torch.randn(2, 2)
    print(x)
    print(f"a/a value is\n{x/x}\n{torch.div(x, x)}")
    print(f"\n\n{'-'*50}\nsum(axis=1) value is\n{x.sum(axis=1)}")


def test_demo7():
    """
    则输出结果将是一个标量,即形状为 ()。在 PyTorch 中,可以使用 dim 参数指定要沿着哪些轴进行求和,如果对所有的轴进行求和,则可以简单地写为 tensor.sum(),输出结果的形状为 ()。
    如果只沿着某个轴进行求和,则输出结果形状中会减少对应的维度。例如,对轴 0 进行求和,则输出形状为 (3, 4);对轴 1 进行求和,则输出形状为 (2, 4);对轴 2 进行求和,则输出形状为 (2, 3)。
    """
    print("test demo 7")
    x = torch.randn(2, 3, 4)
    print(x)
    output = x.sum(dim=(0, 1, 2))
    print(output)


def test_demo8():
    """
    linalg.norm 函数可以接受一个张量,并计算它的范数(norm)。当张量具有多个轴时,我们可以通过指定 dim 参数来计算沿着哪些轴的范数。例如,对于一个大小为 (2, 3, 4) 的张量,我们可以按如下方式计算它的范数:
    总结:
    linalg.norm 函数可以用于计算一个张量的范数,无论它具有多少个轴。当我们指定了轴时,函数会返回沿着指定轴计算得到的范数,输出形状会从张量中移除对应的轴。如果没有指定轴,则函数对整个张量进行计算,输出结果是一个标量。
    """
    x = torch.randn(2, 3, 4)
    print(x)
    # 沿着轴 (0, 1) 计算二范数:沿着轴 (0, 1) 计算了张量的二范数,输出结果是在两个轴上计算的范数,因此输出形状为 (4,)。
    print(torch.linalg.norm(x, ord=2, dim=(0, 1)))
    # 沿着轴 0 计算二范数:沿着轴 0 计算了二范数,这时会对轴 1 和 2 上的元素进行计算,输出形状为 (3, 4)。
    print(torch.linalg.norm(x, ord=2, dim=0))
    # 对整个张量计算二范数:没有指定任何轴,因此函数对整个张量进行了计算,输出结果是一个标量。
    print(torch.linalg.norm(x))
    

if __name__ == '__main__':
    test_demo8()
    test_demo7()
    test_demo6()
    test_demo5()
    test_demo4()
    test_demo3()
    test_demo2()
    test_demo1()

运行结果

tensor([[[-1.2545, -0.5056,  1.3154, -0.0660],
         [ 1.0682,  0.3092, -0.9484,  0.9354],
         [ 0.3330,  0.0151, -0.3165, -0.4617]],

        [[-1.5198,  1.0027, -0.4004, -1.3944],
         [ 1.3531, -0.2831, -0.7134, -0.5271],
         [ 0.0807,  0.5723,  0.4047,  0.7291]]])
tensor([2.6324, 1.2934, 1.6523, 1.7419])
tensor([[1.9707, 1.1229, 1.3750, 1.3960],
        [1.7239, 0.4193, 1.1868, 1.0737],
        [0.3426, 0.5725, 0.5138, 0.8630]])
tensor(4.0183)
test demo 7
tensor([[[-0.6596,  0.3917, -0.1141, -0.6916],
         [ 0.6180,  1.3962,  0.9149, -0.6632],
         [-0.2597, -1.3846, -1.8263,  0.3115]],

        [[ 0.6879,  0.7319, -1.9681,  1.0238],
         [-0.7598,  1.2949,  0.7910,  0.9299],
         [ 0.5629,  1.0090, -0.0192,  0.1628]]])
tensor(2.4804)
test demo 6
tensor([[ 1.6858, -1.0559],
        [-0.6865, -0.8169]])
a/a value is
tensor([[1., 1.],
        [1., 1.]])
tensor([[1., 1.],
        [1., 1.]])


--------------------------------------------------
sum(axis=1) value is
tensor([ 0.6298, -1.5034])
test demo 5
x value is 
[[-0.24163365 -1.562805    0.32346362]
 [-0.04694848 -0.15506767 -1.060381  ]
 [-0.8978073  -0.04264306  0.2788014 ]]
len(x) value is
 3
test demo forth
x value is
 tensor([[[-0.3772,  0.1083,  1.0138, -1.2778],
         [-1.3714, -1.6503,  1.6648,  0.8888],
         [-0.6994, -1.5098, -0.4362,  0.4289]],

        [[ 0.4660, -0.0861,  0.7674, -0.8659],
         [ 1.4352, -0.2237, -0.2477, -0.2899],
         [ 0.3212, -0.9914, -0.4831,  0.1442]]])
x len is 
 2
test demo third
the sum value is
 [[ 1.3835357  -0.70508033  0.9173095   0.4717696  -0.22867692]
 [-0.70508033 -2.7936964  -1.1713065  -1.6168464  -2.317293  ]
 [ 0.9173095  -1.1713065   0.45108336  0.00554341 -0.69490314]
 [ 0.4717696  -1.6168464   0.00554341 -0.43999654 -1.1404431 ]
 [-0.22867692 -2.317293   -0.69490314 -1.1404431  -1.8408896 ]]
test demo second
x value is 
tensor([[-2.0150, -0.8099],
        [-0.1205,  0.3034]])

y value is 
tensor([[ 0.5589,  0.0835],
        [-0.0257,  0.8108]])

x add y value is
 tensor([[-1.4561, -0.7264],
        [-0.1462,  1.1142]])
sum value is same ?
 tensor([[True, True, True, True]])
test demo first
tensor([[ 0.4403, -0.7769],
        [ 1.2694, -1.1072]])
copy x to y  tensor([[ 0.4403, -0.7769],
        [ 1.2694, -1.1072]])
x.reshape.reshape valuw same ? tensor([[True, True],
        [True, True]])