亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Python基于TensorFlow接口實(shí)現(xiàn)深度學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)回歸

 更新時(shí)間:2023年02月17日 14:15:46   作者:瘋狂學(xué)習(xí)GIS  
這篇文章主要為大家詳細(xì)介紹了如何基于Python語(yǔ)言中TensorFlow的tf.estimator接口,實(shí)現(xiàn)深度學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)回歸的具體方法,感興趣的可以了解一下

1 寫在前面

1. 本文介紹的是基于TensorFlow tf.estimator接口的深度學(xué)習(xí)網(wǎng)絡(luò),而非TensorFlow 2.0中常用的Keras接口;關(guān)于Keras接口實(shí)現(xiàn)深度學(xué)習(xí)回歸,我們將在下一篇博客中介紹。

2. 本文代碼以DNNRegressor回歸為例;而由于基于 tf.estimator接口的深度學(xué)習(xí)回歸分類整體較為類似,因此二者具有觸類旁通的效果。

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

4. 相關(guān)版本信息:

  • Python版本:3.8.5;
  • TensorFlow版本:2.4.1;
  • 編譯器版本:Spyder 4.1.5

2 代碼分解介紹

2.1 準(zhǔn)備工作

首先需要引入相關(guān)的庫(kù)與包。

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的代碼往往會(huì)輸出較多的日志信息,從而使得我們對(duì)代碼執(zhí)行情況的了解受到一定影響。代碼輸出的日志信息有四種,依據(jù)嚴(yán)重程度由低到高排序:INFO(通知)<WARNING(警告)<ERROR(錯(cuò)誤)<FATAL(致命的);我們可以通過如下代碼來(lái)對(duì)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 參數(shù)配置

深度學(xué)習(xí)代碼一大特點(diǎn)即為具有較多的參數(shù)需要我們手動(dòng)定義。為避免調(diào)參時(shí)上下翻找,我們可以將主要的參數(shù)集中在一起,方便我們后期調(diào)整。

其中,具體參數(shù)的含義在本文后續(xù)部分詳細(xì)介紹。

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

2.3 原有模型刪除

DNNRegressor每執(zhí)行一次,便會(huì)在指定路徑中保存當(dāng)前運(yùn)行的模型。為保證下一次模型保存時(shí)不受上一次模型運(yùn)行結(jié)果干擾,我們可以將模型文件夾內(nèi)的全部文件刪除。

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

# 調(diào)用DeleteOldModel函數(shù),刪除上一次運(yùn)行所保存的模型
DeleteOldModel(MyModelPath)

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

2.4 數(shù)據(jù)導(dǎo)入與數(shù)據(jù)劃分

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

其中,數(shù)據(jù)的每一列是一個(gè)特征,每一行是全部特征與因變量(就是下面的Yield)組合成的樣本。

# LoadData函數(shù),加載全部數(shù)據(jù)
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路徑所指定的數(shù)據(jù),names中的內(nèi)容為各列的名稱
    return MyData

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

# 劃分?jǐn)?shù)據(jù)訓(xùn)練集與測(cè)試集
TrainX,TestX,TrainY,TestY=train_test_split(AllX,
                                           AllY,
                                           test_size=TestSize, # 指定數(shù)據(jù)中測(cè)試集所占比例
                                           random_state=RandomSeed # 指定劃分訓(xùn)練集與測(cè)試集的隨機(jī)數(shù)種子
                                           )

2.5 Feature Columns定義

Feature Columns就是一個(gè)橋梁,聯(lián)系你的初始數(shù)據(jù)與模型;其好比一個(gè)名單,模型拿著這個(gè)名單到你的數(shù)據(jù)(即本文2.4部分你導(dǎo)入的數(shù)據(jù))中按列的名稱一一搜索,若初始數(shù)據(jù)中的某列名稱在Feature Columns里,那么模型就會(huì)把初始數(shù)據(jù)中這一列的數(shù)據(jù)全部拿到自己這里,進(jìn)行訓(xùn)練。

因?yàn)槲覀兪窍M麑?dǎo)入數(shù)據(jù)的全部特征,那么可以直接在全部數(shù)據(jù)的自變量中循環(huán),將全部特征的名稱導(dǎo)入Feature Columns。

