Python TensorFlow深度學習回歸代碼:DNNRegressor

来源:https://www.cnblogs.com/fkxxgis/archive/2023/02/02/17085652.html
-Advertisement-
Play Games

本文介紹基於Python語言中TensorFlow的tf.estimator介面,實現深度學習神經網路回歸的具體方法。 () 1 寫在前面 1. 本文介紹的是基於TensorFlow tf.estimator介面的深度學習網路,而非TensorFlow 2.0中常用的Keras介面;關於Keras接 ...


  本文介紹基於Python語言中TensorFlowtf.estimator介面,實現深度學習神經網路回歸的具體方法。

目錄

1 寫在前面

  1. 本文介紹的是基於TensorFlow tf.estimator介面的深度學習網路,而非TensorFlow 2.0中常用的Keras介面;關於Keras介面實現深度學習回歸,我們將在下一篇博客中介紹。

  2. 本文代碼以DNNRegressor回歸為例;而由於基於 tf.estimator介面的深度學習回歸分類整體較為類似,因此二者具有觸類旁通的效果。

  3. 本文第二部分為代碼的分解介紹,第三部分為完整代碼。

  4. 相關版本信息:Python版本:3.8.5TensorFlow版本:2.4.1;編譯器版本:Spyder 4.1.5

2 代碼分解介紹

2.1 準備工作

  首先需要引入相關的庫與包。

import os
import openpyxl
import numpy as np
import pandas as pd
import tensorflow as tf
import scipy.stats as stats
import matplotlib.pyplot as plt
from sklearn import metrics
from sklearn.model_selection import train_test_split

  其次,基於TensorFlow的代碼往往會輸出較多的日誌信息,從而使得我們對代碼執行情況的瞭解受到一定影響。代碼輸出的日誌信息有四種,依據嚴重程度由低到高排序:INFO(通知)<WARNING(警告)<ERROR(錯誤)<FATAL(致命的);我們可以通過如下代碼來對TensorFlow的輸出日誌信息加以約束。

os.environ['TF_CPP_MIN_LOG_LEVEL']='3'

  其中,3代表只輸出FATAL信息。但要註意,這句代碼需要放在import tensorflow的前面:

import os
os.environ['TF_CPP_MIN_LOG_LEVEL']='3'
import openpyxl
import numpy as np
import pandas as pd
import tensorflow as tf
import scipy.stats as stats
import matplotlib.pyplot as plt
from sklearn import metrics
from sklearn.model_selection import train_test_split

2.2 參數配置

  深度學習代碼一大特點即為具有較多的參數需要我們手動定義。為避免調參時上下翻找,我們可以將主要的參數集中在一起,方便我們後期調整。

  其中,具體參數的含義在本文後續部分詳細介紹。

# 將各類變數放在一個位置集中定義,十分有利於機器學習等變數較多的代碼
MyModelPath="G:/CropYield/03_DL/02_DNNModle" # 確定每一次訓練所得模型保存的位置
MyDataPath="G:/CropYield/03_DL/00_Data/AllDataAll.csv" # 確定輸入數據的位置
MyResultSavePath="G:/CropYield/03_DL/03_OtherResult/EvalResult54.xlsx" # 確定模型精度結果(RMSE等)與模型參數保存的位置
TestSize=0.2 # 確定數據中測試集所占比例
RandomSeed=np.random.randint(low=24,high=25) # 確定劃分訓練集與測試集的隨機數種子
OptMethod='Adam' # 確定模型所用的優化方法
LearningRate=0.01 # 確定學習率
DecayStep=200 # 確定學習率下降的步數
DecayRate=0.96 # 確定學習率下降比率
HiddenLayer=[64,128] # 確定隱藏層數量與每一層對應的神經元數量
ActFun='tf.nn.relu' # 確定激活函數
Dropout=0.3 # 確定Dropout的值
LossReduction='tf.compat.v1.ReductionV2.SUM_OVER_BATCH_SIZE' # 指定每個批次訓練誤差的減小方法
BatchNorm='False' # 確定是否使用Batch Normalizing
TrainBatchSize=110 # 確定訓練數據一個Batch的大小
TrainStep=3000 # 確定訓練數據的Step數量
EvalBatchSize=1 # 確定驗證數據一個Batch的大小
PredictBatchSize=1 # 確定預測數據(即測試集)一個Batch的大小

2.3 原有模型刪除

  DNNRegressor每執行一次,便會在指定路徑中保存當前運行的模型。為保證下一次模型保存時不受上一次模型運行結果干擾,我們可以將模型文件夾內的全部文件刪除。

