1. 程式人生 > >實現屬於自己的TensorFlow(二)

實現屬於自己的TensorFlow(二)

這樣從後向前逐級計算通過鏈式法則就可以計算出與損失值對其相關節點的梯度了。因此我們下一步要做的就是給定某個損失函式節點並計算它對於某一節點梯度計算。

下面在看一個不同的計算圖:

這裡的x節點有將輸出到兩個不同的節點中,此時我們需要計算所有從gx的路徑然後按照上面單挑路徑的鏈式法則計算方法計算每條路徑的梯度值,最終再將不同路徑的梯度求和即可。因此Lossx的梯度為:

WX20180204-205513@2x

梯度計算

通過上面對反向傳播的介紹我們已經知道損失值對某個節點的梯度是怎麼求的(具體的實現方法在下一部分說明),下面就是如何求取針對某個節點上的梯度了,只要每個節點上的梯度計算出來沿著路徑反方向不斷乘下去就會得到你想要的節點的梯度了。本部分就介紹如何求損失值對具體某個節點的梯度值。

本部分我們就是幹這麼一個事,首先我們先畫個節點:

f節點可以看成一個函式z=f(x,y), 我們需要做的就是求f(x,y)/xf(x,y)/y.

平方運算的梯度計算

我們先用一個平方運算(之所以不用求和和乘積/矩陣乘積來做例子,因為這裡面涉及到矩陣求導維度的處理,會在稍後進行總結, 而平方運算並不會涉及到維度的變化比較簡單):

