使用OneFlow搭建神经网络
使用OneFlow搭建神經(jīng)網(wǎng)絡(luò)
在 識別 MNIST 手寫體數(shù)字 的例子中,通過 flow.layers 和 flow.nn 中提供的接口搭建了一個簡單的 LeNet 網(wǎng)絡(luò)。下面,將通過LeNet來介紹 Onflow 中網(wǎng)絡(luò)搭建的核心元素—算子(op)和層(layer)。
LeNet 是一個主要由卷積層、池化層和全連接層組成的神經(jīng)網(wǎng)絡(luò)。
上圖中有兩類元素,一類是方框代表的運(yùn)算單元,包括 op 和 layer 兩類,比如 conv2d 、 dense 、 max_pool2d 等;一類是箭頭代表的數(shù)據(jù)。對應(yīng)了以下代碼:
def lenet(data, train=False):
initializer = flow.truncated_normal(0.1)
conv1 = flow.layers.conv2d(
data,
32,
5,
padding=“SAME”,
activation=flow.nn.relu,
name=“conv1”,
kernel_initializer=initializer,
)
pool1 = flow.nn.max_pool2d(
conv1, ksize=2, strides=2, padding=“SAME”, name=“pool1”, data_format=“NCHW”
)
conv2 = flow.layers.conv2d(
pool1,
64,
5,
padding=“SAME”,
activation=flow.nn.relu,
name=“conv2”,
kernel_initializer=initializer,
)
pool2 = flow.nn.max_pool2d(
conv2, ksize=2, strides=2, padding=“SAME”, name=“pool2”, data_format=“NCHW”
)
reshape = flow.reshape(pool2, [pool2.shape[0], -1])
hidden = flow.layers.dense(
reshape,
512,
activation=flow.nn.relu,
kernel_initializer=initializer,
name=“dense1”,
)
if train:
hidden = flow.nn.dropout(hidden, rate=0.5, name=“dropout”)
return flow.layers.dense(hidden, 10, kernel_initializer=initializer, name=“dense2”)
作業(yè)函數(shù)運(yùn)行時,data 是形狀為 100x1×28×28 的數(shù)據(jù),data 首先作為 conv2d 的輸入?yún)⑴c卷積計(jì)算,得到計(jì)算結(jié)果conv1 ,然后 conv1 作為輸入傳給 max_pool2d ,依此類推。
op 和 layer
算子(Op)是比較常用的一種概念,是 OneFlow 中基本的運(yùn)算單元,上文代碼中的 reshape 和 nn.max_pool2d 就是兩種算子。
layers.conv2d 和 layers.dense 不是基本的運(yùn)算單元,由算子組合成的特定的運(yùn)算層(layer)。層的存在使得搭建神經(jīng)網(wǎng)絡(luò)更方便,相關(guān)接口使用請參考 oneflow.layers API。
通過閱讀 oneflow.layers 源碼 ,可以學(xué)習(xí)由基本算子構(gòu)建運(yùn)算層的細(xì)節(jié)。
網(wǎng)絡(luò)構(gòu)建過程中的數(shù)據(jù)塊
OneFlow 默認(rèn)模式是靜態(tài)圖機(jī)制,網(wǎng)絡(luò)的構(gòu)建和運(yùn)行過程其實(shí)是分開的。因此,在定義網(wǎng)絡(luò)時,各個變量中 并沒有 真實(shí)的數(shù)據(jù),只是數(shù)據(jù)的占位符。對于真實(shí)數(shù)據(jù)的計(jì)算發(fā)生在作業(yè)函數(shù)的調(diào)用過程中。
在構(gòu)建網(wǎng)絡(luò)時,只是描述了網(wǎng)絡(luò)中各個節(jié)點(diǎn)的性質(zhì)、形狀(如 shape、dtype)與連接關(guān)系等,這些節(jié)點(diǎn)中沒有具體的數(shù)值,僅僅只是 數(shù)據(jù)占位符, OneFlow 可以根據(jù)這種數(shù)據(jù)占位符進(jìn)行編譯推理,得到計(jì)算圖。
這種數(shù)據(jù)占位符在 OneFlow 的語境中被稱作 Blob ,在 OneFlow 中有對應(yīng)的基類 BlobDef。
搭建網(wǎng)絡(luò)時可以打印 Blob 的屬性,比如以下代碼打印 conv1 的 shape 和 dtype :
print(conv1.shape, conv1.dtype)
Blob 的運(yùn)算符重載 BlobDef 中定義了運(yùn)算符重載,也就是說,BlobDef 對象之間可以進(jìn)行加減乘除等操作。
例如下面這句代碼中的加號:
output = output + fc2_biases
這句代碼等價于:
output = flow.broadcast_add(output, fc2_biases)
總結(jié)
使用 OneFlow 進(jìn)行神經(jīng)網(wǎng)絡(luò)搭建,需要 OneFlow 提供的算子或?qū)幼鳛橛?jì)算單元。數(shù)據(jù)占位符 Blob 作為算子和層的輸入和輸出,運(yùn)算符重載幫助簡化了部分語句。
OneFlow 提供的算子可以參閱 API 文檔中的:oneflow.nn、oneflow.math、oneflow.layers 等模塊。
總結(jié)
以上是生活随笔為你收集整理的使用OneFlow搭建神经网络的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。