# DeleteOldModel函數,刪除上一次運行所保存的模型
def DeleteOldModel(ModelPath):
    AllFileName=os.listdir(ModelPath) # 獲取ModelPath路徑下全部文件與文件夾
    for i in AllFileName:
        NewPath=os.path.join(ModelPath,i) # 分別將所獲取的文件或文件夾名稱與ModelPath路徑組合
        if os.path.isdir(NewPath): # 若組合後的新路徑是一個文件夾
            DeleteOldModel(NewPath) # 遞歸調用DeleteOldModel函數
        else:
            os.remove(NewPath) # 若不是一個新的文件夾,而是一個文件,那麼就刪除

# 調用DeleteOldModel函數,刪除上一次運行所保存的模型
DeleteOldModel(MyModelPath)

  需要註意,以上代碼僅刪除指定路徑下的文件,文件夾不刪除。大家如果需要將文件夾也同時刪除,修改以上代碼函數中的後面幾句即可。

2.4 數據導入與數據劃分

  我的數據已經保存在了.csv文件中,因此可以用pd.read_csv直接讀取。

  其中,數據的每一列是一個特征,每一行是全部特征與因變數(就是下麵的Yield)組合成的樣本。

# LoadData函數,載入全部數據
def LoadData(DataPath):
    MyData=pd.read_csv(DataPath,names=['EVI0610','EVI0626','EVI0712','EVI0728','EVI0813','EVI0829',
                                       'EVI0914','EVI0930','EVI1016','Lrad06','Lrad07','Lrad08',
                                       'Lrad09','Lrad10','Prec06','Prec07','Prec08','Prec09',
                                       'Prec10','Pres06','Pres07','Pres08','Pres09','Pres10',
                                       'SIF161','SIF177','SIF193','SIF209','SIF225','SIF241',
                                       'SIF257','SIF273','SIF289','Shum06','Shum07','Shum08',
                                       'Shum09','Shum10','SoilType','Srad06','Srad07','Srad08',
                                       'Srad09','Srad10','Temp06','Temp07','Temp08','Temp09',
                                       'Temp10','Wind06','Wind07','Wind08','Wind09','Wind10',
                                       'Yield'],header=0) # 載入DataPath路徑所指定的數據,names中的內容為各列的名稱
    return MyData

# 初始數據處理
AllXY=LoadData(MyDataPath) # 調用LoadData函數,獲取數據
Label={"Yield":AllXY.pop("Yield")} # 將因變數從全部數據中提取出
AllX,AllY=AllXY,(pd.DataFrame(Label)) # 將自變數與因變數分離

# 劃分數據訓練集與測試集
TrainX,TestX,TrainY,TestY=train_test_split(AllX,
                                           AllY,
                                           test_size=TestSize, # 指定數據中測試集所占比例
                                           random_state=RandomSeed # 指定劃分訓練集與測試集的隨機數種子
                                           )

2.5 Feature Columns定義

  Feature Columns就是一個橋梁,聯繫你的初始數據與模型;其好比一個名單,模型拿著這個名單到你的數據(即本文2.4部分你導入的數據)中按列的名稱一一搜索,若初始數據中的某列名稱在Feature Columns里,那麼模型就會把初始數據中這一列的數據全部拿到自己這裡,進行訓練。

  因為我們是希望導入數據的全部特征,那麼可以直接在全部數據的自變數中迴圈,將全部特征的名稱導入Feature Columns

  在這裡需要註意的是,只有連續數值變數才可以用tf.feature_column.numeric_column處理;若是類別變數可以對其加以獨熱編碼等操作。

# estimator介面中的模型需要用“Feature columns”對象作為輸入數據,只有這樣模型才知道讀取哪些數據
FeatureColumn=[] # 定義一個新的“Feature columns”對象
for key in AllX.keys():
    FeatureColumn.append(tf.feature_column.numeric_column(key=key)) # 將全部因變數數據(需要均為連續變數)導入

2.6 模型優化方法構建與模型結構構建

  模型優化方法即模型中的optimizer,其可以在模型結構構建時輸入;但有時優化方法較為複雜(例如引入了學習率下降),那麼在構建模型時配置優化方法的話就會有些不方便。因此我們首先構建模型優化方法。

