针对有自己训练任务或者模型设计任务的同学来说,训练过程中的参数变化是判断自己模型梯度消失与否的重要评价标准,本文以yolo卷积层的梯度值为例,给出如何进行数据可视化的方法
对于darknet框架来说,由于不存在内存共享,因此如果有使用到GPU的话,需要使用CUDA的函数将GPU内存中的数据传递到CPU中方可进行访问
cuda_pull_array(l.delta_gpu, l.delta, l.outputs);
之后就可以将l.delta中的数据写入文件了,上句代码中,l.outputs是l.delta中的数据量
FILE *fp = fopen("delta.txt", "w");
int num;
for( num = 0; num < l.outputs; num++)
{
fprintf(fp, "%f\n", l.delta[num]);
}
就可以得到最终的文件,下面就是针对输出的数据进行分析,不得不说,python真的是写工具的最佳编程语言,各种库的支持无语伦比,顺便推荐一个python中超级厉害的作图工具 seaborn
#!usr/bin/python3
# -*- coding:utf-8 -*-
# 作者:ArtyZe
import matplotlib.pyplot as plt
import numpy as np
# 设置曲线图绘制精度,并采集平均值样点数据
class AvgValueObj:
X = []
Y = []
precision = 1
def __init__(self):
self.X = []
self.Y = []
self.precision = 1
def set_precision(self, precision):
self.precision = precision
def get_value(self, scatter_obj):
x_tmp = []
y_tmp = []
i = 0
while scatter_obj.X.index(scatter_obj.X[-1]) >= i+self.precision:
sum_y = 0
for x in scatter_obj.X[i: i+self.precision]:
sum_y += scatter_obj.Y[x]
y_avg = sum_y / self.precision
x_tmp.append(i+self.precision/2)
y_tmp.append(y_avg)
i += self.precision
self.X = x_tmp
self.Y = y_tmp
class PointObj:
x = 0
y = 0
def __init__(self):
self.x = 0
self.y = 0
# def id_x(self, x):
# if self.x == x:
# return self
#
# def id_y(self, y):
# if self.y == y:
# return self
# 设置包络线精度,先设置横轴取点的精度,根据纵轴上在精度范围内点的个数决定是否要包络在内
class EnvelopeValueObj:
x_precision = 1
y_precision = 0.1
X_max = []
Y_max = []
X_min = []
Y_min = []
def __init__(self):
self.X_max = []
self.Y_max = []
self.X_min = []
self.Y_min = []
self.x_precision = 1
self.y_precision = 0.1
def import_point_obj(self, scatter_obj):
i = 0
while i+self.x_precision < len(scatter_obj.X):
point_obj_list = []
y_list = []
# point_obj = PointObj()
sum_y = 0
for x in scatter_obj.X[i: i+self.x_precision]:
point_obj = PointObj()
point_obj.x = x
tem_y = scatter_obj.Y[scatter_obj.X.index(x)]
point_obj.y = tem_y
sum_y += tem_y
point_obj_list.append(point_obj)
avg_y = sum_y / self.x_precision
for point in point_obj_list:
y_list.append(point.y)
y_list.sort(reverse=True)
for y in y_list:
if (y_list.index(y)+1) < len(y_list) and \
y >= avg_y and \
abs(y - y_list[y_list.index(y)+1]) > self.y_precision:
for point in point_obj_list:
if point.y == y:
point_obj_list.remove(point)
y_list.remove(y)
y_list.reverse()
for y in y_list:
if y_list.index(y)+1 < len(y_list) and \
y <= avg_y and \
abs(y_list[y_list.index(y)+1] - y) > self.y_precision:
for point in point_obj_list:
if point.y == y:
point_obj_list.remove(point)
for point in point_obj_list:
if point.y == y_list[-1]:
point_max = point
self.X_max.append(point_max.x)
self.Y_max.append(point_max.y)
elif point.y == y_list[0]:
point_min = point
self.X_min.append(point_min.x)
self.Y_min.append(point_min.y)
else:
pass
print("已经处理完前%s个数据..." % i)
i += self.x_precision
# 绘制曲线图
class DrawLine:
X = []
Y = []
def __init__(self):
self.X = []
self.Y = []
# 导入对象
def get_value(self, value_obj, tp):
if tp == "avg":
self.X = value_obj.X
self.Y = value_obj.Y
elif tp == "env_max":
self.X = value_obj.X_max
self.Y = value_obj.Y_max
elif tp == "env_min":
self.X = value_obj.X_min
self.Y = value_obj.Y_min
# 绘制曲线
def draw_line(self):
plt.plot(self.X, self.Y, color='yellow', linewidth=1.5)
class ScatterObj:
path = ""
X = []
Y = []
def __init__(self):
self.path = ""
self.X = []
self.Y = []
def set_path(self, path):
self.path = path
def get_xy(self):
with open(self.path, "r") as file:
lines = file.readlines()
i = 0
for line in lines:
value = float(line.split()[0])
self.X.append(i)
self.Y.append(value)
i = i + 1
# def distribute(self, color, label, linewidth):
# plt.scatter(self.X, self.Y, color=color, label=label, linewidth=linewidth)
delta0_path = "/home/gaoyang/Desktop/SeNet/delta_0.txt"
delta1_path = "/home/gaoyang/Desktop/SeNet/delta_1.txt"
avg_path = "/home/gaoyang/Desktop/SeNet/avg_0.txt"
scale_path = "/home/gaoyang/Desktop/SeNet/scale_0.txt"
# 平均值散点图
avg_obj = ScatterObj()
avg_obj.set_path(avg_path)
avg_obj.get_xy()
scale_obj = ScatterObj()
scale_obj.set_path(scale_path)
scale_obj.get_xy()
#如果你只要看delta而不看其他的权值参数
if 0:
# delta区域散点图
delta0_obj = ScatterObj()
delta0_obj.set_path(delta0_path)
delta0_obj.get_xy()
delta1_obj = ScatterObj()
delta1_obj.set_path(delta1_path)
delta1_obj.get_xy()
ax2 = plt.subplot(2, 1, 2)
# delta1_obj.distribute('black', 'delta', 0.05)
# delta0_obj.distribute('blue', 'delta', 0.01)
plt.scatter(delta0_obj.X, delta0_obj.Y, color='black', label='delta', linewidth=0.01)
plt.scatter(delta1_obj.X, delta1_obj.Y, color='blue', label='delta', linewidth=0.05)
if 1:
'''
此处用于delta值的上下界拟合线
x_precision越大,横轴取点越少,折线越平滑,精度越低
y_precision越大,包含的散点值越多,为了让拟合线更贴近边界,应取比游离点离集中值的距离更小的值,但尽量大
'''
envelope_value_obj = EnvelopeValueObj()
envelope_value_obj.x_precision = 2000
envelope_value_obj.y_precision = 0.07
envelope_value_obj.import_point_obj(delta0_obj)
env_max_line = DrawLine()
env_max_line.get_value(envelope_value_obj, "env_max")
env_max_line.draw_line()
env_min_line = DrawLine()
env_min_line.get_value(envelope_value_obj, "env_min")
env_min_line.draw_line()
plt.legend(loc='upper right', frameon=False, borderaxespad=0.1)
plt.xlabel('count')
plt.ylabel('value')
plt.grid()
#如果同时需要看delta和weight等参数
if 1:
ax1 = plt.subplot(2, 1, 1)
# avg_obj.distribute('red', 'avg', 0.8)
# scale_obj.distribute('green', 'scale', 0.8)
plt.scatter(avg_obj.X, avg_obj.Y, color='red', label='avg', linewidth=0.8)
# 平均线
avg_value_obj = AvgValueObj()
avg_value_obj.precision = 5
avg_value_obj.get_value(avg_obj)
avg_line = DrawLine()
avg_line.get_value(avg_value_obj, "avg")
avg_line.draw_line()
plt.scatter(scale_obj.X, scale_obj.Y, color='green', label='scale', linewidth=0.8)
plt.legend(loc='upper right', frameon=False, borderaxespad=0.1)
plt.ylim(-0.2, 1)
plt.xlabel('count')
plt.ylabel('value')
plt.grid()
# delta区域散点图
delta0_obj = ScatterObj()
delta0_obj.set_path(delta0_path)
delta0_obj.get_xy()
delta1_obj = ScatterObj()
delta1_obj.set_path(delta1_path)
delta1_obj.get_xy()
ax2 = plt.subplot(2, 1, 2)
# delta1_obj.distribute('black', 'delta', 0.05)
# delta0_obj.distribute('blue', 'delta', 0.01)
plt.scatter(delta0_obj.X, delta0_obj.Y, color='black', label='delta', linewidth=0.01)
plt.scatter(delta1_obj.X, delta1_obj.Y, color='blue', label='delta', linewidth=0.05)
if 1:
'''
此处用于delta值的上下界拟合线
x_precision越大,横轴取点越少,折线越平滑,精度越低
y_precision越大,包含的散点值越多,为了让拟合线更贴近边界,应取比游离点离集中值的距离更小的值,但尽量大
'''
envelope_value_obj = EnvelopeValueObj()
envelope_value_obj.x_precision = 2000
envelope_value_obj.y_precision = 0.07
envelope_value_obj.import_point_obj(delta0_obj)
env_max_line = DrawLine()
env_max_line.get_value(envelope_value_obj, "env_max")
env_max_line.draw_line()
env_min_line = DrawLine()
env_min_line.get_value(envelope_value_obj, "env_min")
env_min_line.draw_line()
plt.legend(loc='upper right', frameon=False, borderaxespad=0.1)
plt.xlabel('count')
plt.ylabel('value')
plt.grid()
plt.savefig("0.png")
这里呢,我是会有四个文件要做图,不过我在代码里也给出了只看delta的接口,把if 0改成if 1就可以了,不过要记得把下面的if 1改成if 0关掉该接口,最后给出我的处理图片