1-3.nilboy的tensorflow-yolo代码的微观分析
父类Net
1.def _variable_on_cpu(self, name, shape, initializer, pretrain=True, train=True):
tf.device('/cpu:0')指定运行设备为CPU,tf.get_variable(name, shape, initializer=initializer, dtype=tf.float32)在内存中申请变量,指定变量的名称,形状,初始化器,类型。通常用于权重的申请。
2.def _variable_with_weight_decay(self, name, shape, stddev, wd, pretrain=True, train=True):
计算某个权重的权重衰减
tf.nn.l2_loss(var)利用L2范数来计算张量的误差值(每一个元素进行平方,然后求和,最后乘一个1/2),tf.add_to_collection('losses', weight_decay)将变量放入一个集合,将集合中的多个变量变成一个列表。
3.def conv2d(self, scope, input, kernel_size, stride=1, pretrain=True, train=True):
构建卷积层,偏置值,并使用leaky_relu激活
conv = tf.nn.conv2d(input, kernel, [1, stride, stride, 1], padding='SAME'),input和conv结构一样都是[batch,height,width,channels],kernel(卷积核)结构是[height,width,in_channels,out_channels],这里脑海里应该有一张图才对。卷积核在input上按stride步调很小的一步一步走。每周一步生成一个值,放入input中,这个经过自身的相加和与偏置值的相加、并使用激活函数激活而生成。
4.def max_pool(self, input, kernel_size, stride):
temp_pool=tf.nn.max_pool(conv , ksize, strides, padding, name=None),temp_pool和conv结构一样都是[batch,height,width,channels],但channels不会改变,height和width会改变。
5.def local(self, scope, input, in_dimension, out_dimension, leaky=True, pretrain=True, train=True):
将输入张量平铺层向量,与权重向量做内积,偏置值,并使用激活函数激活
tf.matmul(reshape, weights)矩阵reshape和举证weights进行内积,local = tf.identity(local, name=scope.name)在计算图中创建新节点,并复制数据给新节点。
子类YoloTinyNet
1.def inference(self, images):
构建yolo模型
local3 = tf.concat([class_probs, scales, boxes], 3)在第三维的方向上进行数据叠加。
2.def loss(self, predicts, labels, objects_num):
先对一张图片中的一个目标求损失(类别损失、位置损失、置信度损失(对象、非对象)),然后将一张图片的每个目标的四类损失分别相加,得到一张图片的四类损失,依照相同的方法,将第二张图片的四类损失与第一张图片的四类损失相加。最后将一批图片的四类损失相加除以一批图片的个数得到最后的loss.
def body1(self, num, object_num, loss, predict, labels, nilboy):
代码可以分成三部分:(1)objects和response的计算(2)置信度和指示器的计算(3)四类损失的计算。其中有个单元格和边界框的概念,只有计算类别损失时算到边界框,置信度损失和位置损失都要细致到单元格。
置信度=iou*response,指示器和置信度是形状相同的矩阵,指示器中值为0或1且是置信度的子集,置信度的值为0~1的数。
iou的值实际上就单元格中对象是某一类的概率值。
objects = tf.pad(objects, temp, "CONSTANT")填充
base_boxes = np.tile(np.resize(base_boxes, [self.cell_size, self.cell_size, 1, 4]),[1, 1, self.boxes_per_cell, 1])对某一维度的复制,维度增加
max_I = tf.reduce_max(I, 2, keep_dims=True)求某一维度的最大值,维度减少
def iou(self, boxes1, boxes2):
tf.stack( values,axis=0,name=’stack’) 对张量进行拼接,维度可能发生变化。
boxes1 = tf.transpose(boxes1, [1, 2, 3, 0])对张量进行转置
tf.maximum(a,b)返回a和b之间的最大值
tf.summary.scalar('class_loss', loss[0] / self.batch_size):
每一批图片的类别损失日志记录值,用于以后在tensorboard上做可视化。
TextDataSet(DataSet):
1.def __init__(self, common_params, dataset_params):
创建队列:一个记录队列(record_queue)、一个图像标签队列(image_label_queue),将txt文件读取存储成二维数组,开启六个线程,一个线程执行生产者任务,另外五个线程执行消费者任务
2.def record_producer(self):
将二维数组读取,放入记录队列,队列长为10000,此时当第10001项进入队列是,线程要等待。
3.def record_customer(self):
取出记录队列中的项,def record_process(self, record):对取出的项进行解析,读取图片对图片进行颜色通道转换,缩放以支持神经网络的输入,记录目标的位置、种类、数目,最后已[image, labels, object_num]的格式返回。将返回值放入图像标签队列,有五个线程在执行这个操作,所以图像标签队列(image_label_queue)很快达到设定的最大值512,5个线程开始出现等待。
4.def batch(self):
读一批图片(16张),分别返回3个数组,第一个数组放16的图片的矩阵(经过类型转换、归一化),第二个数组放16个对应图片的标签(类型转化),第三个数组放16个对应图片包含的目标个数。
类YoloSolver
参数准备、构建计算图、优化目标函数
1.def __init__(self, dataset, net, common_params, solver_params):
设置参数,例如学习率、动量系数、最大训练次数等等。
2.def construct_graph(self):
构建计算图模型
self.images = tf.placeholder(tf.float32, (self.batch_size, self.height, self.width, 3))占位符,模型的输入参数,一般输入图片和标签。输入参数经神经网络模型(假设函数)得到预测,由预测与真实值得到loss(目标函数),优化(优化函数)损失,之后更新神经网络的权重。
3.def _train(self):
优化损失
4.def solve(self):
恢复模型(预训练模型的恢复),保存模型
summary_op = tf.summary.merge_all()可以将所有summary全部保存到磁盘,以便tensorboard显示。summary_writer = tf.summary.FileWriter(self.train_dir, sess.graph)指定一个文件路径来保存计算图,summary_writer.add_summary(summary_str, step)将训练中的数据保存到文件路径中的计算图。
print (format_str % (datetime.now(), step, loss_value,examples_per_sec, sec_per_batch)) 打印第几步,每一步的损失值,一秒处理几张图片,处理一批图片用的多少秒。
demo.py
恢复模型,(读图、转换颜色通道、缩放等等)输入图片得到训练好的值,对值进行解析,在图上画矩形框和标定类。保存图片。实际输出=sess.run(输出参数,输入)。
def process_predicts(predicts):
先确定图片中存在的是什么对象,在确定其位置。然后再找出四个坐标。预测出的四个坐标是相对一单元格的。需要将其转换的相对图片的四个坐标。
index = np.argmax(P)返回P中值最大的索引
index = np.unravel_index(index, P.shape)给出index元素在P中的位置
浙公网安备 33010602011771号