# 定義模型優化方法
# Optimizer=OptMethod # 優化方法選用OptMethod所指定的方法
Optimizer=lambda:tf.keras.optimizers.Adam(
    learning_rate=tf.compat.v1.train.exponential_decay(learning_rate=LearningRate, # 初始學習率
                                                       global_step=tf.compat.v1.train.get_global_step(),
                                                       # 全局步數,用以計算已經衰減後的學習率
                                                       # get_global_step()函數自動獲取當前的已經執行的步數
                                                       decay_steps=DecayStep, # 學習率下降完成的指定步數
                                                       decay_rate=DecayRate # 衰減率
                                                       ) # 選用基於學習率指數下降的Adam方法,此舉有助於降低過擬合風險
                                                         # 這一函數返回每次對應的學習率
    )

  以上代碼中有兩個Optimizer=,第一個是直接輸入優化方法的名稱即可,名稱包括:'Adagrad', 'Adam', 'Ftrl', 'RMSProp', SGD';預設為Adagrad

  第二個是在選擇了優化方法的基礎上,配置其他信息。例如第二個,其代表著學習率指數下降的Adam優化方法。其中,tf.compat.v1.train.exponential_decay可視作一個計算每次訓練學習率的函數,他返回的是每一次對應的學習率。可能這麼說不太好理解,看這個公式:其返回值為learning_rate *decay_rate ^ (global_step / decay_steps),是不是就明白啦。

  我們選擇第二個優化方法,因此把第一個註釋掉。

  隨後,我們定義模型的結構。

# 基於DNNRegressor構建深度學習模型
DNNModel=tf.estimator.DNNRegressor(feature_columns=FeatureColumn, # 指定模型所用的“Feature columns”對象
                                   hidden_units=HiddenLayer, # 指定隱藏層數量與每一層對應的神經元數量
                                   optimizer=Optimizer, # 指定模型所用的優化方法                                  
                                   activation_fn=eval(ActFun), # 指定激活函數
                                   dropout=Dropout, # 指定Dropout的值
                                   label_dimension=1, # 輸出數據的維度,即因變數的個數
                                   model_dir=MyModelPath, # 指定每一次訓練所得模型保存的位置
                                   # loss_reduction=eval(LossReduction), # 指定每個批次訓練誤差的減小方法
                                   batch_norm=eval(BatchNorm) # 指定是否使用Batch Normalizing
                                   )

  模型的構建,對照著代碼上的註釋,就比較好理解了;其中,我把loss_reduction註釋掉,是因為可能由於TensorFlow版本的問題,其總是報錯,所以就用預設的值就好;而最後一個batch_norm,決定了是否進行Batch NormalizingBatch Normalizing可以保持深度神經網路在每一層保持相同分佈,從而加快網路收斂與增強網路穩固性。

  其它參數可以參考官方網站,這裡暫時不再贅述。

2.7 模型訓練

  訓練模型這一部分,我認為反而比模型的構建可能還難理解一些。我們先看代碼:

# 基於訓練數據訓練模型
DNNModel.train(input_fn=lambda:InputFun(TrainX,
                                        TrainY,
                                        True,
                                        TrainBatchSize
                                        ), # 調用InputFun函數;InputFun函數返回“tf.data.Dataset”對象,這個對象才可以被
                                           # train函數識別並帶入模型;由於InputFun函數每次返回BatchSize大小的數據個數,
                                           # 因此需要多次執行,前面需要加lambda
               steps=TrainStep # 指定模型訓練的步數
               )

  我們可以這麼理解:在train函數中,只有一個參數input_fn;而這個參數的輸入,又是一個新的函數——這個新的函數就是大名鼎鼎的input function了。

  他長這個樣子:

# InputFun函數,訓練數據與驗證數據所用的Input函數
def InputFun(Features,Labels,Training,BatchSize):
    Datasets=tf.data.Dataset.from_tensor_slices((dict(Features),Labels)) # 對數據加以載入
    if Training:
        Datasets=Datasets.shuffle(1000).repeat() # 對於訓練數據,需要打亂(shuffle)、重覆(repeat)
    return Datasets.batch(BatchSize) # 將經過上述處理後的數據以每次BatchSize個輸出

  那我們首先就看input function——也就是代碼中的InputFun函數。其實這個函數的用處很簡單,用官網的話說,其就是用來輸入模型支持的數據類型的——只有經過input function處理後,數據才可以被DNNRegressor識別。聽上去這麼厲害,它到底是如何操作的呢?

  很簡單,它只需要將初始的數據轉換為特定的格式即可,這個格式是一個元組(tuple),這個元組有兩個元素:

  一就是features,是一個字典。這個字典的每一個鍵是每一個特征的名稱,就比如用植物特性對花的種類加以區分,那麼花的“葉長”“葉片厚度”等等就是一個個特征的名稱,也就是這裡的一個個“鍵”;而這個字典的值,就是這個特征對應的全部樣本的數值組成的數組。

  二就是label,是全部樣本對應的label,也就是因變數。

  不知道大家有沒有理解,我們就舉一個簡單的例子。假如我們用兩個地方的溫度與降水預測這兩個地方的作物產量:其溫度分別為10 ℃、20 ℃,降水分別為15 mm,25 mm,作物產量分別為100千克每公頃,150千克每公頃——那麼tuple由兩個部分組成:

tuple=(features,label)
features={'溫度':np.array([10,20]),'降水':np.array([15,25])}
label=np.array([100,150])

  怎麼樣,是不是明白啦。

  理解了之後,我們繼續看InputFun函數。首先,tf.data.Dataset.from_tensor_slices用來將輸入的數據載入並轉換為Datase的形式;隨後,如果是訓練狀態下,那麼數據會進行打亂.shuffle(1000)——相當於對數據加以洗牌,防止初始數據具有一定的趨勢。例如如果我們做分類,其中初始數據的前80%都是第一類,後20%都是第二類,那麼如果我們不打亂數據,會使得用前80%數據訓練出來的結果都是第一類(即模型只認識第一類),在後20%進行測試時,所得結果也全都為第一類;所以要打亂。其中的1000buffer_size參數,這個數據必須要比你的數據樣本個數大。至於.shuffle(1000)這個函數的原理我一直沒有搞明白,大家感興趣的話可以加以進一步瞭解。

  .repeat()則是對數據集加以重覆,之所以要重覆,是因為我們需要對全部數據訓練好幾輪(即好幾個Epoch),因此要對初始數據加以重覆。

  隨後,用.batch()函數輸出BatchSize個數據,也就是一批數據;其中BatchSize就是每一批數據的個數。

  這個就是InputFun函數。再看train函數函數:大家也看出來了,這個InputFun函數是每次輸出一批(BatchSize個)數據;而我們訓練的時候,肯定是要一批一批不停輸入數據的,因此這就解釋了為什麼InputFun函數前有一個lambda——因為InputFun函數要把處理後的數據分多次傳給train

2.8 模型驗證與測試

  理解了以上內容,接下來就好理解多了。我們需要進行驗證與測試的操作——其實驗證也就是利用了測試集數據,之所以我還進行了測試,是因為希望可以獲取測試集預測結果,從而更直觀地瞭解模型精度水平。

# InputFunPredict函數,測試數據所用的Input函數
def InputFunPredict(Features,BatchSize):
    return tf.data.Dataset.from_tensor_slices(dict(Features)).batch(BatchSize) # 對數據加以載入,以每次BatchSize個輸出    

# 驗證模型並保存驗證結果
EvalResult=DNNModel.evaluate(input_fn=lambda:InputFun(TestX,
                                                      TestY,
                                                      False,
                                                      EvalBatchSize
                                                      )
                             )
# 列印驗證結果
print('ev:{}'.format(EvalResult))

# 基於測試數據測試模型精度結果
PredictValues=DNNModel.predict(input_fn=lambda:InputFunPredict(TestX,
                                                               PredictBatchSize
                                                               )
                               )

  其中,驗證時.evaluate所用的InputFun函數其實和訓練集所用的是一樣的函數,只不過驗證時不需要進行打亂.shuffle(1000)和重覆.repeat()操作;而測試時.predictInputFun函數則是新的,其只需要輸入自變數、無需輸入因變數。

2.9 精度評定、擬合圖像繪製與模型參數與精度結果保存

  精度評定與擬合圖像就不用過多說啦~最終,我們最好將模型參數與精度衡量指標結果保存在Excel表格中,這樣子方便之後的調參過程。這裡就不再一一介紹啦,大家對照代碼中的註釋即可。

# AccuracyVerification函數,進行精度驗證指標的計算與繪圖
def AccuracyVerification(PredictLabels,TestLabels):
    value=0
    PredictValuesList=[]
    for k in PredictLabels:
        value=k.get('predictions')[0]
        PredictValuesList.append(value)
    TestLabels=TestLabels.values.tolist()
    TestYList=sum(TestLabels,[])
    # 以上為獲取測試數據的因變數與模型預測所得的因變數
    Pearsonr=stats.pearsonr(TestYList,PredictValuesList) # 計算皮爾遜相關係數
    R2=metrics.r2_score(TestYList,PredictValuesList) # 計算R方
    RMSE=metrics.mean_squared_error(TestYList,PredictValuesList)**0.5 # 計算RMSE
    plt.cla()
    plt.plot(TestYList,PredictValuesList,'r*')
    plt.xlabel('Actual Values')
    plt.ylabel('Predicted Values')
    # 以上為繪製擬合圖像
    print('Pearson correlation coefficient is {0}, and RMSE is {1}.'.format(Pearsonr[0],RMSE))
    return (Pearsonr[0],R2,RMSE,PredictValuesList)

