日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

【theano-windows】学习笔记三——theano中的导数

發布時間:2023/12/13 windows 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【theano-windows】学习笔记三——theano中的导数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

就一個NN而言,包含梯度、偏置、參數更新,而前面第一篇博客學習了theano中符號變量的定義, 第二篇博客學習了變量的隨機初始化, 變量之間的互相操作(類似于sigmoid(w?x+b)), 但是參數更新還應涉及到損失函數的偏導計算,這一章節就是看看theano的梯度計算函數`tensor.grad(). 此外還有雅可比式(一階導),海森矩陣(二階導),雅克比乘以向量,海森矩陣乘以向量的操作

梯度計算

目前感覺這個函數沒什么需要注意的, 使用方法直接就是 T.grad(y,x), 意思就是y對x求導,而且我們還能用function.marker.fgraph.outputs[0]把得到的導數公式輸出出來,先導入模塊,沒什么好說的

import theano import theano.tensor as T from theano import pp#用于輸出表達式
  • 拿y=x^2+x^3+x^4試水

    x=T.dscalar('x')#定義一個變量 y=x**2+x**3+x**4#定義一個操作 gy=T.grad(y,x)#將y對x求導 f=theano.function([x],gy)# 執行這個求導函數 pp(f.maker.fgraph.outputs[0])

    輸出是

    Elemwise{Composite{((i0 * i1) + (i2 * sqr(i1)) + (i3 * Composite{(sqr(i0) * i0)}(i1)))}}(TensorConstant{2.0}, x, TensorConstant{3.0}, TensorConstant{4.0})

    然后怎么依據這個輸出把導數表達式寫出來呢?這里我們把i0,i1,i2,i3分別用2,x,3,4替換(TensorConstant{2.0}意思就是常數張量2.0,’sqr’代表平方),然后帶入到前面的Composite{((i0 * i1) + (i2 * sqr(i1)) + (i3 * Composite{(sqr(i0) * i0)}(i1)))}中, 注意遇到Composite{xxx}(xxx), 就用()中的xxx去替換{}中的xxx,然后我來分析一波

    這樣就能得到一個結果2*x+3*x^2+4*(x^2)*x,剛好就是y=x2+x3+x4x的偏導結果

  • 同樣的例子套入到對率函數中去

    y1=1/(1+T.exp(-x)) gy1=T.grad(y1,x) f2=theano.function([x],gy1)# pp(gy1)pp(f2.maker.fgraph.outputs[0])

    輸出是

    Elemwise{Composite{(scalar_sigmoid((-i0)) * scalar_sigmoid(i0))}}(x)

    按照上面的圖畫一下,然后可以寫出來結果是sigmoid(-x)*sigmoid(x),其實也就是
    y?y?x=sigmoid(x)=11+e?x=sigmoid(?x)?sigmoid(x)=11+e?x?11+ex=y(1?y)

注意, T.grad()的第二個參數可以是一個列表,那么輸出也就是列表了,意思應該就是損失函數可以對權重和偏置在一個函數中求導

計算雅克比矩陣

在theano中雅克比就是計算一個函數的輸出相對于每個輸入的一階偏導數。theano中有兩種方法去實現

  • 間接(人工)方法
    由于這需要使用到循環(對每個輸入都要計算偏導數), 因而提前接觸到了theano中用于創建循環的函數scan(), 如果想提前了解scan(), 可以去看這位博主的五個例子掌握theano.scan函數

    x=T.dvector('x') y=x**2 J,updates=theano.scan(lambda i,y,x : T.grad(y[i],x),sequences=T.arange(y.shape[0]),non_sequences=[y,x]) f=theano.function([x],J,updates=updates) f([4,4]) ?``` array([[ 8., 0.],[ 0., 8.]]) ?```

    這里稍微說一下用到的scan內容:

    • 第一個參數默認就是定義的函數了,這里用了個lambda表達式lambda i,y,x : T.grad(y[i],x)意思是我們要計算這個梯度, 而這i,y,x的來源就是后面的幾個參數,賦值順序一般是sequences中的變量outputs_info的變量,non_sequences中的變量 , 這個順序要記住
    • 參數sequences表示我們需要遍歷的量,一般都是T.arange()創建的列表,把它丟給了i
    • 參數non_sequences是其他兩個輸入量[y,x],把它丟給了lambda函數中的y,x
    • 返回值J是輸出變量列表,updates是字典,表示每個輸出變量列表的更新規則
  • 直接方法
    theano中直接提供了一個函數來實現Jacobian矩陣的計算theano.gradient.jacobian(expression, wrt, consider_constant=None, disconnected_inputs='raise')

    #直接計算hessian矩陣x=T.dvector('x') y=T.dvector('y') input=[x,y] s=T.sum(x**2+y**2) f=theano.gradient.jacobian(expression=s,wrt=input) h=theano.function(input,f) x=[1,2] y=[1,2] h(x,y) ''' [array([ 2., 4.]), array([ 2., 4.])] '''

    看樣子計算的就是損失函數expression關于input中變量的偏導數

計算海森矩陣

普遍接受的關于海森矩陣的數學說法是: 它是具有標量輸出和向量輸入的二階偏導函數的矩陣。同樣有間接和直接兩種計算方法

  • 間接(人工)計算方法
    與間接計算Jacobian矩陣不同的是我們不是計算某個表達式的雅克比式,而是計算關于導數T.grad(cost,x)的雅可比式

    #間接計算Hessian矩陣x=T.dvector('x') y=x**2 cost=y.sum() gy=T.grad(cost,x)#先計算損失關于x的梯度 H,updates=theano.scan(lambda i,gy,x : T.grad(gy[i],x),sequences=T.arange(gy.shape[0]),non_sequences=[gy,x]) f=theano.function([x],H,updates=updates) f([4,4]) ''' array([[ 2., 0.],[ 0., 2.]]) '''

    依舊是theano.scan()的應用, 第一個參數是計算梯度的函數, 后面的先把sequences的列表丟給i, 然后將non_sequence中的gy,x分別丟給lambda表達式中的gy和x

  • 直接計算方法
    theano中直接提供了一個函數來實現Hessian矩陣的計算:theano.gradient.hessian(cost, wrt, consider_constant=None, disconnected_inputs='raise')

    x=T.dvector('x') y=T.dvector('y') input=[x,y] s=T.sum(x**2+y**2) f=theano.gradient.hessian(cost=s,wrt=input) h=theano.function(input,f) x=[1,2] y=[1,2] h(x,y) ''' [array([[ 2., 0.],[ 0., 2.]]), array([[ 2., 0.],[ 0., 2.]])] '''

    看樣子計算的就是損失函數cost關于input中變量的偏導數

雅可比式與向量乘積

R-操作(右乘)

計算目標

?f(x)?xv
其中 x可以是矩陣或者是張量,主要還是因為我們需要依據權重矩陣做一些表達式的計算

#雅可比式*向量 W=T.dmatrix('W') V=T.dmatrix('V') x=T.dvector('x') y=T.dot(x,W) JV=T.Rop(y,W,V)#這里直接調用的就是Rop函數對應右乘操作 f=theano.function([W,V,x],JV) w=[[1, 1], [1, 1]] v=[[2, 2], [2, 2]] x=[0,1] f(w,v,x) ''' array([ 2., 2.]) '''

這干了一件什么事情呢?數學表達式如下:
y?y?W?V=W?x=x?V

L-操作(左乘)

#向量*雅可比式 W = T.dmatrix('W') V = T.dvector('V') x = T.dvector('x') y = T.dot(x, W) VJ = T.Lop(y, W, V)#這里直接調用的就是Rop函數對應右乘操作 f = theano.function([V,x], VJ) f([2, 2], [0, 1]) ''' array([[ 0., 0.],[ 2., 2.]]) '''

yV??y?W=W?x=V?x

左乘和右乘的差別

其實從矩陣的乘法規則就能發現他們的不同:

左乘中的v與輸出有相同的shape, 右乘中的v與輸入有相同的shape。

左乘的結果與輸入有相同shape, 右乘的結果與輸出有相似的shape

海森矩陣與向量乘積

由于Hessian矩陣具有對成型, 所以有兩種操作可以得到相同的結果,但是性能可能稍有不同。所以theano建議大家在使用兩個方法時先分析一下

方法一:

x=T.dvector('x') v=T.dvector('v') y=T.sum(x**2)#定義操作 gy=T.grad(y,x)#一階導 vH=T.grad(T.sum(gy*v),x)#利用一階導得到二階導 f=theano.function([x,v],vH) f([4,4],[2,2]) ''' array([ 4., 4.]) '''

方法二:

x=T.dvector('x') v=T.dvector('v') y=T.sum(x**2)#定義操作 gy=T.grad(y,x)#一階導 Hv=T.Rop(gy,x,v)#利用Jacobian矩陣的右乘操作 f=theano.function([x,v],Hv) f([4,4],[2,2]) ''' array([ 4., 4.]) '''

注意事項

  • grad函數是符號運算: 接受和返回Theano變量
  • grad可以被重復使用
  • grad操作中, 標量損失可以直接用grad處理, 但是數組類型的需要用循環處理,比如計算Jacobian矩陣中需要對向量中每個值進行梯度的循環計算
  • 內置函數能夠高效計算向量*雅可比式、向量*海森矩陣

代碼地址:鏈接: https://pan.baidu.com/s/1eSAIZOu 密碼: wu27

總結

以上是生活随笔為你收集整理的【theano-windows】学习笔记三——theano中的导数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。