如何用Paddle Fluid API搭建簡單的神經網絡?這裡有一份編程指南

2021-01-11 機器之心Pro

PaddlePaddle 是百度自主研發,集深度學習核心框架、工具組件和服務平臺為一體的開源深度學習平臺。該平臺技術領先、功能完備。Paddle Fluid 是 PaddlePaddle 的核心框架,滿足模型開發、訓練、部署的全流程需求。本文將展示如何用 Paddle Fluid API 編程並搭建一個簡單的神經網絡。

本文將介紹:

Paddle Fluid 有哪些核心概念如何在 Paddle Fluid 中定義運算過程如何使用 executor 運行 Paddle Fluid 操作如何從邏輯層對實際問題建模如何調用 API(層,數據集,損失函數,優化方法等等)

使用 Tensor 表示數據

Paddle Fluid 和其它主流框架一樣,使用 Tensor 數據結構來承載數據。Tensor 可以簡單理解成一個多維數組,一般而言可以有任意多的維度。不同的 Tensor 可以具有自己的數據類型和形狀,同一 Tensor 中每個元素的數據類型是一樣的,Tensor 的形狀就是 Tensor 的維度。

下圖直觀地表示 1~6 維的 Tensor:

在 Paddle Fluid 中存在三種特殊的 Tensor:

1. 模型中的可學習參數

模型中的可學習參數(包括網絡權重、偏置等)生存期和整個訓練任務一樣長,會接受優化算法的更新,在 Paddle Fluid 中以 Variable 的子類 Parameter 表示。

在 Paddle Fluid 中可以通過 fluid.layers.create_parameter 來創建可學習參數:

w = fluid.layers.create_parameter(name="w",shape=[1],dtype='float32')

一般情況下,您不需要自己來創建網絡中的可學習參數,Paddle Fluid 為大部分常見的神經網絡基本計算模塊都提供了封裝。以最簡單的全連接模型為例,下面的代碼片段會直接為全連接層創建連接權值(W)和偏置(bias)兩個可學習參數,無需顯式地調用 Parameter 相關接口來創建。

import paddle.fluid as fluidy = fluid.layers.fc(input=x, size=128, bias_attr=True)

2. 輸入輸出 Tensor

整個神經網絡的輸入數據也是一個特殊的 Tensor,在這個 Tensor 中,一些維度的大小在定義模型時無法確定(通常包括:batch size,如果 mini-batch 之間數據可變,也會包括圖片的寬度和高度等),在定義模型時需要佔位。

Paddle Fluid 中使用 fluid.layers.data 來接收輸入數據,fluid.layers.data 需要提供輸入 Tensor 的形狀信息,當遇到無法確定的維度時,相應維度指定為 None 或 -1,如下面的代碼片段所示:

import paddle.fluid as fluid#定義x的維度為[3,None],其中我們只能確定x的第一的維度為3,第二個維度未知,要在程序執行過程中才能確定x = fluid.layers.data(name="x", shape=[3,None], dtype="int64")#batch size無需顯示指定,框架會自動補充第0維為batch size,並在運行時填充正確數值a = fluid.layers.data(name="a",shape=[3,4],dtype='int64')#若圖片的寬度和高度在運行時可變,將寬度和高度定義為None。#shape的三個維度含義分別是:channel、圖片的寬度、圖片的高度b = fluid.layers.data(name="image",shape=[3,None,None],dtype="float32")

其中,dtype="int64" 表示有符號 64 位整數數據類型,更多 Paddle Fluid 目前支持的數據類型請在官網查閱:http://paddlepaddle.org/documentation/docs/zh/1.4/user_guides/howto/prepare_data/feeding_data.html#fluid。

3. 常量 Tensor

Paddle Fluid 通過 fluid.layers.fill_constant 來實現常量 Tensor,用戶可以指定 Tensor 的形狀,數據類型和常量值。代碼實現如下所示:

import paddle.fluid as fluiddata = fluid.layers.fill_constant(shape=[1], value=0, dtype='int64')

需要注意的是,上述定義的 tensor 並不具有值,它們僅表示將要執行的操作,如您直接列印 data 將會得到描述該 data 的一段信息:

print data

輸出結果:

name: "fill_constant_0.tmp_0"type {type: LOD_TENSOR lod_tensor { tensor { data_type: INT64 dims: 1 } }}persistable: false

具體輸出數值將在 Executor 運行時得到,詳細過程會在後文展開描述。

數據傳入

Paddle Fluid 有特定的數據傳入方式:

您需要使用 fluid.layers.data 配置數據輸入層,並在 fluid.Executor 或 fluid.ParallelExecutor 中,使用 executor.run(feed=...) 傳入訓練數據。

具體的數據準備過程,您可以閱讀官網使用指南「準備數據」章節。

使用 Operator 表示對數據的操作

在 Paddle Fluid 中,所有對數據的操作都由 Operator 表示,您可以使用內置指令來描述它們的神經網絡。為了便於用戶使用,在 Python 端,Paddle Fluid 中的 Operator 被一步封裝入 paddle.fluid.layers,paddle.fluid.nets 等模塊。這是因為一些常見的對 Tensor 的操作可能是由更多基礎操作構成,為了提高使用的便利性,框架內部對基礎 Operator 進行了一些封裝,包括創建 Operator 依賴可學習參數,可學習參數的初始化細節等,減少用戶重複開發的成本。例如用戶可以利用 paddle.fluid.layers.elementwise_add() 實現兩個輸入 Tensor 的加法運算:

#定義網絡import paddle.fluid as fluida = fluid.layers.data(name="a",shape=[1],dtype='float32')b = fluid.layers.data(name="b",shape=[1],dtype='float32')result = fluid.layers.elementwise_add(a,b)#定義Exectorcpu = fluid.core.CPUPlace() #定義運算場所,這裡選擇在CPU下訓練exe = fluid.Executor(cpu) #創建執行器exe.run(fluid.default_startup_program()) #網絡參數初始化#準備數據import numpydata_1 = int(input("Please enter an integer: a="))data_2 = int(input("Please enter an integer: b="))x = numpy.array([[data_1]])y = numpy.array([[data_2]])#執行計算outs = exe.run(feed={'a':x,'b':y}, fetch_list=[result.name])#驗證結果print "%d+%d=%d" % (data_1,data_2,outs[0][0])

輸出結果:

a=7b=37+3=10

本次運行時,輸入 a=7,b=3,得到 outs=10。

您可以複製這段代碼在本地執行,根據指示輸入其它數值觀察計算結果。

如果想獲取網絡執行過程中的 a,b 的具體值,可以將希望查看的變量添加在 fetch_list 中。

...#執行計算outs = exe.run(feed={'a':x,'b':y}, fetch_list=[a,b,result.name])#查看輸出結果print outs

輸出結果:

[array([[7]]), array([[3]]), array([[10]])]

使用 Program 描述神經網絡模型

Paddle Fluid 不同於其它大部分深度學習框架,去掉了靜態計算圖的概念,代之以 Program 的形式動態描述計算過程。這種動態的計算描述方式兼具網絡結構修改的靈活性和模型搭建的便捷性,在保證性能的同時極大地提高了框架對模型的表達能力。

開發者的所有 Operator 都將寫入 Program,在 Paddle Fluid 內部將自動轉化為一種叫作 ProgramDesc 的描述語言,Program 的定義過程就像在寫一段通用程序,有開發經驗的用戶在使用 Paddle Fluid 時,會很自然的將自己的知識遷移過來。

其中,Paddle Fluid 通過提供順序、分支和循環三種執行結構的支持,讓用戶可以通過組合描述任意複雜的模型。

順序執行:

用戶可以使用順序執行的方式搭建網絡:

x = fluid.layers.data(name='x',shape=[13], dtype='float32')y_predict = fluid.layers.fc(input=x, size=1, act=None)y = fluid.layers.data(name='y', shape=[1], dtype='float32')cost = fluid.layers.square_error_cost(input=y_predict, label=y)

條件分支——switch、if else:

Paddle Fluid 中有 switch 和 if-else 類來實現條件選擇,用戶可以使用這一執行結構在學習率調節器中調整學習率或其它希望的操作:

lr = fluid.layers.tensor.create_global_var(shape=[1], value=0.0, dtype='float32', persistable=True, name="learning_rate")one_var = fluid.layers.fill_constant(shape=[1], dtype='float32', value=1.0)two_var = fluid.layers.fill_constant(shape=[1], dtype='float32', value=2.0)with fluid.layers.control_flow.Switch() as switch: with switch.case(global_step == zero_var): fluid.layers.tensor.assign(input=one_var, output=lr) with switch.default(): fluid.layers.tensor.assign(input=two_var, output=lr)

關於 Paddle Fluid 中 Program 的詳細設計思想,可以參考閱讀官網進階使用「設計思想」中更多 Fluid 中的控制流,可以參考閱讀 API 文檔。

使用 Executor 執行 Program

Paddle Fluid 的設計思想類似於高級程式語言 C++和 JAVA 等。程序的執行過程被分為編譯和執行兩個階段。用戶完成對 Program 的定義後,Executor 接受這段 Program 並轉化為 C++後端真正可執行的 FluidProgram,這一自動完成的過程叫做編譯。編譯過後需要 Executor 來執行這段編譯好的 FluidProgram。例如上文實現的加法運算,當構建好 Program 後,需要創建 Executor,進行初始化 Program 和訓練 Program:

#定義Exectorcpu = fluid.core.CPUPlace() #定義運算場所,這裡選擇在CPU下訓練exe = fluid.Executor(cpu) #創建執行器exe.run(fluid.default_startup_program()) #用來進行初始化的program#訓練Program,開始計算#feed以字典的形式定義了數據傳入網絡的順序#fetch_list定義了網絡的輸出outs = exe.run(feed={'a':x,'b':y}, fetch_list=[result.name])

代碼實例

您已經對 Paddle Fluid 核心概念有了初步認識了,不妨嘗試配置一個簡單的網絡吧。如果感興趣的話可以跟隨本部分,完成一個非常簡單的數據預測。

從邏輯層面明確了輸入數據格式、模型結構、損失函數以及優化算法後,需要使用 Paddle Fluid 提供的 API 及算子來實現模型邏輯。一個典型的模型主要包含 4 個部分,分別是:輸入數據格式定義,模型前向計算邏輯,損失函數以及優化算法。

1、問題描述

給定一組數據 <X,Y>,求解出函數 f,使得 y=f(x),其中 X,Y 均為一維張量。最終網絡可以依據輸入 x,準確預測出 y_predict。

2、定義數據

假設輸入數據 X=[1 2 3 4],Y=[2,4,6,8],在網絡中定義:

#定義X數值train_data=numpy.array([[1.0],[2.0],[3.0],[4.0]]).astype('float32')#定義期望預測的真實值y_truey_true = numpy.array([[2.0],[4.0],[6.0],[8.0]]).astype('float32')

3、搭建網絡(定義前向計算邏輯)

接下來需要定義預測值與輸入的關係,本次使用一個簡單的線性回歸函數進行預測:

#定義輸入數據類型x = fluid.layers.data(name="x",shape=[1],dtype='float32')#搭建全連接網絡y_predict = fluid.layers.fc(input=x,size=1,act=None)

這樣的網絡就可以進行預測了,雖然輸出結果只是一組隨機數,離預期結果仍相差甚遠:

#加載庫import paddle.fluid as fluidimport numpy#定義數據train_data=numpy.array([[1.0],[2.0],[3.0],[4.0]]).astype('float32')y_true = numpy.array([[2.0],[4.0],[6.0],[8.0]]).astype('float32')#定義預測函數x = fluid.layers.data(name="x",shape=[1],dtype='float32')y_predict = fluid.layers.fc(input=x,size=1,act=None)#參數初始化cpu = fluid.core.CPUPlace()exe = fluid.Executor(cpu)exe.run(fluid.default_startup_program())#開始訓練outs = exe.run(feed={'x':train_data}, fetch_list=[y_predict.name])#觀察結果print outs

輸出結果:

[array([[0.74079144],[1.4815829 ], [2.2223744 ], [2.9631658 ]], dtype=float32)]

4、添加損失函數