# WriteAccuracy函數,將模型所涉及的參數與最終精度結果保存
def WriteAccuracy(*WriteVar):
    ExcelData=openpyxl.load_workbook(WriteVar[0])
    SheetName=ExcelData.get_sheet_names() # 獲取全部Sheet
    WriteSheet=ExcelData.get_sheet_by_name(SheetName[0]) # 獲取指定Sheet
    WriteSheet=ExcelData.active # 激活指定Sheet
    MaxRowNum=WriteSheet.max_row # 獲取指定Sheet對應第一個空行
    for i in range(len(WriteVar)-1):
        exec("WriteSheet.cell(MaxRowNum+1,i+1).value=WriteVar[i+1]") # 用exec執行語句,寫入信息
    ExcelData.save(WriteVar[0]) # 保存文件

# 調用AccuracyVerification函數,進行精度驗證指標的計算與繪圖
AccuracyResult=AccuracyVerification(PredictValues,TestY)
PearsonR,R2,RMSE,PredictY=AccuracyResult[0],AccuracyResult[1],AccuracyResult[2],AccuracyResult[3]

# 調用WriteAccuracy函數,將模型所涉及的參數與最終精度結果保存
WriteAccuracy(MyResultSavePath,PearsonR,R2,RMSE,TestSize,RandomSeed,OptMethod,LearningRate,DecayStep,
              DecayRate,','.join('%s' %i for i in HiddenLayer),ActFun,Dropout,LossReduction,
              BatchNorm,TrainBatchSize,TrainStep,EvalBatchSize,PredictBatchSize)

  至此,全部的代碼分解介紹都結束啦~

3 詳細代碼

# -*- coding: utf-8 -*-
"""
Created on Tue Feb 23 16:13:21 2021

@author: Chutj
"""

# 載入必要的庫、包等
import os
os.environ['TF_CPP_MIN_LOG_LEVEL']='3'
import openpyxl
import numpy as np
import pandas as pd
import tensorflow as tf
import scipy.stats as stats
import matplotlib.pyplot as plt
from sklearn import metrics
from sklearn.model_selection import train_test_split

# ===============*** 函數聲明區域 ***===============

# DeleteOldModel函數,刪除上一次運行所保存的模型
def DeleteOldModel(ModelPath):
    AllFileName=os.listdir(ModelPath) # 獲取ModelPath路徑下全部文件與文件夾
    for i in AllFileName:
        NewPath=os.path.join(ModelPath,i) # 分別將所獲取的文件或文件夾名稱與ModelPath路徑組合
        if os.path.isdir(NewPath): # 若組合後的新路徑是一個文件夾
            DeleteOldModel(NewPath) # 遞歸調用DeleteOldModel函數
        else:
            os.remove(NewPath) # 若不是一個新的文件夾,而是一個文件,那麼就刪除

# LoadData函數,載入全部數據
def LoadData(DataPath):
    MyData=pd.read_csv(DataPath,names=['EVI0610','EVI0626','EVI0712','EVI0728','EVI0813','EVI0829',
                                       'EVI0914','EVI0930','EVI1016','Lrad06','Lrad07','Lrad08',
                                       'Lrad09','Lrad10','Prec06','Prec07','Prec08','Prec09',
                                       'Prec10','Pres06','Pres07','Pres08','Pres09','Pres10',
                                       'SIF161','SIF177','SIF193','SIF209','SIF225','SIF241',
                                       'SIF257','SIF273','SIF289','Shum06','Shum07','Shum08',
                                       'Shum09','Shum10','SoilType','Srad06','Srad07','Srad08',
                                       'Srad09','Srad10','Temp06','Temp07','Temp08','Temp09',
                                       'Temp10','Wind06','Wind07','Wind08','Wind09','Wind10',
                                       'Yield'],header=0) # 載入DataPath路徑所指定的數據,names中的內容為各列的名稱
    return MyData

# InputFun函數,訓練數據與驗證數據所用的Input函數
def InputFun(Features,Labels,Training,BatchSize):
    Datasets=tf.data.Dataset.from_tensor_slices((dict(Features),Labels)) # 對數據加以載入
    if Training:
        Datasets=Datasets.shuffle(1000).repeat() # 對於訓練數據,需要打亂(shuffle)、重覆(repeat)
    return Datasets.batch(BatchSize) # 將經過上述處理後的數據以每次BatchSize個輸出

# InputFunPredict函數,測試數據所用的Input函數
def InputFunPredict(Features,BatchSize):
    return tf.data.Dataset.from_tensor_slices(dict(Features)).batch(BatchSize) # 對數據加以載入,以每次BatchSize個輸出

