获取绘图函数
首先,看到需要画acc和loss图。先去参考现成的,于是打开猫12分类,找到生成折线图的地方。
发现框内的两个函数绘制了折线图。既然是作为函数出现,说明已经有一定的封装,考虑能不能把整个函数搬走用。
由于这个文档是个ipynb文档,没法用Ctrl来看函数定义,所以直接选择Ctrl + f来在网页里查找函数定义的内容。
找到了,不是库函数,看定义可知这个函数传入两个List
型的参数,然后就根据这两个List
的内容来绘制一个折线图。而且看起来需要import
一个叫plt
的东西。
找到import plt
的地方,那么把draw_train_acc
复制到自己代码里的时候,还要在前面加上import matplotlib.pyplot as plt
回到函数这里,现在看一下batchs
和train_accs
这两个参数里面要装什么东西。
通过阅读函数调用前对Batchs
和all_train_accs
的修改可以发现,Batchs
里面是递增数列,每次递增训练批次的大小,也就是5;all_train_accs
里面装的是每批次训练的正确率acc。也就是说传两个整数数列进去就行。
在本地的代码编辑器上实验一下。
import matplotlib.pyplot as plt
def draw_train_acc(Batchs, train_accs):
title="training accs"
plt.title(title, fontsize=24)
plt.xlabel("batch", fontsize=14)
plt.ylabel("acc", fontsize=14)
plt.plot(Batchs, train_accs, color='green', label='training accs')
plt.legend()
plt.grid()
plt.show()
a = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
b = [0.1, 0.2, 0.3, 0.4, 0.5, 0.9, 0.3, 0.28, 0.01, 0.8]
draw_train_acc(a, b)
效果可以满足要求。
获得正确率数据
有了绘图函数,现在要找到用来绘图的数据。Batchs
没有问题,一个等差数列直接用range()
函数生成就行。现在需要找到每次训练的正确率。
在【学习率 优化方法比较】的模型训练部分找到了这么一个函数。
def record(self, epoch_id, trainLossMean, trainAccMean, EvalLossMean, EvalAccMean):
if os.path.exists(self.rankPath+'record.csv') is False:
init = {
"epoch":epoch_id,
"train_loss":trainLossMean,
'train_acc':trainAccMean,
"eval_loss":EvalLossMean,
'eval_acc':EvalAccMean
}
df = pd.DataFrame([init])
df.to_csv(self.rankPath+'record.csv', index=False)
else:
df = pd.read_csv(self.rankPath+'record.csv')
df.loc[df.index.max() + 1] = [epoch_id, trainLossMean, trainAccMean, EvalLossMean, EvalAccMean]
df.to_csv(self.rankPath+'record.csv', index=False)
把 epoch_id
, trainLossMean
, trainAccMean
, EvalLossMean
, EvalAccMean
这几个存入了一个叫record.csv
的文件。
从项目数据里找到这个文件,打开发现里面就是训练集/验证集的acc/loss。
发现这个文件有两千多行。仔细观察文件内容和record()
函数的代码,发现每训练完一个批次,就会往文件末追加一行。
再结合这个模型的批次大小是200,训练批次是100,就可以得知训练一轮后record.csv
的最后100行是绘图需要的数据。折线图的横坐标应该是每次递增200的等差数列,也就是range(0,20000,200)
。
现在已经知道了可以直接从文件里读取我们需要的数据,那么就要找怎么读取.csv
文件。那就想到,刚刚找到的record()
函数里有调用写入.csv
文件的函数,那同一个包里应当就有读取.csv
文件的函数。
发现调用的函数来自pd
,那么pandas
这个包里面应该就有需要的功能。果断开始百度
有很多教程,开始找需要的东西。现在需要的是实现“将.csv
中某一列数据的最后100项转成List
”这个操作。
阅读大量函数ing……
找到两个功能可以用:
那么就可以写出代码了。读取record.csv
文件,只读取训练正确率这一行,转置为一个Series
,用切片语法拿出最后100个数据。
pd.read_csv(".\\rank\\record.csv", usecols=["train_acc"]).squeeze("columns")[-100:]
有个问题,参数需要List
,但现在这个东西的类型是Series
。
直接外面套个list()
试试看,如果Series
这个类型有向List
的转换就能直接转过去。
list(pd.read_csv(".\\rank\\record.csv", usecols=["train_acc"]).squeeze("columns")[-100:])
运行成功了,那么现在用来绘图的正确率列表也已经拿到手了。
组合代码
import pandas as pd
import matplotlib.pyplot as plt
def draw_train_acc(Batchs, train_accs):
title="training accs"
plt.title(title, fontsize=24)
plt.xlabel("batch", fontsize=14)
plt.ylabel("acc", fontsize=14)
plt.plot(Batchs, train_accs, color='green', label='training accs')
plt.legend()
plt.grid()
plt.show()
train_acc = list(pd.read_csv(".\\rank\\record.csv", usecols=["train_acc"]).squeeze("columns")[-100:])
draw_train_acc(range(0, 20000, 200), train_acc)
把recode.csv
下载到本地,在本地先测试一下组合起来的代码,效果不错。
改进代码
需要画四张图,训练集/验证集 acc/loss 两两组合,对应的折线颜色、折线标注、标题和纵轴坐标都要变化。写四个函数就有点拉了,考虑把这个函数修改修改,要变的东西都提取到参数里。
观察一下,这几个地方都是会变化的,把它们都提取到函数参数中。
通过调整color
, title
, ylabel
这三个参数,就可以让要画的四张图都有对应的折线颜色、折线标注、标题和纵轴坐标。
import pandas as pd
import matplotlib.pyplot as plt
def draw_graph(Batchs, train_accs, color, title, ylabel):
title = title + ' ' + ylabel
plt.title(title, fontsize=24)
plt.xlabel("batch", fontsize=14)
plt.ylabel(ylabel, fontsize=14)
plt.plot(Batchs, train_accs, color=color, label=title)
plt.legend()
plt.grid()
plt.show()
train_acc = list(pd.read_csv(".\\rank\\record.csv", usecols=["train_acc"]).squeeze("columns")[-100:])
train_loss = list(pd.read_csv(".\\rank\\record.csv", usecols=["train_loss"]).squeeze("columns")[-100:])
eval_acc = list(pd.read_csv(".\\rank\\record.csv", usecols=["eval_acc"]).squeeze("columns")[-100:])
eval_loss = list(pd.read_csv(".\\rank\\record.csv", usecols=["eval_loss"]).squeeze("columns")[-100:])
draw_graph(range(0, 20000, 200), train_acc, color="green", title="train", ylabel="acc")
draw_graph(range(0, 20000, 200), train_loss, color="red", title="train", ylabel="loss")
draw_graph(range(0, 20000, 200), eval_acc, color="green", title="eval", ylabel="acc")
draw_graph(range(0, 20000, 200), eval_loss, color="red", title="eval", ylabel="loss")
这样代码就完成了,效果OK。