完成模型搭建後,如何評估預測結果的好壞呢?我們通常在設計的網絡中添加損失函數,以計算真實值與預測值的差。

在本例中,損失函數採用均方差函數:

cost = fluid.layers.square_error_cost(input=y_predict, label=y)avg_cost = fluid.layers.mean(cost)

輸出一輪計算後的預測值和損失函數:

#加載庫import paddle.fluid as fluidimport numpy#定義數據train_data=numpy.array([[1.0],[2.0],[3.0],[4.0]]).astype('float32')y_true = numpy.array([[2.0],[4.0],[6.0],[8.0]]).astype('float32')#定義網絡x = fluid.layers.data(name="x",shape=[1],dtype='float32')y = fluid.layers.data(name="y",shape=[1],dtype='float32')y_predict = fluid.layers.fc(input=x,size=1,act=None)#定義損失函數cost = fluid.layers.square_error_cost(input=y_predict,label=y)avg_cost = fluid.layers.mean(cost)#參數初始化cpu = fluid.core.CPUPlace()exe = fluid.Executor(cpu)exe.run(fluid.default_startup_program())#開始訓練outs = exe.run(feed={'x':train_data,'y':y_true}, fetch_list=[y_predict.name,avg_cost.name])#觀察結果print outs

輸出結果:

[array([[0.9010564],[1.8021128], [2.7031693], [3.6042256]], dtype=float32), array([9.057577], dtype=float32)]

可以看到第一輪計算後的損失函數為 9.0,仍有很大的下降空間。

5、網絡優化

確定損失函數後,可以通過前向計算得到損失值,然後通過鏈式求導法則得到參數的梯度值。

獲取梯度值後需要更新參數,最簡單的算法是隨機梯度下降法:w=wηg,由 fluid.optimizer.SGD 實現:

sgd_optimizer = fluid.optimizer.SGD(learning_rate=0.01)

讓我們的網絡訓練 100 次,查看結果:

#加載庫import paddle.fluid as fluidimport numpy#定義數據train_data=numpy.array([[1.0],[2.0],[3.0],[4.0]]).astype('float32')y_true = numpy.array([[2.0],[4.0],[6.0],[8.0]]).astype('float32')#定義網絡x = fluid.layers.data(name="x",shape=[1],dtype='float32')y = fluid.layers.data(name="y",shape=[1],dtype='float32')y_predict = fluid.layers.fc(input=x,size=1,act=None)#定義損失函數cost = fluid.layers.square_error_cost(input=y_predict,label=y)avg_cost = fluid.layers.mean(cost)#定義優化方法sgd_optimizer = fluid.optimizer.SGD(learning_rate=0.01)sgd_optimizer.minimize(avg_cost)#參數初始化cpu = fluid.core.CPUPlace()exe = fluid.Executor(cpu)exe.run(fluid.default_startup_program())##開始訓練,迭代100次for i in range(100):outs = exe.run( feed={'x':train_data,'y':y_true}, fetch_list=[y_predict.name,avg_cost.name])#觀察結果print outs

輸出結果:

[array([[2.2075021],[4.1005487], [5.9935956], [7.8866425]], dtype=float32), array([0.01651453], dtype=float32)]

可以看到 100 次迭代後,預測值已經非常接近真實值了,損失值也從初始值 9.05 下降到了 0.01。

至此,恭喜您!已經成功使用 PaddlePaddle 核心框架 Paddle Fluid 搭建了一個簡單網絡。如果您還想嘗試更多,可以從官網繼續閱讀相關的文檔及更多豐富的模型實例。

PaddlePaddle 項目地址:https://github.com/PaddlePaddlePaddlePaddle 官網使用指南地址:http://paddlepaddle.org/documentation/docs/zh/1.4/user_guides/index_cn.html?from=paddlenav