在這里需要注意的是,只有連續(xù)數(shù)值變量才可以用tf.feature_column.numeric_column處理;若是類別變量可以對(duì)其加以獨(dú)熱編碼等操作。

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

2.6 模型優(yōu)化方法構(gòu)建與模型結(jié)構(gòu)構(gòu)建

模型優(yōu)化方法即模型中的optimizer,其可以在模型結(jié)構(gòu)構(gòu)建時(shí)輸入;但有時(shí)優(yōu)化方法較為復(fù)雜(例如引入了學(xué)習(xí)率下降),那么在構(gòu)建模型時(shí)配置優(yōu)化方法的話就會(huì)有些不方便。因此我們首先構(gòu)建模型優(yōu)化方法。

# 定義模型優(yōu)化方法
# Optimizer=OptMethod # 優(yōu)化方法選用OptMethod所指定的方法
Optimizer=lambda:tf.keras.optimizers.Adam(
    learning_rate=tf.compat.v1.train.exponential_decay(learning_rate=LearningRate, # 初始學(xué)習(xí)率
                                                       global_step=tf.compat.v1.train.get_global_step(),
                                                       # 全局步數(shù),用以計(jì)算已經(jīng)衰減后的學(xué)習(xí)率
                                                       # get_global_step()函數(shù)自動(dòng)獲取當(dāng)前的已經(jīng)執(zhí)行的步數(shù)
                                                       decay_steps=DecayStep, # 學(xué)習(xí)率下降完成的指定步數(shù)
                                                       decay_rate=DecayRate # 衰減率
                                                       ) # 選用基于學(xué)習(xí)率指數(shù)下降的Adam方法,此舉有助于降低過擬合風(fēng)險(xiǎn)
                                                         # 這一函數(shù)返回每次對(duì)應(yīng)的學(xué)習(xí)率
    )

以上代碼中有兩個(gè)Optimizer=,第一個(gè)是直接輸入優(yōu)化方法的名稱即可,名稱包括:'Adagrad''Adam''Ftrl''RMSProp'SGD';默認(rèn)為Adagrad。

第二個(gè)是在選擇了優(yōu)化方法的基礎(chǔ)上,配置其他信息。例如第二個(gè),其代表著學(xué)習(xí)率指數(shù)下降的Adam優(yōu)化方法。其中,tf.compat.v1.train.exponential_decay可視作一個(gè)計(jì)算每次訓(xùn)練學(xué)習(xí)率的函數(shù),他返回的是每一次對(duì)應(yīng)的學(xué)習(xí)率??赡苓@么說(shuō)不太好理解,看這個(gè)公式:其返回值為learning_rate *decay_rate ^ (global_step / decay_steps),是不是就明白啦。

我們選擇第二個(gè)優(yōu)化方法,因此把第一個(gè)注釋掉。

隨后,我們定義模型的結(jié)構(gòu)。

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

模型的構(gòu)建,對(duì)照著代碼上的注釋,就比較好理解了;其中,我把loss_reduction注釋掉,是因?yàn)榭赡苡捎?strong>TensorFlow版本的問題,其總是報(bào)錯(cuò),所以就用默認(rèn)的值就好;而最后一個(gè)batch_norm,決定了是否進(jìn)行Batch Normalizing。Batch Normalizing可以保持深度神經(jīng)網(wǎng)絡(luò)在每一層保持相同分布,從而加快網(wǎng)絡(luò)收斂與增強(qiáng)網(wǎng)絡(luò)穩(wěn)固性。

其它參數(shù)可以參考官方網(wǎng)站,這里暫時(shí)不再贅述。

2.7 模型訓(xùn)練

訓(xùn)練模型這一部分,我認(rèn)為反而比模型的構(gòu)建可能還難理解一些。我們先看代碼:

# 基于訓(xùn)練數(shù)據(jù)訓(xùn)練模型
DNNModel.train(input_fn=lambda:InputFun(TrainX,
                                        TrainY,
                                        True,
                                        TrainBatchSize
                                        ), # 調(diào)用InputFun函數(shù);InputFun函數(shù)返回“tf.data.Dataset”對(duì)象,這個(gè)對(duì)象才可以被
                                           # train函數(shù)識(shí)別并帶入模型;由于InputFun函數(shù)每次返回BatchSize大小的數(shù)據(jù)個(gè)數(shù),
                                           # 因此需要多次執(zhí)行,前面需要加lambda
               steps=TrainStep # 指定模型訓(xùn)練的步數(shù)
               )

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

