1、前言java
ND4J從beta2開始就開始支持自動微分,不過直到beta4版本爲止,自動微分還只支持CPU,GPU版本將在後續版本中實現。網絡
本篇博客中,咱們將用ND4J來構建一個函數,利用ND4J SameDiff構建函數求函數值和求函數每一個變量的偏微分值。ide
2、構建函數函數
構建函數和分別手動求偏導數code
給定一個點(2,3)手動求函數值和偏導,計算以下:blog
f=2+3*4+3=17,f對x的偏導:1+2*2*3=13,f對y的偏導:4+1=5get
3、經過ND4J自動微分來求博客
完整代碼io
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()); } }
4、運行結果class
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
結果爲1七、1三、5和手動求出的結果徹底一致。
自動微分屏蔽了deeplearning在求微分過程當中的不少細節,特別是矩陣求導、矩陣範數求導等等,是很是麻煩的,用自動微分,能夠輕鬆實現各式各樣的網絡結構。
快樂源於分享。
此博客乃做者原創, 轉載請註明出處