1 写在前面
tf.estimatorKerasKeras请看这里DNNRegressortf.estimator官网本文第二部分为代码的分解介绍,第三部分为完整代码。
下载:
相关版本信息:
Python版本:3.8.5
TensorFlow版本:2.4.1
编译器版本:Spyder 4.1.5


2 代码分解介绍
2.1 准备工作
首先需要引入相关的库与包。
1import
2import
3importas
4importas
5importas
6importas
7importas
8fromimport
9fromimport
其次,基于TensorFlow的代码往往会输出较多的日志信息,从而使得我们对代码执行情况的了解受到一定影响。代码输出的日志信息有四种,依据严重程度由低到高排序:INFO(通知)<WARNING(警告)<ERROR(错误)<FATAL(致命的);我们可以通过:
1'TF_CPP_MIN_LOG_LEVEL''3'
来对TensorFlow的输出日志信息加以约束。其中,“3”代表只输出FATAL信息。但要注意,这句代码需要放在 import tensorflow的前面:
1import
2'TF_CPP_MIN_LOG_LEVEL''3'
3import
4importas
5importas
6importas
7importas
8importas
9fromimport
10fromimport
2.2 参数配置
深度学习代码一大特点即为具有较多的参数需要我们手动定义。为避免调参时上下翻找,我们可以将主要的参数集中在一起,方便我们后期调整。
其中,具体参数的含义在本文后续部分详细介绍。
1# 将各类变量放在一个位置集中定义,十分有利于机器学习等变量较多的代码
2"G:/CropYield/03_DL/02_DNNModle"# 确定每一次训练所得模型保存的位置
3"G:/CropYield/03_DL/00_Data/AllDataAll.csv"# 确定输入数据的位置
4"G:/CropYield/03_DL/03_OtherResult/EvalResult54.xlsx"# 确定模型精度结果(RMSE等)与模型参数保存的位置
50.2# 确定数据中测试集所占比例
62425# 确定划分训练集与测试集的随机数种子
7'Adam'# 确定模型所用的优化方法
80.01# 确定学习率
9200# 确定学习率下降的步数
100.96# 确定学习率下降比率
1164128# 确定隐藏层数量与每一层对应的神经元数量
12'tf.nn.relu'# 确定激活函数
130.3# 确定Dropout的值
14'tf.compat.v1.ReductionV2.SUM_OVER_BATCH_SIZE'# 指定每个批次训练误差的减小方法
15'False'# 确定是否使用Batch Normalizing
16110# 确定训练数据一个Batch的大小
173000# 确定训练数据的Step数量
181# 确定验证数据一个Batch的大小
191# 确定预测数据(即测试集)一个Batch的大小
2.3 原有模型删除
DNNRegressor
1# DeleteOldModel函数,删除上一次运行所保存的模型
2defDeleteOldModel(ModelPath)
3# 获取ModelPath路径下全部文件与文件夹
4forin
5# 分别将所获取的文件或文件夹名称与ModelPath路径组合
6if# 若组合后的新路径是一个文件夹
7# 递归调用DeleteOldModel函数
8else
9# 若不是一个新的文件夹,而是一个文件,那么就删除
10
11# 调用DeleteOldModel函数,删除上一次运行所保存的模型
12
需要注意,以上代码仅删除指定路径下的文件,文件夹不删除。大家如果需要将文件夹也同时删除,修改以上代码函数中的后面几句即可。
2.4 数据导入与数据划分
pd.read_csv
其中,数据的每一列是一个特征,每一行是全部特征与因变量(就是下面的Yield)组合成的样本。
1# LoadData函数,加载全部数据
2defLoadData(DataPath)
3'EVI0610''EVI0626''EVI0712''EVI0728''EVI0813''EVI0829'
4'EVI0914''EVI0930''EVI1016''Lrad06''Lrad07''Lrad08'
5'Lrad09''Lrad10''Prec06''Prec07''Prec08''Prec09'
6'Prec10''Pres06''Pres07''Pres08''Pres09''Pres10'
7'SIF161''SIF177''SIF193''SIF209''SIF225''SIF241'
8'SIF257''SIF273''SIF289''Shum06''Shum07''Shum08'
9'Shum09''Shum10''SoilType''Srad06''Srad07''Srad08'
10'Srad09''Srad10''Temp06''Temp07''Temp08''Temp09'
11'Temp10''Wind06''Wind07''Wind08''Wind09''Wind10'
12'Yield'0# 加载DataPath路径所指定的数据,names中的内容为各列的名称
13return
14
15# 初始数据处理
16# 调用LoadData函数,获取数据
17"Yield""Yield"# 将因变量从全部数据中提取出
18# 将自变量与因变量分离
19
20# 划分数据训练集与测试集
21
22
23# 指定数据中测试集所占比例
24# 指定划分训练集与测试集的随机数种子
25
2.5 Feature Columns定义
Feature Columns就是一个桥梁,联系你的初始数据与模型;其好比一个名单,模型拿着这个名单到你的数据(即2.4部分你导入的数据)中按列的名称一一搜索,若初始数据中的某列名称在Feature Columns里,那么模型就会把初始数据中这一列的数据全部拿到自己这里,进行训练。
因为我们是希望导入数据的全部特征,那么可以直接在全部数据的自变量中循环,将全部特征的名称导入Feature Columns。
tf.feature_column.numeric_column
1# estimator接口中的模型需要用“Feature columns”对象作为输入数据,只有这样模型才知道读取哪些数据
2# 定义一个新的“Feature columns”对象
3forin
4# 将全部因变量数据(需要均为连续变量)导入
2.6 模型优化方法构建与模型结构构建
optimizer
1# 定义模型优化方法
2# Optimizer=OptMethod # 优化方法选用OptMethod所指定的方法
3lambda
4# 初始学习率
5
6# 全局步数,用以计算已经衰减后的学习率
7# get_global_step()函数自动获取当前的已经执行的步数
8# 学习率下降完成的指定步数
9# 衰减率
10# 选用基于学习率指数下降的Adam方法,此举有助于降低过拟合风险
11# 这一函数返回每次对应的学习率
12
Optimizer=
tf.compat.v1.train.exponential_decaylearning_rate *decay_rate ^ (global_step / decay_steps)
我们选择第二个优化方法,因此把第一个注释掉。
随后,我们定义模型的结构。
1# 基于DNNRegressor构建深度学习模型
2# 指定模型所用的“Feature columns”对象
3# 指定隐藏层数量与每一层对应的神经元数量
4# 指定模型所用的优化方法
5# 指定激活函数
6# 指定Dropout的值
71# 输出数据的维度,即因变量的个数
8# 指定每一次训练所得模型保存的位置
9# loss_reduction=eval(LossReduction), # 指定每个批次训练误差的减小方法
10# 指定是否使用Batch Normalizing
11
loss_reductionbatch_norm
其它参数可以参考:https://www.tensorflow.org/api_docs/python/tf/estimator/DNNRegressor,或参考:https://www.tensorflow.org/api_docs/python/tf/nn
2.7 模型训练
训练模型这一部分,我认为反而比模型的构建可能还难理解一些。我们先看代码:
1# 基于训练数据训练模型
2lambda
3
4True
5
6# 调用InputFun函数;InputFun函数返回“tf.data.Dataset”对象,这个对象才可以被
7# train函数识别并带入模型;由于InputFun函数每次返回BatchSize大小的数据个数,
8# 因此需要多次执行,前面需要加lambda
9# 指定模型训练的步数
10
traininput_fninput function
他长这个样子:
1# InputFun函数,训练数据与验证数据所用的Input函数
2defInputFun(Features,Labels,Training,BatchSize)
3# 对数据加以加载
4if
51000# 对于训练数据,需要打乱(shuffle)、重复(repeat)
6return# 将经过上述处理后的数据以每次BatchSize个输出
input functionInputFuninput functionDNNRegressor
很简单,它只需要将初始的数据转换为特定的格式即可,这个格式是一个元组(tuple),这个元组有两个元素:
features
label
不知道大家有没有理解,我们就举一个简单的例子。假如我们用两个地方的温度与降水预测这两个地方的作物产量:其温度分别为10 ℃、20 ℃,降水分别为15 mm,25 mm,作物产量分别为100千克每公顷,150千克每公顷——那么tuple由两个部分组成:
1
2'温度'1020'降水'1525
3100150
怎么样,是不是明白啦。
InputFuntf.data.Dataset.from_tensor_slices.shuffle(1000)buffer_size.shuffle(1000)
.repeat()Epoch.batch()
InputFuntrainInputFunInputFunlambdaInputFuntrain
2.8 模型验证与测试
理解了以上内容,接下来就好理解多了。我们需要进行验证与测试的操作——其实验证也就是利用了测试集数据,之所以我还进行了测试,是因为希望可以获取测试集预测结果,从而更直观地了解模型精度水平。
1# InputFunPredict函数,测试数据所用的Input函数
2defInputFunPredict(Features,BatchSize)
3return# 对数据加以加载,以每次BatchSize个输出
4
5# 验证模型并保存验证结果
6lambda
7
8False
9
10
11
12# 打印验证结果
13'ev:{}'
14
15# 基于测试数据测试模型精度结果
16lambda
17
18
19
.evaluateInputFun.shuffle(1000).repeat().predictInputFun
2.9 精度评定、拟合图像绘制与模型参数与精度结果保存
精度评定与拟合图像就不用过多说啦~最终,我们最好将模型参数与精度衡量指标结果保存在Excel表格中,这样子方便之后的调参过程。这里就不再一一介绍啦,大家对照代码中的注释即可。
1# AccuracyVerification函数,进行精度验证指标的计算与绘图
2defAccuracyVerification(PredictLabels,TestLabels)
30
4
5forin
6'predictions'0
7
8
9
10# 以上为获取测试数据的因变量与模型预测所得的因变量
11# 计算皮尔逊相关系数
12# 计算R方
130.5# 计算RMSE
14
15'r*'
16'Actual Values'
17'Predicted Values'
18# 以上为绘制拟合图像
19'Pearson correlation coefficient is {0}, and RMSE is {1}.'0
20return0
21
22# WriteAccuracy函数,将模型所涉及的参数与最终精度结果保存
23defWriteAccuracy(*WriteVar)
240
25# 获取全部Sheet
260# 获取指定Sheet
27# 激活指定Sheet
28# 获取指定Sheet对应第一个空行
29forin-1
30"WriteSheet.cell(MaxRowNum+1,i+1).value=WriteVar[i+1]"# 用exec执行语句,写入信息
310# 保存文件
32
33# 调用AccuracyVerification函数,进行精度验证指标的计算与绘图
34
350123
36
37# 调用WriteAccuracy函数,将模型所涉及的参数与最终精度结果保存
38
39',''%s'forin
40
至此,全部的代码分解介绍都结束啦~
3 详细代码
1# -*- coding: utf-8 -*-
2
3
4
5
6
7
8# 加载必要的库、包等
9import
10'TF_CPP_MIN_LOG_LEVEL''3'
11import
12importas
13importas
14importas
15importas
16importas
17fromimport
18fromimport
19
20# ===============*** 函数声明区域 ***===============
21
22# DeleteOldModel函数,删除上一次运行所保存的模型
23defDeleteOldModel(ModelPath)
24# 获取ModelPath路径下全部文件与文件夹
25forin
26# 分别将所获取的文件或文件夹名称与ModelPath路径组合
27if# 若组合后的新路径是一个文件夹
28# 递归调用DeleteOldModel函数
29else
30# 若不是一个新的文件夹,而是一个文件,那么就删除
31
32# LoadData函数,加载全部数据
33defLoadData(DataPath)
34'EVI0610''EVI0626''EVI0712''EVI0728''EVI0813''EVI0829'
35'EVI0914''EVI0930''EVI1016''Lrad06''Lrad07''Lrad08'
36'Lrad09''Lrad10''Prec06''Prec07''Prec08''Prec09'
37'Prec10''Pres06''Pres07''Pres08''Pres09''Pres10'
38'SIF161''SIF177''SIF193''SIF209''SIF225''SIF241'
39'SIF257''SIF273''SIF289''Shum06''Shum07''Shum08'
40'Shum09''Shum10''SoilType''Srad06''Srad07''Srad08'
41'Srad09''Srad10''Temp06''Temp07''Temp08''Temp09'
42'Temp10''Wind06''Wind07''Wind08''Wind09''Wind10'
43'Yield'0# 加载DataPath路径所指定的数据,names中的内容为各列的名称
44return
45
46# InputFun函数,训练数据与验证数据所用的Input函数
47defInputFun(Features,Labels,Training,BatchSize)
48# 对数据加以加载
49if
501000# 对于训练数据,需要打乱(shuffle)、重复(repeat)
51return# 将经过上述处理后的数据以每次BatchSize个输出
52
53# InputFunPredict函数,测试数据所用的Input函数
54defInputFunPredict(Features,BatchSize)
55return# 对数据加以加载,以每次BatchSize个输出
56
57# AccuracyVerification函数,进行精度验证指标的计算与绘图
58defAccuracyVerification(PredictLabels,TestLabels)
590
60
61forin
62'predictions'0
63
64
65
66# 以上为获取测试数据的因变量与模型预测所得的因变量
67# 计算皮尔逊相关系数
68# 计算R方
690.5# 计算RMSE
70
71'r*'
72'Actual Values'
73'Predicted Values'
74# 以上为绘制拟合图像
75'Pearson correlation coefficient is {0}, and RMSE is {1}.'0
76return0
77
78# WriteAccuracy函数,将模型所涉及的参数与最终精度结果保存
79defWriteAccuracy(*WriteVar)
800
81# 获取全部Sheet
820# 获取指定Sheet
83# 激活指定Sheet
84# 获取指定Sheet对应第一个空行
85forin-1
86"WriteSheet.cell(MaxRowNum+1,i+1).value=WriteVar[i+1]"# 用exec执行语句,写入信息
870# 保存文件
88
89
90# ===============*** 代码由此开始执行 ***===============
91# ++++++++++--- 建议由这里开始看 ---++++++++++
92
93# 将各类变量放在一个位置集中定义,十分有利于机器学习等变量较多的代码
94"G:/CropYield/03_DL/02_DNNModle"# 确定每一次训练所得模型保存的位置
95"G:/CropYield/03_DL/00_Data/AllDataAll.csv"# 确定输入数据的位置
96"G:/CropYield/03_DL/03_OtherResult/EvalResult54.xlsx"# 确定模型精度结果(RMSE等)与模型参数保存的位置
970.2# 确定数据中测试集所占比例
982425# 确定划分训练集与测试集的随机数种子
99'Adam'# 确定模型所用的优化方法
1000.01# 确定学习率
101200# 确定学习率下降的步数
1020.96# 确定学习率下降比率
10364128# 确定隐藏层数量与每一层对应的神经元数量
104'tf.nn.relu'# 确定激活函数
1050.3# 确定Dropout的值
106'tf.compat.v1.ReductionV2.SUM_OVER_BATCH_SIZE'# 指定每个批次训练误差的减小方法
107'False'# 确定是否使用Batch Normalizing
108110# 确定训练数据一个Batch的大小
1093000# 确定训练数据的Step数量
1101# 确定验证数据一个Batch的大小
1111# 确定预测数据(即测试集)一个Batch的大小
112
113# 调用DeleteOldModel函数,删除上一次运行所保存的模型
114
115
116# 初始数据处理
117# 调用LoadData函数,获取数据
118"Yield""Yield"# 将因变量从全部数据中提取出
119# 将自变量与因变量分离
120
121# 划分数据训练集与测试集
122
123
124# 指定数据中测试集所占比例
125# 指定划分训练集与测试集的随机数种子
126
127
128# estimator接口中的模型需要用“Feature columns”对象作为输入数据,只有这样模型才知道读取哪些数据
129# 定义一个新的“Feature columns”对象
130forin
131# 将全部因变量数据(需要均为连续变量)导入
132
133# 定义模型优化方法
134# Optimizer=OptMethod # 优化方法选用OptMethod所指定的方法
135lambda
136# 初始学习率
137
138# 全局步数,用以计算已经衰减后的学习率
139# get_global_step()函数自动获取当前的已经执行的步数
140# 学习率下降完成的指定步数
141# 衰减率
142# 选用基于学习率指数下降的Adam方法,此举有助于降低过拟合风险
143# 这一函数返回每次对应的学习率
144
145
146
147# 基于DNNRegressor构建深度学习模型
148# 指定模型所用的“Feature columns”对象
149# 指定隐藏层数量与每一层对应的神经元数量
150# 指定模型所用的优化方法
151# 指定激活函数
152# 指定Dropout的值
1531# 输出数据的维度,即因变量的个数
154# 指定每一次训练所得模型保存的位置
155# loss_reduction=eval(LossReduction), # 指定每个批次训练误差的减小方法
156# 指定是否使用Batch Normalizing
157
158
159# tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.INFO) # 将INFO级别的日志信息显示到屏幕
160
161# 基于训练数据训练模型
162lambda
163
164True
165
166# 调用InputFun函数;InputFun函数返回“tf.data.Dataset”对象,这个对象才可以被
167# train函数识别并带入模型;由于InputFun函数每次返回BatchSize大小的数据个数,
168# 因此需要多次执行,前面需要加lambda
169# 指定模型训练的步数
170
171
172# 验证模型并保存验证结果
173lambda
174
175False
176
177
178
179# 打印验证结果
180'ev:{}'
181
182# 基于测试数据测试模型精度结果
183lambda
184
185
186
187
188# 调用AccuracyVerification函数,进行精度验证指标的计算与绘图
189
1900123
191
192# 调用WriteAccuracy函数,将模型所涉及的参数与最终精度结果保存
193
194',''%s'forin
195