1. 程式人生 > >學習筆記:caffe2 教程記錄四

學習筆記:caffe2 教程記錄四

接著caffe2 教程記錄三,這個是第四篇

##4.Caffe2的主要概念
Blobs and Workspace, Tensors

Caffe2中的資料被組織為blob。 blob只是記憶體中一個命名的資料塊。 大多數blob包含一個張量(想想多維陣列),在Python中它們被轉換為numpy陣列(numpy是一個流行的Python數值庫,已經作為Caffe2的先決條件安裝)。

Workspace(工作區)儲存所有blob。 以下示例顯示如何將Blob提供到workspace(工作空間)並再次獲取它們。 Workspace(工作區)在您開始使用它們的那一刻初始化。

from caffe2.python import workspace, model_helper
import numpy as np
# Create random tensor of three dimensions
x = np.random.rand(4, 3, 2)
print(x)
print(x.shape)

workspace.FeedBlob("my_x", x)

x2 = workspace.FetchBlob("my_x")
print(x2)

Nets and Operators(網路和運算子):

Caffe2中的基本模型抽象是網路(簡稱 network)。 網路是運算子的圖形,每個運算符采用一組輸入blob並生成一個或多個輸出blob。

在下面的程式碼塊中,我們將建立一個超級簡單的模型。 它將包含以下元件:

一個全連線層(FC)
用Softmax啟用Sigmoid
交叉熵損失
直接編寫網路非常繁瑣,因此最好使用有助於建立網路的Python類 model helpers( 模型助手)。 即使我們呼叫它並傳入單個名稱“我的第一個網路”,ModelHelper也會建立兩個相互關聯的網路:

一個初始化引數(參考init_net)
一個執行實際訓練的(參考exec_net)

 

# Create the input data
data = np.random.rand(16, 100).astype(np.float32)

# Create labels for the data as integers [0, 9].
label = (np.random.rand(16) * 10).astype(np.int32)

workspace.FeedBlob("data", data)
workspace.FeedBlob("label", label)

我們建立了一些隨機資料和隨機標籤,然後將它們作為blob提供給工作區

您現在已經使用model_helper建立了我們之前提到的兩個網路(init_net和exec_net)。 我們計劃在此模型中使用FC運算子新增完全連線的層,但首先我們需要通過建立隨機填充的blob來進行準備工作,以獲得FC op期望的權重和偏差。 當我們新增FC op時,我們將按名稱引用權重和偏差blob作為輸入。

weight = m.param_init_net.XavierFill([], 'fc_w', shape=[10, 100])
bias = m.param_init_net.ConstantFill([], 'fc_b', shape=[10, ])

在Caffe2中,FC op接收輸入blob(我們的資料),權重和偏差。 使用XavierFill或ConstantFill的權重和偏差都將採用空陣列,名稱和形狀(如shape = [output,input])。

fc_1 = m.net.FC(["data", "fc_w", "fc_b"], "fc1")
pred = m.net.Sigmoid(fc_1, "pred")
softmax, loss = m.net.SoftmaxWithLoss([pred, "label"], ["softmax", "loss"])

 檢視上面的程式碼塊:

首先,我們在記憶體中建立了輸入資料和標籤blob(實際上,您將從輸入資料來源(如資料庫)載入資料)。請注意,資料和標籤blob的第一個維度為“16”;這是因為模型的輸入是一次只有16個樣本的小批量。許多Caffe2操作員可以通過ModelHelper直接訪問,並且可以一次處理一小批輸入。

其次,我們通過定義一組運算子來建立模型:FC,Sigmoid和SoftmaxWithLoss。注意:此時,運算子沒有被執行,您只是建立模型的定義。

模型助手將建立兩個網:m.param_init_net,這是一個只執行一次的網。它將初始化所有引數blob,例如FC層的權重。實際培訓是通過執行m.net完成的。這對您來說是透明的,並且會自動發生。

網路定義儲存在protobuf結構中(有關詳細資訊,請參閱Google的協議緩衝區文件 https://developers.google.com/protocol-buffers/)。您可以通過呼叫net.Proto()輕鬆檢查它:

輸出應如下所示:

你還應該看一下param初始化net

print(m.param_init_net.Proto())

您可以看到有兩個運算子如何為FC運算子的權重和偏差blob建立隨機填充。
這是Caffe2 API的主要思想:使用Python方便地組合網路來訓練你的模型,將這些網路傳遞給C ++程式碼作為序列化的protobuffers,然後讓C ++程式碼以完全的效能執行網路。
 

Executing

現在,當我們定義模型訓練操作符時,我們可以開始執行它來訓練我們的模型。
首先,我們只執行一次param初始化:

workspace.RunNetOnce(m.param_init_net)

請注意,像往常一樣,這實際上會將param_init_net的protobuffer傳遞給C ++執行時以便執行。

然後我們建立實際的training Net:

workspace.CreateNet(m.net)

 

我們建立它一次,然後我們可以多次有效地執行它: 

# Run 100 x 10 iterations
for _ in range(100):
    data = np.random.rand(16, 100).astype(np.float32)
    label = (np.random.rand(16) * 10).astype(np.int32)

    workspace.FeedBlob("data", data)
    workspace.FeedBlob("label", label)

    workspace.RunNet(m.name, 10)   # run for 10 times

注意我們如何將m.name而不是net定義本身傳遞給RunNet()。 由於網路是在工作空間內建立的,因此我們不需要再次傳遞定義。

執行後,您可以檢查儲存在輸出blob(包含張量,即numpy陣列)中的結果:

print(workspace.FetchBlob("softmax"))
print(workspace.FetchBlob("loss"))

 

Backward pass:

這個網路只包含forward pass(前向傳播),因此它不會學習任何東西。 通過在forward pass(前向傳播)中為每個運算子新增梯度運算子來建立backward pass(反向傳播)。
如果您想嘗試此操作,請新增以下步驟並檢查結果!
在呼叫RunNetOnce()之前插入:

m.AddGradientOperators([loss])

檢查protobuf輸出:

print(m.net.Proto())

概述總結結束了,但在教程中還有很多內容,請在tutorials 中進行檢視。 

有關 Forward and Backward(前傳/反傳) 補充

(該內容 來自caffeCn深度學習社群,主要用於記錄 )