怎么用 Matlab 实现 aurograd 自动微分
注意:
- 本文是之前的文章《投影梯度下降法(ee227c Lecture4 学习笔记)》的一部分。因为我觉得可能还会有人需要这个方法,为了方便被搜索引擎搜到,所以单独拿出来写一篇文章。如果要下载源码,请点击原文。
- 本文所描述的方法只适用于有显式数学表达式的函数,自变量可以是标量、向量、矩阵,但是必须有数学表达式。一般的编程函数,比如里面有
for
循环啊、if
啊、递归等,是用不了的。
在查文档的时候,发现有gradient
、diff2
等函数,但是它们都不满足我的需要。在问LLM的时候,LLM给出了这样的回答:
LLM完全理解了我的需要,然后给出了一个完全错误的回答。所以,接下来的内容,就是实现这个图里面的东西。如果你发现图里面的东西不是你想要的,那可以不用看了。
接下来利用稀疏逆协方差估计的背景介绍一下所用的方法。
稀疏逆协方差估计是一种统计方法,用于估计变量之间的依赖关系。该方法通过优化一个包含正则化项的目标函数来实现。其优化目标为: \[
\min _{X \in \mathbb{R}^{n \times n}, X \succeq 0}\langle S, X\rangle-\log \operatorname{det}(X)+\alpha\|X\|_1
\] 在这里,我们定义: \[
\langle S, X\rangle=\text{tr} (S^\top X)
\] 和 \[
\|X\|_1=\sum_{ij}|X_{ij}|
\] 在原文中,使用到了python
的autograd
功能。但是Matlab
不带有这个功能,为此,我颇下了一番功夫,最终得到一个解决方案。
这个问题解决起来很棘手,因为函数的参数都是矩阵。如果只用 syms A
指令,生成的只是单个变量。例如:
1 |
|
输出
1 |
|
这显然不是我们要的结果。这时,我们需要生成矩阵符号:
1 |
|
输出
1 |
|
但是此时如果我们直接用MatlabFunction
函数转换,会得到一个以25个变量为参数的函数:
1 |
|
输出:
1 |
|
这并不是我们需要的形式。在生成函数时,我们使用Vars
字符串,然后把S
和X
用大括号括起来,这样就行了。
1 |
|
输出
1 |
|
此时如果想用gradient
函数求微分,又会报错:
1 |
|
输出:
1 |
|
既然他说 must be a vector,那就把它向量化:
1 |
|
输出:
1 |
|
成功了。
所以我先用Matlab的符号运算生成了矩阵符号,书写函数以后,将被求导的矩阵转换成向量,用gradient
函数进行符号求导,然后再进行一次矩阵向量化的包装,这样一来,基本可以实现autograd
自动求导的效果。
1 |
|
这时,只要运行
1 |
|
它就会返回函数
1 |
|
也就是 \[
\text{tr}(S^\top X)-\log \operatorname{det}(X)+0.1\|X\|_1
\] 在矩阵X
处的导数。
本站的运行成本约为每个月5元人民币,如果您觉得本站有用,欢迎打赏: