Caffe2的相關概念
接下來你可以學到更多Caffe2中主要的概念,這些概念對理解和開發Caffe2相當重要。
Blobs and Workspace,Tensors
Caffe2中,數據是用blobs儲存的。Blob只是內存中的一個數據塊。大多數Blobs包含一個張量(tensor),可以理解為多維矩陣,在Python中,他們被轉換為numpy 矩陣。
? Workspace
保存著所有的Blobs
。下面的例子展示了如何向Workspace
中傳遞Blobs
和取出他們。Workspace
在你開始使用他們時,才進行初始化。
# 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中最基本的對象是net
,net
可以說是一系列Operators
的集合,每個Operator
根據輸入的blob
輸出一個或者多個blob
。
? 下面我們將會創建一個超級簡單的模型。他擁有如下部件:
- 一個全連接層
- 一個
Sigmoid
激活函數和一個Softmax
函數 - 一個交叉損失
? 直接構建網絡是很厭煩的,所以最好使用Python接口的模型助手來構建網絡。我們只需簡單的調用CNNModelHelper
,他就會幫我們創建兩個想聯系的網絡。 - 一個用于初始化參數(
ref.init_net
) - 一個用于實際訓練(
ref.init_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)
# Create model using a model helper
m = cnn.CNNModelHelper(name="my first net")
fc_1 = m.FC("data", "fc1", dim_in=100, dim_out=10)
pred = m.Sigmoid(fc_1, "pred")
[softmax, loss] = m.SoftmaxWithLoss([pred, "label"], ["softmax", "loss"])
上面的代碼中,我們首先在內存中創建了輸入數據和標簽,實際使用中,往往從database
等載體中讀入數據。可以看到輸入數據和標簽的第一維度是16
,這是因為輸入的最小batch
最小是16
。Caffe2中很多Operator
都能直接通過CNNModelHelper
來進行,并且能夠一次處理一個batch
。CNNModelHelper’s Operator List中有更詳細的解析。
? 第二,我們通過一些操作創建了一個模型。比如FC
,Sigmoid
,SoftmaxWithLoss
。注意:這個時候,這些操作并沒有真正執行,他們僅僅是對模型進行了定義。
? 模型助手創建了兩個網絡:m.param_init_net
,這個網絡將僅僅被執行一次。他將會初始化參數blob
,例如全連接層的權重。真正的訓練是通過執行m.net
來是現實的。這是自動發生的。
? 網絡的定義保存在一個protobuf
結構體中。你可以很容易的通過調用net.proto
來查看它。
print(str(m.net.Proto()))
輸出如下:
name: "my first net"
op {
input: "data"
input: "fc1_w"
input: "fc1_b"
output: "fc1"
name: ""
type: "FC"
}
op {
input: "fc1"
output: "pred"
name: ""
type: "Sigmoid"
}
op {
input: "pred"
input: "label"
output: "softmax"
output: "loss"
name: ""
type: "SoftmaxWithLoss"
}
external_input: "data"
external_input: "fc1_w"
external_input: "fc1_b"
external_input: "label"
同時,你也可以查看參數初始化網絡:
print(str(m.param_init_net.Proto()))
這就是Caffe2的API:使用Python接口方便快速的構建網絡并訓練你的模型,Python接口將這些網絡通過序列化的protobuf
傳遞給C++接口,然后C++接口全力的執行。
Executing
現在我們可以開始訓練我們的模型。
? 首先,我們先跑一次參數初始化網絡。
workspace.RunNetOnce(m.param_init_net)
這個操作將會把param_init_net
的protobuf
傳遞給C++代碼進行執行。
? 然后我們真正的創建網絡:
workspace.CreateNet(m.net)
一旦創建好網絡,我們就可以高效的跑起來:
# Run 100 x 10 iterations 跑100*10次迭代
for j in range(0, 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 跑十次
這里要注意的是我們怎樣在RunNet()
函數中使用網絡的名字。并且在這里,由于網絡已經在workspace
中創建,所以我們不需要再傳遞網絡的定義。執行完后,你可以查看存在輸出blob
中的結果。
print(workspace.FetchBlob("softmax"))
print(workspace.FetchBlob("loss"))
Backward pass
上面的網絡中,僅僅包含了網絡的前向傳播,因此它是學習不到任何東西的。后向傳播對每一個前向傳播進行gradient operator
。如果你想自己嘗試這樣的操作,那么你可以進行以下操作并檢查結果。
? 在RunNetOnce()
前,插入下面操作:
m.AddGradientOperators([loss])
然后測試protobuf
的輸出:
print(str(m.net.Proto()))
以上就是大體的使用教程
譯者注:
訓練過程可以總結為以下步驟:
# Create model using a model helper
m = cnn.CNNModelHelper(name="my first net")
fc_1 = m.FC("data", "fc1", dim_in=100, dim_out=10)
pred = m.Sigmoid(fc_1, "pred")
[softmax, loss] = m.SoftmaxWithLoss([pred, "label"], ["softmax", "loss"])
m.AddGradientOperators([loss]) #注意這一行代碼
workspace.RunNetOnce(m.param_init_net)
workspace.CreateNet(m.net)
# Run 100 x 10 iterations
for j in range(0, 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
結語:
轉載請注明出處:http://www.lxweimin.com/c/cf07b31bb5f2