# AccuracyVerification函數,進行精度驗證指標的計算與繪圖
def AccuracyVerification(PredictLabels,TestLabels):
    value=0
    PredictValuesList=[]
    for k in PredictLabels:
        value=k.get('predictions')[0]
        PredictValuesList.append(value)
    TestLabels=TestLabels.values.tolist()
    TestYList=sum(TestLabels,[])
    # 以上為獲取測試數據的因變數與模型預測所得的因變數
    Pearsonr=stats.pearsonr(TestYList,PredictValuesList) # 計算皮爾遜相關係數
    R2=metrics.r2_score(TestYList,PredictValuesList) # 計算R方
    RMSE=metrics.mean_squared_error(TestYList,PredictValuesList)**0.5 # 計算RMSE
    plt.cla()
    plt.plot(TestYList,PredictValuesList,'r*')
    plt.xlabel('Actual Values')
    plt.ylabel('Predicted Values')
    # 以上為繪製擬合圖像
    print('Pearson correlation coefficient is {0}, and RMSE is {1}.'.format(Pearsonr[0],RMSE))
    return (Pearsonr[0],R2,RMSE,PredictValuesList)

# WriteAccuracy函數,將模型所涉及的參數與最終精度結果保存
def WriteAccuracy(*WriteVar):
    ExcelData=openpyxl.load_workbook(WriteVar[0])
    SheetName=ExcelData.get_sheet_names() # 獲取全部Sheet
    WriteSheet=ExcelData.get_sheet_by_name(SheetName[0]) # 獲取指定Sheet
    WriteSheet=ExcelData.active # 激活指定Sheet
    MaxRowNum=WriteSheet.max_row # 獲取指定Sheet對應第一個空行
    for i in range(len(WriteVar)-1):
        exec("WriteSheet.cell(MaxRowNum+1,i+1).value=WriteVar[i+1]") # 用exec執行語句,寫入信息
    ExcelData.save(WriteVar[0]) # 保存文件


# ===============*** 代碼由此開始執行 ***===============
#      ++++++++++--- 建議由這裡開始看 ---++++++++++

# 將各類變數放在一個位置集中定義,十分有利於機器學習等變數較多的代碼
MyModelPath="G:/CropYield/03_DL/02_DNNModle" # 確定每一次訓練所得模型保存的位置
MyDataPath="G:/CropYield/03_DL/00_Data/AllDataAll.csv" # 確定輸入數據的位置
MyResultSavePath="G:/CropYield/03_DL/03_OtherResult/EvalResult54.xlsx" # 確定模型精度結果(RMSE等)與模型參數保存的位置
TestSize=0.2 # 確定數據中測試集所占比例
RandomSeed=np.random.randint(low=24,high=25) # 確定劃分訓練集與測試集的隨機數種子
OptMethod='Adam' # 確定模型所用的優化方法
LearningRate=0.01 # 確定學習率
DecayStep=200 # 確定學習率下降的步數
DecayRate=0.96 # 確定學習率下降比率
HiddenLayer=[64,128] # 確定隱藏層數量與每一層對應的神經元數量
ActFun='tf.nn.relu' # 確定激活函數
Dropout=0.3 # 確定Dropout的值
LossReduction='tf.compat.v1.ReductionV2.SUM_OVER_BATCH_SIZE' # 指定每個批次訓練誤差的減小方法
BatchNorm='False' # 確定是否使用Batch Normalizing
TrainBatchSize=110 # 確定訓練數據一個Batch的大小
TrainStep=3000 # 確定訓練數據的Step數量
EvalBatchSize=1 # 確定驗證數據一個Batch的大小
PredictBatchSize=1 # 確定預測數據(即測試集)一個Batch的大小

# 調用DeleteOldModel函數,刪除上一次運行所保存的模型
DeleteOldModel(MyModelPath)

# 初始數據處理
AllXY=LoadData(MyDataPath) # 調用LoadData函數,獲取數據
Label={"Yield":AllXY.pop("Yield")} # 將因變數從全部數據中提取出
AllX,AllY=AllXY,(pd.DataFrame(Label)) # 將自變數與因變數分離

# 劃分數據訓練集與測試集
TrainX,TestX,TrainY,TestY=train_test_split(AllX,
                                           AllY,
                                           test_size=TestSize, # 指定數據中測試集所占比例
                                           random_state=RandomSeed # 指定劃分訓練集與測試集的隨機數種子
                                           )

# estimator介面中的模型需要用“Feature columns”對象作為輸入數據,只有這樣模型才知道讀取哪些數據
FeatureColumn=[] # 定義一個新的“Feature columns”對象
for key in AllX.keys():
    FeatureColumn.append(tf.feature_column.numeric_column(key=key)) # 將全部因變數數據(需要均為連續變數)導入