Python
123456789101112 classSquare(Operation):''' Square operation. '''# ...defcompute_gradient(self,grad=None):''' Compute the gradient for square operation wrt input value.        :param grad: The gradient of other operation wrt the square output.        :type grad: ndarray.
        '''input_value=self.input_nodes[0].output_valueifgrad isNone:grad=np.ones_like(self.output_value)returngrad*np.multiply(2.0,input_value)

其中grad為損失值對Square輸出的梯度值,也就是上圖中的Loss/z的值, 它的shape一定與Square的輸出值的shape一致

神經網路反向傳播的矩陣梯度計算

矩陣梯度的計算是實現反向傳播演算法重要的一部分, 但是在實現神經網路反向傳播的矩陣求導與許多公式列表上羅列出來的還是有差別的。

矩陣/向量求導

首先先看下矩陣的求導,其實矩陣的求導本質上就是目標矩陣中的元素對變數矩陣中的元素求偏導,至於求導後的導數矩陣的形狀大都也都是為了形式上的美觀方便求導之後的繼續使用。所以不必被那些複雜的矩陣求導形式迷惑了雙眼。這裡上傳了一份矩陣求導公式法則的列表PDF版本,可以一步一步通過(行/列)向量對標量求導再到(行/列)向量對(行/列)向量求導再到矩陣對矩陣的求導逐漸擴充套件。

例如標量yy對矩陣WX20180204-210153@2x求導, 我們就對標量y對於X的所有元素求偏導,最終得到一個導數矩陣,矩陣形狀同X相同:

WX20180204-210301@2x

神經網路反向傳播中的矩陣求導

之所以把矩陣求導分成兩部分,是因為在實現矩陣求導的時候發現做反向傳播的時候的矩陣求導與矩陣求導公式的形式上還是有區別的。所謂的區別就是,我們在神經網路進行矩陣求導的時候其實是Loss(損失)函式對節點中的矩陣進行求導,而損失函式是標量,那每次我們對計算圖中的每個節點計算梯度的時候其實是計算的標量(損失值)對矩陣(節點輸出值)的求導. 也就是說在進行反向傳播的時候我們用的只是矩陣求導中的一種,即標量對矩陣的求導, 也就是上面舉的例子的形式。再進一步其實就是損失函式對矩陣中每個元素進行求偏導的過程,通俗的講就是計算圖中矩陣中的每個元素對損失值的一個影響程度。因此這樣計算出來的導數矩陣的形狀與變數的形狀一定是一致的。

直觀上理解就是計算圖中對向量/矩陣求導的時候計算的是矩陣中的元素對損失值影響程度的大小,其形狀與矩陣形狀相同。

求和操作的梯度計算

現在我們以求和操作的梯度計算為例說明反向傳播過程中矩陣求導的實現方法。

對於求和操作: C=A+b, 其中

WX20180204-210448@2x

WX20180204-210517@2x

損失值LLC梯度矩陣為

WX20180204-210611@2x

下面我們計算L/b, 根據我們之前說的這個梯度的維度(形狀)應該與b相同,也就是一個標量,那麼具體要怎麼計算呢?我們分成兩部分來處理:

WX20180204-210820@2x

下面是求和操作梯度計算的Python實現:

Python
1234567891011121314151617181920212223 classAdd(object):# ...defcompute_gradient(self,grad=None):''' Compute the gradients for this operation wrt input values.        :param grad: The gradient of other operation wrt the addition output.        :type grad: number or a ndarray, default value is 1.0.        '''x,y=[node.output_value fornode inself.input_nodes]ifgrad isNone:grad=np.ones_like(self.output_value)grad_wrt_x=gradwhilenp.ndim(grad_wrt_x)>len(np.shape(x)):grad_wrt_x=np.sum(grad_wrt_x,axis=0)foraxis,size inenumerate(np.shape(x)):ifsize==1:grad_wrt_x=np.sum(grad_wrt_x,axis=axis,keepdims=True)grad_wrt_y=gradwhilenp.ndim(grad_wrt_y)>len(np.shape(y)):grad_wrt_y=np.sum(grad_wrt_y,axis=0)foraxis,size inenumerate(np.shape(y)):ifsize==1:grad_wrt_y=np.sum(grad_wrt_y,axis=axis,keepdims=True)return[grad_wrt_x,grad_wrt_y]

其中grad引數就是上面公式中的GG它的shape應該與該節點的輸出值(output_value的形狀一直)。

矩陣乘梯度的計算

這部分主要介紹如何在反向傳播求梯度中運用維度分析來幫助我們快速獲取梯度。先上一個矩陣乘操作的例子:C=AB

其中, CM×K的矩陣, AM×N的矩陣, BN×K的矩陣。

損失值LC的梯度為 G=L/C, 其形狀與矩陣C相同同為M×K

通過維度分析可以通過我們標量求導的知識再稍微對矩陣的形狀進行處理(左乘,右乘,轉置)來出正確的梯度。當然如果需要分析每個元素的導數也是可以的,可以參考這篇神經網路中利用矩陣進行反向傳播運算的實質, 下面我們主要使用維度分析來快速計算反向傳播中矩陣乘節點中矩陣對矩陣的導數。

若我們想求L/B, 根據標量計算的鏈式法則應該有:

WX20180204-211152@2x

下面是矩陣乘操作梯度計算的Python實現:

Python
12345678910111213141516 classMatMul(Operation):# ...defcompute_gradient(self,grad=None):''' Compute and return the gradient for matrix multiplication.        :param grad: The gradient of other operation wrt the matmul output.        :type grad: number or a ndarray, default value is 1.0.        '''# Get input values.x,y=[node.output_value fornode inself.input_nodes]# Default gradient wrt the matmul output.ifgrad isNone:grad=np.ones_like(self.output_value)# Gradients wrt inputs.dfdx=np.dot(grad,np.transpose(y))dfdy=np.dot(np.transpose(x),grad)return[dfdx,dfdy]

其他操作的梯度計算

這裡就不一一介紹了其他操作的梯度計算了,類似的我們根據維度分析以及理解反向傳播裡矩陣梯度其實就是標量求梯度放到了矩陣的規則裡的一種變形的本質,其他梯度也可以推導並實現出來了。

總結

本文介紹了通過計算圖的反向傳播快速計算梯度的原理以及每個節點相應梯度的計算和實現,有了每個節點的梯度計算我們就可以通過實現反向傳播演算法來實現損失函式對所有節點的梯度計算了,下一篇中將會總結通過廣度優先搜尋實現圖中節點梯度的計算以及梯度下降優化器的實現。

參考

相關推薦

實現屬於自己TensorFlow()

這樣從後向前逐級計算通過鏈式法則就可以計算出與損失值對其相關節點的梯度了。因此我們下一步要做的就是給定某個損失函式節點並計算它對於某一節點的梯度計算。 下面在看一個不同的計算圖: 這裡的x節點有將輸出到兩個不同的節點中,此時我們需要計算所有從g到x的路徑然後按照上面單挑路徑的鏈式法則計算方法計算每條路徑的

實現屬於自己TensorFlow(1):計算圖與前向傳播

前段時間因為課題需要使用了一段時間TensorFlow,感覺這種框架很有意思,除了可以搭建複雜的神經網路,也可以優化其他自己需要的計算模型,所以一直想自己學習一下寫一個類似的圖計算框架。前幾天組會開完決定著手實現一個模仿TensorFlow介面的簡陋版本圖計算框架以學習計算圖程

Python實現屬於自己的公交地鐵線路圖

本文主要講解的就是用Python計算公交線路圖的功能,即輸入起始點和結束點,即能夠得出公交的線路。 先說下資料的來源,直接網上爬取,也可以直接略過此點,直接下載我的原始碼獲取。 # coding=utf-8 import requests from bs4 import Beauti

C++STL之vector,實現屬於自己的my_vector

直接上程式碼 #include<iostream> //#include "my_vector.cpp" template <class elementType> class My_Vector { public: typedef elem

簡單製作屬於自己維碼

一、二維碼的簡介 1,二維碼或者二維條碼是用某種特定的幾何圖形按一定的規律在平面(二維方向上)分佈的黑白相間的圖形記錄資料符號資訊的圖形。 2,二維碼上有很多的點和空白,其中的點代表二進位制的1,而空

第一次使用Android Studio時你應該知道的一切配置():新建一個屬於自己的工程並安裝Genymotion模擬器

人性 pro net 參考 json irb 一個地方 vid 調試 【聲明】 歡迎轉載,但請保留文章原始出處→_→ 生命壹號:http://www.cnblogs.com/smyhvae/ 文章來源:http://www.cnblogs.com/smyhvae/p/439

Tensorflow學習教程------實現lenet並且進行分類

-i ase vector 一個隊列 label ide def shuffle img #coding:utf-8 import tensorflow as tf import os def read_and_decode(filename): #根據文件名生成

go 開發屬於自己的日誌庫-檔案日誌庫原型實現

上一篇中已經講述了日誌庫的需求,這一篇中我們來實現日誌庫的原型。 新建一個專案,這裡我用的hm_log,在專案下新建一個log_interface.go日誌規範,定義日誌級別的方法: package hm_log type Log interface { Debug(format string, ar

用Python製作屬於自己的個性維碼,維碼換膚真的是騷操作!

  二維碼又稱QR Code,是一個近幾年來流行的一種編碼方式,使用黑白矩形圖案表示二進位制資料,被裝置掃描後可獲取其中所包含的資訊。本教程將展示如何在原有黑白圖片的基礎上,給二維碼新增一些色彩和動態效果,也可以說是給二維碼換個面板。 首先,簡單瞭解一下二維碼的基礎知識。

寫一個屬於自己的PHP的MVC框架(

第一篇文章已經把所需的目錄搭建好了,接下來的工作就是寫一些程式碼了 用編輯器開啟public/index.php檔案,寫上下面的程式碼 <?php define(DS, DIRECTORY_SEPARATOR); define(ROOT, dirna

go開發屬於自己的日誌庫-檔案日誌庫實現

上一篇中我們已經把日誌寫入檔案中了,但是還有一些問題,可以看到我們日誌內容沒有記錄時間,也沒有日誌級別。錯誤日誌,沒有錯誤的檔案和行號,也不知道在哪個函數出錯的,這些我們也是需要加入進去的。 所以,我們的日誌列印的內容應該是這樣的: 2018-11-08 18:18:18.888 DEBUG [logDe

go開發屬於自己的日誌庫-控制檯日誌實現

上一篇中我們將檔案日誌庫基本實現了,我們現在再講console日誌庫實現,那我們的日誌庫也基本就可以完成了。 新建console.go,把我們console日誌庫也實現了。因為console日誌庫只是將

go開發屬於自己的日誌庫-檔案日誌庫原型實現

上一篇中已經講述了日誌庫的需求,這一篇中我們來實現日誌庫的原型。 新建一個專案,這裡我用的hm_log,在專案下新建一個log_interface.go日誌規範,定義日誌級別的方法: package hm_log type Log interface { D

3、《SSO CAS單點系列》之 自己動手實現一個屬於自己的SSO認證伺服器!

上篇《實現一個SSO認證伺服器是這樣的》中,我們詳細講述了實現SSO的基本思路,本篇我們按照這個思路,親自動手實現一個輕量級的SSO認證中心。除了認證中心,我們還要改造系統應用的登入登出部分,使之與認證中心互動,共同完成SSO。因此我們的實現分成兩大部分,一個是SSO Ser

使用 樹莓派 搭建屬於自己的 web伺服器()設定Apache

1. 獲取伺服器ip地址: 1 ifconfig 2. 更改本地hosts檔案 要想在瀏覽器中輸入一個域名也一樣可以訪問你的伺服器,你需要更改電腦中的hosts檔案 linux 系統: 1 sudo vim /etc/hosts windows 系

遊戲程式設計之DirectX的修煉:(建立屬於自己的windows視窗程式:下)

上一節給我們寫了一個非常小的win32程式,雖然也是一個完整的win32程式,但是美中不足的是,是什麼那?就是我們使用的視窗是系統給我設計好的,所以我們現在要來設計一個自己的視窗,來裝載你的美麗的遊戲夢。 視窗這東西吧,說難也難,說簡單也不簡單,畢竟是鄙人花時間想出來的。但

(更新視訊教程)Tensorflow object detection API 搭建屬於自己的物體識別模型(2)——訓練並使用自己的模型

2018.05.10 本人時差黨,有時候回覆不及時。建立了一個QQ群,方便大家互相學習交流。 -----------------------------------------------------------------------------------------

Tensorflow object detection API 搭建屬於自己的物體識別模型(1)——環境搭建與測試

後續部落格地址(附帶視訊教程)--------------------------------------------------------------------------------------------------最近對深度學習比較感興趣,看了網上很多資料,嘗試了

打造屬於自己的underscore系列 ( )

在上一篇 打造屬於自己的underscore系列 ( 一 )的文章中,我們介紹了underscore 的一些設計思想和理念,並對框架的結構進行了詳細的介紹,這一節的原始碼打造,我們會深入javascript的資料型別,並會對underscore對各種資料型別的判定方法進行分析。 二, 資料型別診斷

Tensorflow object detection API 搭建屬於自己的物體識別模型——環境搭建與測試

1、開發環境搭建 ①、安裝Anaconda   建議選擇 Anaconda3-5.0.1 版本,已經整合大多數庫,並將其作為預設python版本(3.6.3),配置好環境變數(Anaconda安裝則已經配好)。也可以直接安裝python,安裝各種包比較麻煩,因此直接裝了Anaconda整合環境。   安