相關焦點

  • PaddlePaddle 2.0.0 Beta 發布,API 體系升級,命令式編程完善
    此外,推理庫的C++接口也做了升級優化,推理庫對量化模型的支持以及推理性能都有了全面增強。訓練框架基礎API兼容性說明 Paddle 2.x版本推薦用戶使用位於paddle根目錄下的API,同時在paddle.fluid目錄下保留了所有的Paddle 1.x版本的API。
  • 520禮包 | 情感分析算法從原理到PaddlePaddle實戰全解
    另外,我們也可使用窗口大小不同的卷積核來處理句子,圖1表示卷積神經網絡文本分類模型,不同顏色表示不同大小的卷積核操作。對於一般的短文本分類問題,上文所述的簡單的文本卷積網絡即可達到很高的正確率[1]。若想得到更抽象更高級的文本特徵表示,可以構建深層文本卷積神經網絡[2,3]。循環神經網絡(RNN)循環神經網絡是一種能對序列數據進行精確建模的有力工具。
  • 用飛槳做自然語言處理:神經網絡語言模型應用實例 - 量子位
    但這種方法會有一個很大的問題,那就是前面提到的維度災難,而這裡要實現的神經網絡語言模型(Neural Network Language Model),便是用神經網絡構建語言模型,通過學習分布式詞表示(即詞向量)的方式解決了這個問題。
  • Python視頻教程網課編程零基礎入門數據分析網絡爬蟲全套Python...
    (1套課程) 數據分析與挖掘(8套課程) 辦公自動化(3套課程) 機器學習與人工智慧(7套課程) 開發實戰篇(4套課程) 量化投資(2套課程) 網絡爬蟲(6套課程) 資料庫操作(1套課程) python高級編程(6套課程) 注:零基礎全能篇中,針對windows和liunx系統均有兩套課程可供選擇學習
  • TensorFlow什麼的都弱爆了,強者只用Numpy搭建神經網絡
    大數據文摘出品作者:蔣寶尚很多同學入門機器學習之後,直接用TensorFlow調包實現神經網絡,對於神經網絡內在機理知之甚少。程式語言與技術框架變化更新非常之快,理解背後的原理才是王道。下面文摘菌和大家一起用Numpy實現一步一步實現神經網絡。
  • 教程| 概率編程:使用貝葉斯神經網絡預測金融市場價格
    本文中,Alex Honchar 介紹了利用概率編程和 Pyro 進行價格預測的方法,相較於常規神經網絡,新方法對於數據的依賴程度更小,結果更準確。在實驗中,作者選擇了最近流行的虛擬貨幣「以太幣」作為實例進行價格預測。去年我曾發表過幾篇有關使用神經網絡進行金融價格預測的教程,我認為其中有一部分結果至少還挺有意思,並且值得在實際交易中加以應用。
  • 逆勢而上的技術:圖神經網絡學習來了!
    要問這幾年一直在逆勢而上的技術有哪些?你一定不會忽略它——圖神經網絡。在實際場景中,有大量的數據是在非歐式空間,限制了深度神經網絡的應用。得益於圖神經網絡在非結構化數據上出色的處理能力,它在學界與工業界上大放光彩。然而,圖神經網絡模型目前仍處於前期高速發展期,面臨著多項方法論和實踐挑戰。
  • 「深度學習被可微分編程取代?」展望30年後的神經網絡和函數編程
    在錯誤的representation中的數據對於神經網絡來說是無意義的。在訓練過程中,相鄰的層會協商它們將要傳遞的representation,網絡的性能取決於網絡所期望的representation中的數據。f層後面跟著一個f。f的輸出表示是f的輸入。在神經網絡架構非常簡單的情況下,只有線性序列的層。
  • 百度發布 Paddle Fluid v1.3 版本,帶來多項重要更新
    新增支持網絡無鎖更新的 Pass。新增 QuantizationTransformPass,此為 Quantization Aware Training 量化模式訓練前的圖修改操作部分。預發布 Calibration 的 3 個核心 Python API(paddle.fluid.contrib.Calibrator)。開發 Calibration 工具,保證 FP32 和 INT8 的精度在 ResNet-50 和 MobileNet-V1 在 ImageNet 驗證數據集上相差在 1% 內。
  • 從小白到大師,這裡有一份Pandas入門指南
    簡單的 Google 搜索和幾秒鐘 Pandas 文檔的閱讀,都會使你的閱讀體驗更加愉快。Pandas 的定義和現狀什麼是 Pandas?Pandas 是一個「開源的、有 BSD 開源協議的庫,它為 Python 程式語言提供了高性能、易於使用的數據架構以及數據分析工具」。
  • 一份完全解讀:是什麼使神經網絡變成圖神經網絡?
    本文將就「為什麼圖有用」、「為什麼很難在圖上定義卷積」、「是什麼使神經網絡成為了圖神經網絡」這些問題進行討論。首先,讓我們簡單回顧一下什麼是圖?圖 G 是由有向或無向邊連接的一組節點(頂點)。節點和邊通常是由專家依據知識經驗或是對問題的直覺進行設置的。
  • 深度學習筆記8:利用Tensorflow搭建神經網絡
    個人公眾號:數據科學家養成記 (微信ID:louwill12)前文傳送門:深度學習筆記1:利用numpy從零搭建一個神經網絡深度學習筆記2:手寫一個單隱層的神經網絡深度學習筆記3:手動搭建深度神經網絡(DNN)深度學習筆記4:深度神經網絡的正則化深度學習筆記5:正則化與
  • 神經網絡算法原理_神經網絡算法的應用_神經網絡算法實例說明
    神經網絡是一種模擬人腦結構的算法模型。其原理就在於將信息分布式存儲和並行協同處理。雖然每個單元的功能非常簡單,但大量單元構成的網絡系統就能實現非常複雜的數據計算,並且還是一個高度複雜的非線性動力學習系統。   神經網絡的結構更接近於人腦,具有大規模並行、分布式存儲和處理、自組織、自適應和自學能力。
  • 飛槳框架高層API,輕鬆玩轉AI
    用製作披薩舉例,一般有兩種方法:一種是我們準備好麵粉、牛奶、火腿等食材,精心加工後,就能製作出美味的披薩;而第二種則是我們買商家預烤制的披薩餅,以及調好的餡料,直接加熱就可以吃到披薩了。那麼這兩種方法有什麼區別呢?
  • 百度Paddle Fluid v1.3版本官方正式發布
    預發布Calibration的3個核心Python API(paddle.fluid.contrib.Calibrator)。開發Calibration工具,保證FP32和INT8的精度在ResNet-50和MobileNet-V1在ImageNet驗證數據集上相差在1%內。
  • 代碼詳解:使用NumPy,教你9步從頭搭建神經網絡
    本文介紹了使用NumPy從頭搭建神經網絡的9個步驟,即從數據預處理到反向傳播這一「必經之路」。對機器學習、人工神經網絡、Python語法和編程邏輯有些基本理解最好,(但這也不是必需條件,你可以邊讀邊學)。1. 初始化導入NumPy。
  • 百度PaddlePaddle聯手Kubernetes,助力開發者高效訓練深度學習模型
    開發者通常會將人工智慧程序與網絡服務、日誌收集器和數據處理器一起聯合部署在同一個通用的集群上,以實現高效的數據流程(data pipelines)。為了管理這個過程,開發者就會用到 Kubernetes 這樣的工具;Kubernetes 是現在最複雜精細的通用集群管理系統之一。
  • 用飛槳做自然語言處理:神經網絡語言模型應用實例
    但這種方法會有一個很大的問題,那就是前面提到的維度災難,而這裡要實現的神經網絡語言模型(Neural Network Language Model),便是用神經網絡構建語言模型,通過學習分布式詞表示(即詞向量)的方式解決了這個問題。
  • 一篇文章教你用11行Python代碼實現神經網絡
    聲明:本文是根據英文教程 (用 11 行 Python 代碼實現的神經網絡)學習總結而來,關於更詳細的神經網絡的介紹可以參考我的另一篇博客:。A Neural Network in 11 lines of Python從感知機到人工神經網絡如果你讀懂了下面的文章,你會對神經網絡有更深刻的認識,有任何問題,請多指教。
  • 入門| Tensorflow實戰講解神經網絡搭建詳細過程
    【IT168 技術】之前我們講了神經網絡的起源、單層神經網絡、多層神經網絡的搭建過程、搭建時要注意到的具體問題、以及解決這些問題的具體方法。本文將通過一個經典的案例:MNIST手寫數字識別,以代碼的形式來為大家梳理一遍神經網絡的整個過程。