java 自动微分,ND4J自动微分 - longzhendong的个人空间 - OSCHINA - 中文开源技术交流社区...

一、前言

ND4J从beta2开始就开始支持自动微分,不过直到beta4版本为止,自动微分还只支持CPU,GPU版本将在后续版本中实现。

本篇博客中,我们将用ND4J来构建一个函数,利用ND4J SameDiff构建函数求函数值和求函数每个变量的偏微分值。

二、构建函数

构建函数和分别手动求偏导数

java 自动微分,ND4J自动微分 - longzhendong的个人空间 - OSCHINA - 中文开源技术交流社区..._第1张图片

给定一个点(2,3)手动求函数值和偏导,计算如下:

f=2+3*4+3=17,f对x的偏导:1+2*2*3=13,f对y的偏导:4+1=5

三、通过ND4J自动微分来求

完整代码

package org.nd4j.samediff;

import org.nd4j.autodiff.samediff.SDVariable;

import org.nd4j.autodiff.samediff.SameDiff;

import org.nd4j.linalg.factory.Nd4j;

/**

*

* x+y*x2+y

*

*/

public class Function {

public static void main(String[] args) {

//构建SameDiff实例

SameDiff sd=SameDiff.create();

//创建变量x、y

SDVariable x= sd.var("x");

SDVariable y=sd.var("y");

//定义函数

SDVariable f=x.add(y.mul(sd.math().pow(x, 2)));

f.add("addY",y);

//给变量x、y绑定具体值

x.setArray(Nd4j.create(new double[]{2}));

y.setArray(Nd4j.create(new double[]{3}));

//前向计算函数的值

System.out.println(sd.exec(null, "addY").get("addY"));

//后向计算求梯度

sd.execBackwards(null);

//打印x在(2,3)处的导数

System.out.println(sd.getGradForVariable("x").getArr());

//x.getGradient().getArr()和sd.getGradForVariable("x").getArr()等效

System.out.println(x.getGradient().getArr());

//打印y在(2,3)处的导数

System.out.println(sd.getGradForVariable("y").getArr());

}

}

四、运行结果

o.n.l.f.Nd4jBackend - Loaded [CpuBackend] backend

o.n.n.NativeOpsHolder - Number of threads used for NativeOps: 4

o.n.n.Nd4jBlas - Number of threads used for BLAS: 4

o.n.l.a.o.e.DefaultOpExecutioner - Backend used: [CPU]; OS: [Windows 10]

o.n.l.a.o.e.DefaultOpExecutioner - Cores: [8]; Memory: [3.2GB];

o.n.l.a.o.e.DefaultOpExecutioner - Blas vendor: [MKL]

17.0000

o.n.a.s.SameDiff - Inferring output "addY" as loss variable as none were previously set. Use SameDiff.setLossVariables() to override

13.0000

13.0000

5.0000

结果为17、13、5和手动求出的结果完全一致。

自动微分屏蔽了deeplearning在求微分过程中的很多细节,特别是矩阵求导、矩阵范数求导等等,是非常麻烦的,用自动微分,可以轻松实现各式各样的网络结构。

快乐源于分享。

此博客乃作者原创, 转载请注明出处

你可能感兴趣的:(java,自动微分)