他長(zhǎng)這個(gè)樣子:

# InputFun函數(shù),訓(xùn)練數(shù)據(jù)與驗(yàn)證數(shù)據(jù)所用的Input函數(shù)
def InputFun(Features,Labels,Training,BatchSize):
    Datasets=tf.data.Dataset.from_tensor_slices((dict(Features),Labels)) # 對(duì)數(shù)據(jù)加以加載
    if Training:
        Datasets=Datasets.shuffle(1000).repeat() # 對(duì)于訓(xùn)練數(shù)據(jù),需要打亂(shuffle)、重復(fù)(repeat)
    return Datasets.batch(BatchSize) # 將經(jīng)過上述處理后的數(shù)據(jù)以每次BatchSize個(gè)輸出

那我們首先就看input function——也就是代碼中的InputFun函數(shù)。其實(shí)這個(gè)函數(shù)的用處很簡(jiǎn)單,用官網(wǎng)的話說(shuō),其就是用來(lái)輸入模型支持的數(shù)據(jù)類型的——只有經(jīng)過input function處理后,數(shù)據(jù)才可以被DNNRegressor識(shí)別。聽上去這么厲害,它到底是如何操作的呢?

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

一就是features,是一個(gè)字典。這個(gè)字典的每一個(gè)鍵是每一個(gè)特征的名稱,就比如用植物特性對(duì)花的種類加以區(qū)分,那么花的“葉長(zhǎng)”“葉片厚度”等等就是一個(gè)個(gè)特征的名稱,也就是這里的一個(gè)個(gè)“鍵”;而這個(gè)字典的值,就是這個(gè)特征對(duì)應(yīng)的全部樣本的數(shù)值組成的數(shù)組。

二就是label,是全部樣本對(duì)應(yīng)的label,也就是因變量。

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

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

怎么樣,是不是明白啦。

理解了之后,我們繼續(xù)看InputFun函數(shù)。首先,tf.data.Dataset.from_tensor_slices用來(lái)將輸入的數(shù)據(jù)加載并轉(zhuǎn)換為Datase的形式;隨后,如果是訓(xùn)練狀態(tài)下,那么數(shù)據(jù)會(huì)進(jìn)行打亂.shuffle(1000)——相當(dāng)于對(duì)數(shù)據(jù)加以洗牌,防止初始數(shù)據(jù)具有一定的趨勢(shì)。例如如果我們做分類,其中初始數(shù)據(jù)的前80%都是第一類,后20%都是第二類,那么如果我們不打亂數(shù)據(jù),會(huì)使得用前80%數(shù)據(jù)訓(xùn)練出來(lái)的結(jié)果都是第一類(即模型只認(rèn)識(shí)第一類),在后20%進(jìn)行測(cè)試時(shí),所得結(jié)果也全都為第一類;所以要打亂。其中的1000buffer_size參數(shù),這個(gè)數(shù)據(jù)必須要比你的數(shù)據(jù)樣本個(gè)數(shù)大。至于.shuffle(1000)這個(gè)函數(shù)的原理我一直沒有搞明白,大家感興趣的話可以加以進(jìn)一步了解。

.repeat()則是對(duì)數(shù)據(jù)集加以重復(fù),之所以要重復(fù),是因?yàn)槲覀冃枰獙?duì)全部數(shù)據(jù)訓(xùn)練好幾輪(即好幾個(gè)Epoch),因此要對(duì)初始數(shù)據(jù)加以重復(fù)。

隨后,用.batch()函數(shù)輸出BatchSize個(gè)數(shù)據(jù),也就是一批數(shù)據(jù);其中BatchSize就是每一批數(shù)據(jù)的個(gè)數(shù)。