# 定義模型優化方法
# Optimizer=OptMethod # 優化方法選用OptMethod所指定的方法
Optimizer=lambda:tf.keras.optimizers.Adam(
    learning_rate=tf.compat.v1.train.exponential_decay(learning_rate=LearningRate, # 初始學習率
                                                       global_step=tf.compat.v1.train.get_global_step(),
                                                       # 全局步數,用以計算已經衰減後的學習率
                                                       # get_global_step()函數自動獲取當前的已經執行的步數
                                                       decay_steps=DecayStep, # 學習率下降完成的指定步數
                                                       decay_rate=DecayRate # 衰減率
                                                       ) # 選用基於學習率指數下降的Adam方法,此舉有助於降低過擬合風險
                                                         # 這一函數返回每次對應的學習率
    )


# 基於DNNRegressor構建深度學習模型
DNNModel=tf.estimator.DNNRegressor(feature_columns=FeatureColumn, # 指定模型所用的“Feature columns”對象
                                   hidden_units=HiddenLayer, # 指定隱藏層數量與每一層對應的神經元數量
                                   optimizer=Optimizer, # 指定模型所用的優化方法                                  
                                   activation_fn=eval(ActFun), # 指定激活函數
                                   dropout=Dropout, # 指定Dropout的值
                                   label_dimension=1, # 輸出數據的維度,即因變數的個數
                                   model_dir=MyModelPath, # 指定每一次訓練所得模型保存的位置
                                   # loss_reduction=eval(LossReduction), # 指定每個批次訓練誤差的減小方法
                                   batch_norm=eval(BatchNorm) # 指定是否使用Batch Normalizing
                                   )

# tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.INFO) # 將INFO級別的日誌信息顯示到屏幕

# 基於訓練數據訓練模型
DNNModel.train(input_fn=lambda:InputFun(TrainX,
                                        TrainY,
                                        True,
                                        TrainBatchSize
                                        ), # 調用InputFun函數;InputFun函數返回“tf.data.Dataset”對象,這個對象才可以被
                                           # train函數識別並帶入模型;由於InputFun函數每次返回BatchSize大小的數據個數,
                                           # 因此需要多次執行,前面需要加lambda
               steps=TrainStep # 指定模型訓練的步數
               ) 

# 驗證模型並保存驗證結果
EvalResult=DNNModel.evaluate(input_fn=lambda:InputFun(TestX,
                                                      TestY,
                                                      False,
                                                      EvalBatchSize
                                                      )
                             )
# 列印驗證結果
print('ev:{}'.format(EvalResult))

# 基於測試數據測試模型精度結果
PredictValues=DNNModel.predict(input_fn=lambda:InputFunPredict(TestX,
                                                               PredictBatchSize
                                                               )
                               )

# 調用AccuracyVerification函數,進行精度驗證指標的計算與繪圖
AccuracyResult=AccuracyVerification(PredictValues,TestY)
PearsonR,R2,RMSE,PredictY=AccuracyResult[0],AccuracyResult[1],AccuracyResult[2],AccuracyResult[3]

