詳文帶你使用PaddlePaddle實戰房屋信息預測(入門級)

前言

最近在學習百度PaddlePaddle飛漿深度學習框架,做的第一個例子就是房屋價格預測。儘管官方在實例代碼中做了些講解,但是仍然有很多沒有照顧到的地方。下面,我將通過這個例子,帶大家掌握這個模型。
在這裏插入圖片描述

項目結構

在這裏插入圖片描述
模型:
在這裏插入圖片描述

加載數據

#每次緩存500個數據
BUF_SIZE=500
#每20個組成一個訓練批次
BATCH_SIZE=20
#一次緩存500個數據,其中每次讀取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
)

代碼解析:

  • paddle.reader.shuffle(reader,buf_size)作用:將reader中的數據讀取到緩衝區,讀取數據個數是buf_size。
  • paddle.batch(data,batch_size) 數據打包器,將shuffle方法讀取的數據按照batch_size大小,進行打包。上述例子中,共有404個訓練數據,batch_size=20,共可分得21份(404/20)。

定義模型結構

#定義輸入輸出變量
x = fluid.layers.data(name='x',shape=[13],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,label=y_predict)
avg_cost = fluid.layers.mean(cost)
#定義優化器,這裏使用隨機梯度下降優化器
optimizer = fluid.optimizer.SGDOptimizer(learning_rate=0.01)
opts = optimizer.minimize(avg_cost)
#克隆上述過程。
test_program = fluid.default_main_program().clone(for_test=True)
#創建CPU解釋器
place = fluid.CPUPlace()
exe = fluid.Executor(place)#創建執行器
#初始化參數
exe.run(fluid.default_startup_program())

#向模型輸入變量,轉化成一種特殊的數據結構,可以輸入到Executor
feeder = fluid.DataFeeder(place=place,feed_list=[x,y])

代碼解析:

  • fluid.layers.data(name,shape,dtype)創建一個全局變量,也可以理解爲一個佔位符,在訓練模型得時候通過name進行數據賦值。shape是變量得形狀,dtype是該變量得數據類型。
  • fluid.layers.fc(input,size,act)神經網絡中的全連接層,在此例子中也是作爲預測結果得輸出。size是改連接層大小,act是用於輸出得激活函數。由於我們最終需要預測的是房價,所以這裏size值爲1.
  • fluid.layers.square_error_cost(input,label)預測值和準確值的方差估計,作爲計算誤差的一種方式。Out=(input−label)²
  • fluid.layers.mean(data) paddlepaddle框架自帶的取平均值函數,返回值是data數據的平均值,這裏用來計算每一批數據訓練所得誤差的平均值。
  • fluid.optimizer.SGDOptimizer(learning_rate)隨機梯度下降優化器,參數是學習率。
  • optimizer.minimize()爲網絡添加反向計算過程,並根據反向計算所得的梯度,最小化網絡損失值loss。也就是更新模型中的W權值。
  • fluid.default_main_program().clone(for_test=True)paddle框架採取類似於流程圖的形式。program會記錄用戶定義的操作。這裏將用戶操作進行賦值,用於之後測試。
  • fluid.CPUPlace()指定一個解釋器,我這裏指定的是CPU,當然也可以指定GPU。
  • fluid.Executor(place)創建執行器,這個執行器用於執行program。
  • exe.run(fluid.default_startup_program())執行program。
  • fluid.DataFeeder()向模型輸入變量,轉化成一種特殊的數據結構,可以輸入到Executor。

訓練過程可視化


def draw_train_process(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='red',label='training cost')
    plt.grid()
    plt.show()

代碼解析:

訓練模型

EPOCH_NUM = 30
for pass_id in range(EPOCH_NUM):#遍歷數,也就是訓練次數
    trian_cost=0
    for batch_id,data in enumerate(train_reader()):
        train_cost = exe.run(program=fluid.default_main_program(),
                              feed=feeder.feed(data),#喂數據#這裏對比之前的例子feed={'x':x,'y':y}
                              fetch_list=[avg_cost])#輸出
        if batch_id % 40 ==0:#這裏只是batch_id==0時才觸發。
            print("Pass:%d,Cost:%0.5f" %(pass_id,train_cost[0][0]))
        iter = iter+BATCH_SIZE#記錄訓練次數,用作畫圖
        iters.append(iter)
        train_costs.append(train_cost[0][0])#將損失值保存下來,用於畫圖
    test_cost = 0
    for batch_id,data in enumerate(test_reader()):
        test_cost = exe.run(program=test_program,
                            feed=feeder.feed(data),
                            fetch_list=[avg_cost])
    print('Test:%d,Cost:%0.5f' % (pass_id,test_cost[0][0]))

代碼解析:

  • EPOCH_NUM 定義訓練輪次。
  • enumerate(train_reader())從之前獲取的數據集中,將鍵和值分別的遍歷出來。爲何這裏使用train_reader()而不是train_reader,請看這篇文章:今天終於弄明白了python迭代器是什麼
  • exe.run(program,feed,fetch_list)program 這裏使用的是default_main_program(),這個program存儲着變量和算子。feed是用來傳入參數。這裏使用的是feeder.feed(data)傳入數據。目的是將數據轉化爲一種特殊的結構。fetch_list填入要輸出的值。

保存模型

mode_save_dir="model/house_bosdun.model"
if not os.path.exists(mode_save_dir):#路徑不存在創建路徑
    os.makedirs(mode_save_dir)
print('save models to %s '% (mode_save_dir))
fluid.io.save_inference_model(mode_save_dir,
                                  ['x'],
                                  [y_predict],
                                  exe)

代碼詳情:

  • save_inference_model(dirname,feeded_var_names,target_vars, executor,)第一個參數是保存地址,第二個參數是所有輸入變量的名字,第三個參數是包含所有輸出變量的名字,第四個是用於保存預測模型的執行器

模型導入

infer_exe = fluid.Executor(place)
inference_scope = fluid.core.Scope()
with fluid.scope_guard(inference_scope):#切換作用域
   
    [inference_program,
     feed_target_names,
     fetch_targets] = fluid.io.load_inference_model(mode_save_dir,infer_exe)#參數1地址,參數2執行器(執行引擎)
    infer_reader = paddle.batch(paddle.dataset.uci_housing.test(),batch_size=200)

代碼詳情:

  • with fluid.scope_guard(inference_scope) 切換作用域,這裏切換作用域的原因:防止創建的變量污染全局。說白了,就是爲了使變量爲局部變量。
  • fluid.io.load_inference_model(mode_save_dir,infer_exe)
    參數1模型地址,參數2執行器(執行引擎)。返回的值是, 返回參數1:加載propram(之前描述的程序),參數2:所需要提供的變量名稱,參數3:所有輸出變量。

完整的代碼我就不放了,與官方的基本一致。這裏主要是更加詳細解釋一下一些方法的用法。覺得對你有幫助的話,點個👍吧。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章