這個(gè)就是InputFun函數(shù)。再看train函數(shù)函數(shù):大家也看出來(lái)了,這個(gè)InputFun函數(shù)是每次輸出一批(BatchSize個(gè))數(shù)據(jù);而我們訓(xùn)練的時(shí)候,肯定是要一批一批不停輸入數(shù)據(jù)的,因此這就解釋了為什么InputFun函數(shù)前有一個(gè)lambda——因?yàn)?code>InputFun函數(shù)要把處理后的數(shù)據(jù)分多次傳給train。

2.8 模型驗(yàn)證與測(cè)試

理解了以上內(nèi)容,接下來(lái)就好理解多了。我們需要進(jìn)行驗(yàn)證與測(cè)試的操作——其實(shí)驗(yàn)證也就是利用了測(cè)試集數(shù)據(jù),之所以我還進(jìn)行了測(cè)試,是因?yàn)橄M梢垣@取測(cè)試集預(yù)測(cè)結(jié)果,從而更直觀地了解模型精度水平。

# InputFunPredict函數(shù),測(cè)試數(shù)據(jù)所用的Input函數(shù)
def InputFunPredict(Features,BatchSize):
    return tf.data.Dataset.from_tensor_slices(dict(Features)).batch(BatchSize) # 對(duì)數(shù)據(jù)加以加載,以每次BatchSize個(gè)輸出    

# 驗(yàn)證模型并保存驗(yàn)證結(jié)果
EvalResult=DNNModel.evaluate(input_fn=lambda:InputFun(TestX,
                                                      TestY,
                                                      False,
                                                      EvalBatchSize
                                                      )
                             )
# 打印驗(yàn)證結(jié)果
print('ev:{}'.format(EvalResult))

# 基于測(cè)試數(shù)據(jù)測(cè)試模型精度結(jié)果
PredictValues=DNNModel.predict(input_fn=lambda:InputFunPredict(TestX,
                                                               PredictBatchSize
                                                               )
                               )

其中,驗(yàn)證時(shí).evaluate所用的InputFun函數(shù)其實(shí)和訓(xùn)練集所用的是一樣的函數(shù),只不過驗(yàn)證時(shí)不需要進(jìn)行打亂.shuffle(1000)和重復(fù).repeat()操作;而測(cè)試時(shí).predictInputFun函數(shù)則是新的,其只需要輸入自變量、無(wú)需輸入因變量。

2.9 精度評(píng)定、擬合圖像繪制與模型參數(shù)與精度結(jié)果保存

精度評(píng)定與擬合圖像就不用過多說(shuō)啦~最終,我們最好將模型參數(shù)與精度衡量指標(biāo)結(jié)果保存在Excel表格中,這樣子方便之后的調(diào)參過程。這里就不再一一介紹啦,大家對(duì)照代碼中的注釋即可。

# AccuracyVerification函數(shù),進(jìn)行精度驗(yàn)證指標(biāo)的計(jì)算與繪圖
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,[])
    # 以上為獲取測(cè)試數(shù)據(jù)的因變量與模型預(yù)測(cè)所得的因變量
    Pearsonr=stats.pearsonr(TestYList,PredictValuesList) # 計(jì)算皮爾遜相關(guān)系數(shù)
    R2=metrics.r2_score(TestYList,PredictValuesList) # 計(jì)算R方
    RMSE=metrics.mean_squared_error(TestYList,PredictValuesList)**0.5 # 計(jì)算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函數(shù),將模型所涉及的參數(shù)與最終精度結(jié)果保存
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對(duì)應(yīng)第一個(gè)空行
    for i in range(len(WriteVar)-1):
        exec("WriteSheet.cell(MaxRowNum+1,i+1).value=WriteVar[i+1]") # 用exec執(zhí)行語(yǔ)句,寫入信息
    ExcelData.save(WriteVar[0]) # 保存文件

# 調(diào)用AccuracyVerification函數(shù),進(jìn)行精度驗(yàn)證指標(biāo)的計(jì)算與繪圖
AccuracyResult=AccuracyVerification(PredictValues,TestY)
PearsonR,R2,RMSE,PredictY=AccuracyResult[0],AccuracyResult[1],AccuracyResult[2],AccuracyResult[3]

# 調(diào)用WriteAccuracy函數(shù),將模型所涉及的參數(shù)與最終精度結(jié)果保存
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)

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

3 詳細(xì)代碼

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

