动手学PaddlePaddle(1):线性回归
你將學會:
- 機器學習的基本概念:假設函數、損失函數、優化算法
- 數據怎么進行歸一化處理
- paddlepaddle深度學習框架的一些基本知識
- 如何用paddlepaddle深度學習框架搭建全連接神經網絡
參考資料:https://www.paddlepaddle.org.cn/documentation/docs/zh/1.0/beginners_guide/quick_start/fit_a_line/README.cn.html
目錄
1 - 線性回歸的基本概念
2 - 訓練階段
2.1 - 引用庫
2.2 - 數據
2.3 - 配置網絡結構和設置參數
2.4 - 定義損失函數
2.5 - 優化方法
2.6 - 設置訓練場所+創建執行器+參數初始化
2.7 - 開始訓練
3 - 預測階段
1 - 線性回歸的基本概念
在線性回歸中有幾個基本的概念需要掌握:
- 假設函數(Hypothesis Function)
- 損失函數(Loss Function)
- 優化算法(Optimization Algorithm)
假設函數:
假設函數是指,用數學的方法描述自變量和因變量之間的關系,它們之間可以是一個線性函數或非線性函數。 在本次線性回顧模型中,假設函數為 ,其中,表示模型的預測結果(預測房價),用來和真實的Y區分。模型要學習的參數即:a,b。
損失函數:
損失函數是指,用數學的方法衡量假設函數預測結果與真實值之間的誤差。這個差距越小預測越準確,而算法的任務就是使這個差距越來越小。立模型后,我們需要給模型一個優化目標,使得學到的參數能夠讓預測值盡可能地接近真實值Y。輸入任意一個數據樣本的目標值和模型給出的預測值,損失函數輸出一個非負的實值。這個實值通常用來反映模型誤差的大小。對于線性模型來講,最常用的損失函數就是均方誤差(Mean Squared Error, MSE)。
????????????????????????????????????????????????????????????????????
優化算法:
在模型訓練中優化算法也是至關重要的,它決定了一個模型的精度和運算速度。本章的線性回歸實例中主要使用了梯度下降法進行優化。
2 - 訓練階段
2.1 - 引用庫
首先載入需要用到的庫,它們分別是:
paddle.fluid:引入PaddlePaddle深度學習框架的fluid版本庫;
numpy:NumPy是Python語言的一個擴展程序庫。支持高端大量的維度數組與矩陣運算,此外也針對數組運算提供大量的數學函數庫。NumPy的核心功能是"ndarray"(即n-dimensional array,多維數組)數據結構。
os: python的模塊,可使用該模塊對操作系統、目錄、文件等進行操作。
matplotlib.pyplot:用于生成圖,在驗證模型準確率和展示成本變化趨勢時會使用到。
import paddle import paddle.fluid as fluid import numpy as np import os import matplotlib.pyplot as plt2.2 - 數據
BUF_SIZE=500 BATCH_SIZE=20#用于訓練的數據提供器,每次從緩存中隨機讀取批次大小的數據 train_reader = paddle.batch(paddle.reader.shuffle(paddle.dataset.uci_housing.train(), buf_size=BUF_SIZE), batch_size=BATCH_SIZE) #用于測試的數據提供器,每次從緩存中隨機讀取批次大小的數據 test_reader = paddle.batch(paddle.reader.shuffle(paddle.dataset.uci_housing.test(),buf_size=BUF_SIZE),batch_size=BATCH_SIZE)2.3 - 配置網絡結構和設置參數
配置網絡結構:
線性回歸的模型其實就是一個采用線性激活函數(linear activation)的全連接層(fully-connected layer,fc_layer),因此在Paddlepaddle中利用全連接層模型構造線性回歸,這樣一個全連接層就可以看做是一個簡單的神經網絡,只包含輸入層和輸出層即可。本次的模型由于只有一個影響參數,因此輸入只含一個。
輸入層:
用 x = fluid.layers.data(name='x', shape=[13], dtype='float32')來表示數據的一個輸入層,其中name屬性的名稱為"x",數據的shape為13維向量,本次所用的房價數據集的每條數據有13個屬性,所以shape=13。
輸出層:
用y_predict = fluid.layers.fc(input=x, size=1, act=None)來表示輸出層:其中paddle.layer.fc表示全連接層,input=x表示該層輸入數據為x,size=1表示該層有一個神經元,在Fluid版本中使用的激活函數不再是調用一個函數了,而是傳入一個字符串就可以,比如:act='relu'就表示使用relu激活函數。act=None表示激活函數為線性激活函數。
標簽層:
用y = fluid.layers.data(name='y', shape=[1], dtype='float32')來表示標簽數據,名稱為y,有時我們名稱不用y而用label。數據類型為一維向量。
#定義張量變量x,表示13維的特征值 x = fluid.layers.data(name='x', shape=[13], dtype='float32') #定義張量y,表示目標值 y = fluid.layers.data(name='y', shape=[1], dtype='float32') #定義一個簡單的線性網絡,連接輸入和輸出的全連接層 #input:輸入tensor; #size:該層輸出單元的數目 #act:激活函數 y_predict=fluid.layers.fc(input=x,size=1,act=None)2.4 - 定義損失函數
PaddlePaddle提供了很多的損失函數的接口,比如交叉熵損失函數(cross_entropy)。本項目是一個線性回歸任務,所以使用的是均方差損失函數。可以調用fluid.layers.square_error_cost(input= ,laybel= )實現方差計算。因為fluid.layers.square_error_cost(input= ,laybel= )求的是一個Batch的損失值,所以還要通過調用fluid.layers.mean(loss)對方差求平均。
將輸入定義為 房價預測值,label定義為 標簽數據。進而計算損失值。
cost = fluid.layers.square_error_cost(input=y_predict, label=y) #求一個batch的損失值 avg_cost = fluid.layers.mean(cost) #對損失值求平均值2.5 - 優化方法
損失函數定義確定后,需要定義參數優化方法。為了改善模型的訓練速度以及效果,學術界先后提出了很多優化算法,包括: Momentum、RMSProp、Adam 等,已經被封裝在fluid內部,讀者可直接調用。本次可以用 fluid.optimizer.SGD(learning_rate= ) 使用隨機梯度下降的方法優化,其中learning_rate表示學習率,大家可以自己嘗試修改。
optimizer = fluid.optimizer.SGDOptimizer(learning_rate=0.001) opts = optimizer.minimize(avg_cost)fluid有兩個program,一個是default_main_program,一個是default_startup_program;
fluid.default_main_program()用于獲取默認或全局main program(主程序)。該主程序用于訓練和測試模型。fluid.layers 中的所有layer函數可以向 default_main_program 中添加算子和變量。
參數初始化操作會被寫入fluid.default_startup_program();
使用fluid.default_main_program().clone(for_test=True)語句,我們可以克隆一個default_main_program,以備將來測試時使用。
2.6 - 設置訓練場所+創建執行器+參數初始化
設置訓練場所:
首先進行設置訓練使用的設備。也就是選擇是在CPU上進行訓練,還是在GPU上進行訓練。在復雜量較低的時候使用 CPU 就可以完成任務,但是對于大規模計算就需要使用 GPU 訓練。目前 GPU 訓練都是基于 CUDA 工具之上的。
代碼實現也很簡單,我們使用兩行代碼就可以實現,如下面所示:
- use_cuda=False 表示不使用 GPU 進行訓練
創建執行器:
為了能夠運行開發者定義的網絡拓撲結構和優化器,需要定義執行器。由執行器來真正的執行參數的初始化和網絡的訓練過程。fulid使用了一個C++類Executor用于運行一個程序,Executor類似一個解釋器,Fluid將會使用這樣一個解析器來訓練和測試模型。
之后run一下,初始化執行器; 配置完模型后,參數初始化操作會被寫入到 fluid.default_startup_program() 中。 使用 fluid.Executor() 運行 這一程序,即可在全局中隨機初始化參數。
#使用CPU訓練 use_cuda = False place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace() exe = fluid.Executor(place) #創建一個Executor實例exe exe.run(fluid.default_startup_program()) #Executor的run()方法執行startup_program(),進行參數初始化接下來定義映射
輸入網絡的數據要與網絡本身應該接受的數據相匹配。在paddle的 fluid 中使用 feed_list 的概念來保證輸入的數據與網絡接受的數據的順序是一致的。本示例中使用 feed_list = [x,y] 來告知網絡,輸入的數據是分為兩部分,第一部分是 x 值,第二部分是 label 值。
映射完之后,創建 DataFeeder 對象,在訓練的時候,用戶可調用其 feeder.feed(iterable) 方法將用戶傳入的iterable 數據轉換為 LoDTensor。
# 定義feeder feeder = fluid.DataFeeder(place=place, feed_list=[x, y])#feed_list:向模型輸入的變量名2.7 - 開始訓練
iter=0; iters=[] train_costs=[]def plot_train_cost(iters,train_costs):title="training cost"plt.title(title, fontsize=24)plt.xlabel("iter", fontsize=14)plt.ylabel("cost", fontsize=14)plt.plot(iters, train_costs,color='blue',label='training cost') plt.grid()plt.show()EPOCH_NUM=100 model_save_dir = "/home/aistudio/data/model_save_dir/inference.model"for pass_id in range(EPOCH_NUM): #訓練EPOCH_NUM輪# 開始訓練并輸出最后一個batch的損失值train_cost = 0for batch_id, data in enumerate(train_reader()): #遍歷train_reader迭代器train_cost = exe.run(program=fluid.default_main_program(),#運行主程序feed=feeder.feed(data), #喂入一個batch的訓練數據,根據feed_list和data提供的信息,將輸入數據轉成一種特殊的數據結構fetch_list=[avg_cost]) #print("Pass:%d, Cost:%0.5f" % (pass_id, train_cost[0][0])) #打印最后一個batch的損失值iter=iter+BATCH_SIZEiters.append(iter)train_costs.append(train_cost[0][0])# 開始測試并輸出最后一個batch的損失值test_cost = 0for batch_id, data in enumerate(test_reader()): #遍歷test_reader迭代器test_cost= exe.run(program=test_program, #運行測試chengfeed=feeder.feed(data), #喂入一個batch的測試數據fetch_list=[avg_cost]) #fetch均方誤差print('Test:%d, Cost:%0.5f' % (pass_id, test_cost[0][0])) #打印最后一個batch的損失值#保存模型# 如果保存路徑不存在就創建if not os.path.exists(model_save_dir):os.makedirs(model_save_dir)print ('save models to %s' % (model_save_dir))#保存訓練參數到指定路徑中,構建一個專門用預測的programfluid.io.save_inference_model(model_save_dir, #保存推理model的路徑['x'], #推理(inference)需要 feed 的數據[y_predict], #保存推理(inference)結果的 Variablesexe) #exe 保存 inference model plot_train_cost(iters,train_costs)3 - 預測階段
定義一個畫圖的函數,把預測結果展示出來
#先定兩個list,用來存放預測結果、真實值; infer_results=[] groud_truths=[]#繪制真實值和預測值對比圖 def plot_infer_result(groud_truths,infer_results):title='Boston'plt.title(title, fontsize=24)x = np.arange(1,20) y = xplt.plot(x, y)plt.xlabel('ground truth', fontsize=14)plt.ylabel('infer result', fontsize=14)plt.scatter(groud_truths, infer_results,color='red',label='training cost') plt.grid()plt.show() #預測之前,我們需要創建預測用的Executor infer_exe = fluid.Executor(place) #創建推測用的executor inference_scope = fluid.core.Scope() #Scope指定作用域with fluid.scope_guard(inference_scope):#修改全局/默認作用域(scope), 運行時的所有變量都將分配給新的scope。#從指定目錄中加載 預測用的model(inference model)[inference_program, #推理的programfeed_target_names, #需要在推理program中提供數據的變量名稱fetch_targets] = fluid.io.load_inference_model(#fetch_targets: 推斷結果model_save_dir, #model_save_dir:模型訓練路徑 infer_exe) #infer_exe: 預測用executor#獲取預測數據infer_reader = paddle.batch(paddle.dataset.uci_housing.test(), #獲取uci_housing的測試數據batch_size=200) #從測試數據中讀取一個大小為10的batch數據#從test_reader中分割x和labeltest_data = next(infer_reader())test_x = np.array([data[0] for data in test_data]).astype("float32") # 提取測試集中的xtest_y= np.array([data[1] for data in test_data]).astype("float32") # 提取測試集中的labelresults = infer_exe.run(inference_program, #預測模型feed={feed_target_names[0]: np.array(test_x)}, #喂入要預測的x值fetch_list=fetch_targets) #得到推測結果 print("infer results: (House Price)")for idx, val in enumerate(results[0]):print("%d: %.2f" % (idx, val))infer_results.append(val)print("ground truth:")for idx, val in enumerate(test_y):print("%d: %.2f" % (idx, val))groud_truths.append(val)plot_infer_result(groud_truths,infer_results)總結
以上是生活随笔為你收集整理的动手学PaddlePaddle(1):线性回归的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: master.exe是什么进程 有什么用
- 下一篇: linux 使用gzip压缩打包的文件,