关于pytorch的SVD分解结果和书里不一样的问题

碎碎念

问题是这样的,今天在看鱼书(《深度学习进阶:自然语言处理》)。看到SVD分解:使用奇异值分解(singular value decomposition,SVD)对矩阵进行降维。

然后我手写了一下书里的代码,结果和书中的输出不一样。本来我想越过这个问题不管它,因为书里还用matplotlib画了散点图,我想我画一下看看和人家结果一不一样不就行了嘛。结果我画图也出bug了。在不能使用图的情况下我只好硬着头皮查资料看看我的SVD分解是不是出错了。

然后我去百度,百度到了什么SVD结果和书上不一样啊和PPT不一样啊怎么的,但是到底也没说为什么,所以我只好自己写一下子了。

SVD是什么

SVD就是把一个矩阵分解成U、S、V三个矩阵。其中U、V是两个列向量彼此正交的矩阵。S是除了对角线元素其他都为0的对角矩阵。

示意图大概长这样:
关于pytorch的SVD分解结果和书里不一样的问题

然后知乎上一个例子写的分解公式大概是这样:

关于pytorch的SVD分解结果和书里不一样的问题

原答主是用图像举的例子,分解的项数越多图片越精细(可以参考拉格朗日余项啊之类的项数越多越精细)。

更详细的看知乎:奇异值的物理意义是什么? - 知乎 (zhihu.com)

回到代码

我是个数学废物,所以我也不知道结果不一样究竟是什么造成的,但是看完上边那个公式,据我猜测可能是计算保留的项数不一样。所以造成了我和书上的答案不一样。

那如何验证你的结果是否正确呢?
使用一句简单的u@torch.diag(s)@v即可。

  • @是pytorch里的张量乘法(区分*是按位乘)
  • 结果中的S矩阵是个对角矩阵,但是给出的是个向量,需要使用torch.diag()将其转化为对角矩阵

给一段代码自己试一下:

import torch

# 随机生成一个5*5的张量
tensor = torch.rand(5,5)
# 使用pytorch自带的svd进行分解
u,s,v = torch.linalg.svd(tensor)

# 输出源张量,分解后的三个张量,验证结果
print(f'tensor:\n{tensor}')
print(f'U:\n{u}\nS:\n{s}\nV\n{v}')
print(f'res:\n{u@torch.diag(s)@v}')

我的结果长这样,可以看到tensor和res的结果是一样的。

关于pytorch的SVD分解结果和书里不一样的问题

你的结果可能和你的矩阵还是不一样?

比如下图这种。
其实下图这种只是乍一看不一样而已。 实际上仔细看一下数字还是一样的,看一下数量级,比如tensor[0][0]这个位置,原来是0,最后计算结果是5.0037e-07,给0.00000050037和0差别很大吗……所以这点差异可以忽而略。还是可以认为结果矩阵是和原矩阵一样的。

关于pytorch的SVD分解结果和书里不一样的问题

上一篇:Tensor和NumPy相互转换


下一篇:Pytorch 基础练习+螺旋数据分类