@author: Chutj
"""

# 加載必要的庫(kù)、包等
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

# ===============*** 函數(shù)聲明區(qū)域 ***===============

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

# LoadData函數(shù),加載全部數(shù)據(jù)
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路徑所指定的數(shù)據(jù),names中的內(nèi)容為各列的名稱
    return MyData

# InputFun函數(shù),訓(xùn)練數(shù)據(jù)與驗(yàn)證數(shù)據(jù)所用的Input函數(shù)
def InputFun(Features,Labels,Training,BatchSize):
    Datasets=tf.data.Dataset.from_tensor_slices((dict(Features),Labels)) # 對(duì)數(shù)據(jù)加以加載
    if Training:
        Datasets=Datasets.shuffle(1000).repeat() # 對(duì)于訓(xùn)練數(shù)據(jù),需要打亂(shuffle)、重復(fù)(repeat)
    return Datasets.batch(BatchSize) # 將經(jīng)過上述處理后的數(shù)據(jù)以每次BatchSize個(gè)輸出

# InputFunPredict函數(shù),測(cè)試數(shù)據(jù)所用的Input函數(shù)
def InputFunPredict(Features,BatchSize):
    return tf.data.Dataset.from_tensor_slices(dict(Features)).batch(BatchSize) # 對(duì)數(shù)據(jù)加以加載,以每次BatchSize個(gè)輸出

# AccuracyVerification函數(shù),進(jìn)行精度驗(yàn)證指標(biāo)的計(jì)算與繪圖
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,[])
    # 以上為獲取測(cè)試數(shù)據(jù)的因變量與模型預(yù)測(cè)所得的因變量
    Pearsonr=stats.pearsonr(TestYList,PredictValuesList) # 計(jì)算皮爾遜相關(guān)系數(shù)
    R2=metrics.r2_score(TestYList,PredictValuesList) # 計(jì)算R方
    RMSE=metrics.mean_squared_error(TestYList,PredictValuesList)**0.5 # 計(jì)算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函數(shù),將模型所涉及的參數(shù)與最終精度結(jié)果保存
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對(duì)應(yīng)第一個(gè)空行
    for i in range(len(WriteVar)-1):
        exec("WriteSheet.cell(MaxRowNum+1,i+1).value=WriteVar[i+1]") # 用exec執(zhí)行語(yǔ)句,寫入信息
    ExcelData.save(WriteVar[0]) # 保存文件


# ===============*** 代碼由此開始執(zhí)行 ***===============
#      ++++++++++--- 建議由這里開始看 ---++++++++++

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

# 調(diào)用DeleteOldModel函數(shù),刪除上一次運(yùn)行所保存的模型
DeleteOldModel(MyModelPath)

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

# 劃分?jǐn)?shù)據(jù)訓(xùn)練集與測(cè)試集
TrainX,TestX,TrainY,TestY=train_test_split(AllX,
                                           AllY,
                                           test_size=TestSize, # 指定數(shù)據(jù)中測(cè)試集所占比例
                                           random_state=RandomSeed # 指定劃分訓(xùn)練集與測(cè)試集的隨機(jī)數(shù)種子
                                           )

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

# 定義模型優(yōu)化方法
# Optimizer=OptMethod # 優(yōu)化方法選用OptMethod所指定的方法
Optimizer=lambda:tf.keras.optimizers.Adam(
    learning_rate=tf.compat.v1.train.exponential_decay(learning_rate=LearningRate, # 初始學(xué)習(xí)率
                                                       global_step=tf.compat.v1.train.get_global_step(),
                                                       # 全局步數(shù),用以計(jì)算已經(jīng)衰減后的學(xué)習(xí)率
                                                       # get_global_step()函數(shù)自動(dòng)獲取當(dāng)前的已經(jīng)執(zhí)行的步數(shù)
                                                       decay_steps=DecayStep, # 學(xué)習(xí)率下降完成的指定步數(shù)
                                                       decay_rate=DecayRate # 衰減率
                                                       ) # 選用基于學(xué)習(xí)率指數(shù)下降的Adam方法,此舉有助于降低過擬合風(fēng)險(xiǎn)
                                                         # 這一函數(shù)返回每次對(duì)應(yīng)的學(xué)習(xí)率
    )


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

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

# 基于訓(xùn)練數(shù)據(jù)訓(xùn)練模型
DNNModel.train(input_fn=lambda:InputFun(TrainX,
                                        TrainY,
                                        True,
                                        TrainBatchSize
                                        ), # 調(diào)用InputFun函數(shù);InputFun函數(shù)返回“tf.data.Dataset”對(duì)象,這個(gè)對(duì)象才可以被
                                           # train函數(shù)識(shí)別并帶入模型;由于InputFun函數(shù)每次返回BatchSize大小的數(shù)據(jù)個(gè)數(shù),
                                           # 因此需要多次執(zhí)行,前面需要加lambda
               steps=TrainStep # 指定模型訓(xùn)練的步數(shù)
               ) 

# 驗(yàn)證模型并保存驗(yàn)證結(jié)果
EvalResult=DNNModel.evaluate(input_fn=lambda:InputFun(TestX,
                                                      TestY,
                                                      False,
                                                      EvalBatchSize
                                                      )
                             )
# 打印驗(yàn)證結(jié)果
print('ev:{}'.format(EvalResult))

# 基于測(cè)試數(shù)據(jù)測(cè)試模型精度結(jié)果
PredictValues=DNNModel.predict(input_fn=lambda:InputFunPredict(TestX,
                                                               PredictBatchSize
                                                               )
                               )

# 調(diào)用AccuracyVerification函數(shù),進(jìn)行精度驗(yàn)證指標(biāo)的計(jì)算與繪圖
AccuracyResult=AccuracyVerification(PredictValues,TestY)
PearsonR,R2,RMSE,PredictY=AccuracyResult[0],AccuracyResult[1],AccuracyResult[2],AccuracyResult[3]

# 調(diào)用WriteAccuracy函數(shù),將模型所涉及的參數(shù)與最終精度結(jié)果保存
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)

以上就是Python基于TensorFlow接口實(shí)現(xiàn)深度學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)回歸的詳細(xì)內(nèi)容,更多關(guān)于Python TensorFlow深度學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)回歸的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Sanic框架路由用法實(shí)例分析

    Sanic框架路由用法實(shí)例分析

    這篇文章主要介紹了Sanic框架路由用法,結(jié)合實(shí)例形式較為詳細(xì)的分析了Sanic框架路由的原理、請(qǐng)求參數(shù)、請(qǐng)求類型、重定向等相關(guān)操作技巧,需要的朋友可以參考下
    2018-07-07
  • 淺談Python中的數(shù)據(jù)類型

    淺談Python中的數(shù)據(jù)類型

    Python很重要的的那幾個(gè)數(shù)據(jù)類型:字符串,列表,字典,元組,經(jīng)常有網(wǎng)友問他們之間重要的區(qū)別的是什么?能否舉幾個(gè)例子來(lái)說(shuō)明下!下嘛我們就來(lái)探討下。
    2015-05-05
  • python利用json和pyecharts畫折線圖實(shí)例代碼

    python利用json和pyecharts畫折線圖實(shí)例代碼

    這篇文章主要介紹了python利用json和pyecharts畫折線圖實(shí)例,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-12-12
  • 圖文詳解感知機(jī)算法原理及Python實(shí)現(xiàn)

    圖文詳解感知機(jī)算法原理及Python實(shí)現(xiàn)

    感知機(jī)是二類分類的線性分類模型,其輸入為實(shí)例的特征向量,輸出為實(shí)例的類別(取+1和-1二值)。本文將為大家詳細(xì)講講感知機(jī)算法的原理及實(shí)現(xiàn),需要的可以參考一下
    2022-08-08
  • Pandas標(biāo)記刪除重復(fù)記錄的方法

    Pandas標(biāo)記刪除重復(fù)記錄的方法

    下面小編就為大家分享一篇Pandas標(biāo)記刪除重復(fù)記錄的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧
    2018-04-04
  • 在vscode使用jupyter notebook出現(xiàn)bug及解決

    在vscode使用jupyter notebook出現(xiàn)bug及解決

    這篇文章主要介紹了在vscode使用jupyter notebook出現(xiàn)bug及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • 最新評(píng)論