# 調用WriteAccuracy函數,將模型所涉及的參數與最終精度結果保存
WriteAccuracy(MyResultSavePath,PearsonR,R2,RMSE,TestSize,RandomSeed,OptMethod,LearningRate,DecayStep,
              DecayRate,','.join('%s' %i for i in HiddenLayer),ActFun,Dropout,LossReduction,
              BatchNorm,TrainBatchSize,TrainStep,EvalBatchSize,PredictBatchSize)

  至此,大功告成。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Java版本 JavaSE 標準版,用於桌面程式、控制台等,這是最核心的部分,需要首先學習 JavaME 嵌入式開發,用於家電等(很少用) JavaEE 企業級,用於web、伺服器 一些概念 JDK Java Development Kit,Java開發工具。包含JRE、JVM,且包含一些開發工具( ...
  • 題目描述 給定一個 n 個元素有序的(升序)整型數組 nums 和一個目標值 target ,寫一個函數搜索 nums 中的 target,如果目標值存在返回下標,否則返回 -1。 來源:力扣(LeetCode) 鏈接:https://leetcode.cn/problems/binary-sear ...
  • 第一種:for in girl_dict= {"China": "小美", "Japan": "圖多天光", "Korea": "斯密達美"} for everyKey in girl_dict: print ("key:" + everyKey + "value:" + girl_dict[eve ...
  • Word文檔屬性包括常規、摘要、統計、內容、自定義。其中摘要包括標題、主題、作者、經理、單位、類別、關鍵詞、備註等項目。屬性相當於文檔的名片,可以添加你想要的註釋、說明等。還可以標註版權。 今天就為大家介紹一下,如何通過Java代碼向Word文檔添加文檔屬性。詳情請閱讀以下內容。 將內置文檔屬性添加 ...
  • 顧名思義單調棧就是具有單調性的棧 ==常見模型:找出每個數左邊離它最近的比它大/小的數== 【演算法】 int stk[N],tt = 0; // 棧中存數據 for (int i = 1; i <= n; i ++){ int x; cin >> x; while (tt && stk[tt] >= ...
  • 雙重檢查鎖定與延遲初始化 在 java 程式中,有時候可能需要推遲一些高開銷的對象初始化操作,並且只有在使用這些對象時才進行初始化。此時程式員可能會採用延遲初始化。但要正確實現線程安全的延遲初始化需要一些技巧,否則很容易出現問題。比如,下麵是非線程安全的延遲初始化對象的示例代碼: COPYpubli ...
  • 1. 服務監控三要素^1 服務監控需要滿足的三要素分別如下: 日誌監控 指標監控 請求鏈路追蹤 服務監控只要能滿足這三個要素,基本就能實現我們想要的監控效果。 1.1.主流APM系統^1 APM 系統(Application Performance Management,即應用性能管理)是對企業的應 ...
  • 基礎 我是在ruoyi-vue已經安裝了mybatis-plus的基礎上進行的修改 關於SQLite SQLite 是一個軟體庫,實現了自給自足的、無伺服器的、零配置的、事務性的 SQL 資料庫引擎。 SQLite主頁:https://www.sqlite.org/index.html 1. pom ...
一周排行
    -Advertisement-
    Play Games
  • GoF之工廠模式 @目錄GoF之工廠模式每博一文案1. 簡單說明“23種設計模式”1.2 介紹工廠模式的三種形態1.3 簡單工廠模式(靜態工廠模式)1.3.1 簡單工廠模式的優缺點:1.4 工廠方法模式1.4.1 工廠方法模式的優缺點:1.5 抽象工廠模式1.6 抽象工廠模式的優缺點:2. 總結:3 ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 本章將和大家分享ES的數據同步方案和ES集群相關知識。廢話不多說,下麵我們直接進入主題。 一、ES數據同步 1、數據同步問題 Elasticsearch中的酒店數據來自於mysql資料庫,因此mysql數據發生改變時,Elasticsearch也必須跟著改變,這個就是Elasticsearch與my ...
  • 引言 在我們之前的文章中介紹過使用Bogus生成模擬測試數據,今天來講解一下功能更加強大自動生成測試數據的工具的庫"AutoFixture"。 什麼是AutoFixture? AutoFixture 是一個針對 .NET 的開源庫,旨在最大程度地減少單元測試中的“安排(Arrange)”階段,以提高 ...
  • 經過前面幾個部分學習,相信學過的同學已經能夠掌握 .NET Emit 這種中間語言,並能使得它來編寫一些應用,以提高程式的性能。隨著 IL 指令篇的結束,本系列也已經接近尾聲,在這接近結束的最後,會提供幾個可供直接使用的示例,以供大伙分析或使用在項目中。 ...
  • 當從不同來源導入Excel數據時,可能存在重覆的記錄。為了確保數據的準確性,通常需要刪除這些重覆的行。手動查找並刪除可能會非常耗費時間,而通過編程腳本則可以實現在短時間內處理大量數據。本文將提供一個使用C# 快速查找並刪除Excel重覆項的免費解決方案。 以下是實現步驟: 1. 首先安裝免費.NET ...
  • C++ 異常處理 C++ 異常處理機制允許程式在運行時處理錯誤或意外情況。它提供了捕獲和處理錯誤的一種結構化方式,使程式更加健壯和可靠。 異常處理的基本概念: 異常: 程式在運行時發生的錯誤或意外情況。 拋出異常: 使用 throw 關鍵字將異常傳遞給調用堆棧。 捕獲異常: 使用 try-catch ...
  • 優秀且經驗豐富的Java開發人員的特征之一是對API的廣泛瞭解,包括JDK和第三方庫。 我花了很多時間來學習API,尤其是在閱讀了Effective Java 3rd Edition之後 ,Joshua Bloch建議在Java 3rd Edition中使用現有的API進行開發,而不是為常見的東西編 ...
  • 框架 · 使用laravel框架,原因:tp的框架路由和orm沒有laravel好用 · 使用強制路由,方便介面多時,分多版本,分文件夾等操作 介面 · 介面開發註意欄位類型,欄位是int,查詢成功失敗都要返回int(對接java等強類型語言方便) · 查詢介面用GET、其他用POST 代碼 · 所 ...
  • 正文 下午找企業的人去鎮上做貸後。 車上聽同事跟那個司機對罵,火星子都快出來了。司機跟那同事更熟一些,連我在內一共就三個人,同事那一手指桑罵槐給我都聽愣了。司機也是老社會人了,馬上聽出來了,為那個無辜的企業經辦人辯護,實際上是為自己辯護。 “這個事情你不能怪企業。”“但他們總不能讓銀行的人全權負責, ...