尝试复现SSD,遇到的一系列问题

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/sinat_15901371/article/details/88125260

参考文章:SSD关键源码解析-知乎      目标检测|SSD原理与实现

参考代码:balancap/SSD-Tensorflow

 

真是佩服那些能从头到尾把算法实现好的人。。该有多难啊。

 

现阶段成果:成功运行单种类目标检测

 

1.遇到最多的问题就是 list, array, tensor互相转换了。大部分时间消耗在这个上面。

解决:tensor --> array:

a: tensor; b: array
with tf.Session() as sess:
    b = sess.run(a)

list --> array:

a: list; b: array
b = np.array(a, dtype = 'float32')

 

2.实际VGG输出layer的shape与论文里的不相同。

论文里的layer的shape为(38, 38),(19, 19),(10, 10),(5, 5),(3, 3),(1, 1)。但是按照VGG论文的VGG-16来,输入300*300*3的时候,输出的shape有时候与要求的不一样。后来看了别人的文章,发现是padding的问题。

 

3.建立框框的scale。

参考的balancap的代码,里面的scale设置的与原文不一样,不知道他这样设置有没有经过试验。暂时按照原文来设置。

 

4.读/写tfrecord。

一开始打算将图片文件、标注信息做成tfrecord,以方便后续的读取。遇到的困难有:进制变换。将cv2读到的图片变成byte流存到tfrecord里,然后读出来的时候要进一步解码。遇到了各种编解码问题,就很烦。

读出来的文件是tensor的,喂给placeholder的时候还需要把它变成array,也就是说,图片-->array,变成tensor存好,再读出来变成array,怎么想想都是多此一举。

4.1.tensorflow的placeholder不接受feed为tensor的情况!百思不得其解。。为什么不接受tensor。。

然后,一次读完所有的tfrecord文件的话,必然就OOM了。

4.2.OOM报错。

分步读取的话,就老是报下列的错:

Coordinator stopped with threads still running

 

没想明白是为什么,最后就直接读图片了,反而省事,也很快。

 

5.图片滑窗/resize。

为了检验功能是否正常,使用了简单的resize,而不是滑窗。不管图片的比例,尺寸,通通resize到300*300。性能肯定是有下降的。如果有机会的话,用一下滑窗试试,顺便可以当成是Data Augmentation。

 

6.还是feed的问题。参考着balancap的代码,写着写着发现,place holder的输入,变成a list of tensor了(关联错误4)。尝试将a list of tensor变为一个tensor,但是并没有成功,如果需要这样的话,就要在bounding gt和先验框的算法里,将其重新变为array,或list of tensor。想想就,太麻烦了。最后解决的方法为,每次在train的循环里先算出一部分,然后将算出来的单一tensor,feed到placeholder里面去,就解决这个问题了。

 

7.anchor的尺寸。

一开始的时候没有发现,针对不同的layer,anchor的尺寸是不一样的。layer尺寸从大到小,每个点的anchor数目分别为4, 6, 6, 6, 4, 4。6比4多了1*1和sqrt(Sk * Sk+1)。然后一开始设计的时候,没考虑sqrt(Sk * Sk+1),反正就是说S要多算一个。

另外第一层,也就是conv4_1的话,计算方法是不一样的,独立的。

 

8.各种tensor乘法!加法!减法!根本无从判断算法写的是不是对的。。

 

9.在loss里面,有一个weighted_loss,要求loss tensor和weight tensor相乘。傻傻地弄错了weight tensor的大小,导致tensor过大,直接OOM了。(我还在想1080ti 11G怎么连batch_size是4都不够。。)

 

10.报错

Attempting to use uninitialized value

说是没初始化。。但是我ess.run(tf.global_variables_initializer())了的。。

不知道该怎么办。。训练是能训练了。收敛也收敛了。保存模型一直不行。。

解决,参考我的另一篇文章。。

 

11.越训练越慢。

知乎讨论 发现是在循环中增加了新的op。使用tf.graph.finalize()使计算图变为只读。也就是说,如果有新的op被创建,就会报错了。

暂时发现这个行的op来自降维,其实是删除长度为1的维度,也就是tf.squeeze()。在程序中,为了将输入的list of array 变为tensor以参与后续的运算,用了tf.squeeze(),然后它每次都会创建新的op,然后内存就越来越少了,越来越卡。

解决方案:重构了绑定ground_truth和anchor的模块。将原有的基于tensor的程序改成了基于numpy的逻辑。(顺便还精简了代码逻辑。。)

 

12.报错

unhashable type: 'numpy.ndarray' error

stackoverflow上有人说是因为feed_dict中使用的numpy变量类型与placeholder中的不一样。比如tf.float32和np.float64。但是我的不是这个问题。我的代码问题出在feed_dict中的值与placeholder重名了。(很愚蠢的问题)

 

13.绑定ground_truth和anchor的原理。直接把我代码里的注释复制过来了。

    #------------------------------------------------------------------------------------
    #This loop does have some thing special. Take feature_labels as example.
    #At the begining, feature_scores == 0. After loop, feature_scores is 
    #almost impossible to be zero. The jaccard score continue updates. Using mask,
    #the value of feature_labels --> the label(class) with higher jaccard score. 
    #It will not change if new jaccard score is less than existing feature_score.
    #As the loop goes on. The feature_labels --> label(class) with highest jaccard score.
    #Same as feature_labels, other 4 'array' sotre the highest jaccard score
    #label(class)'s localization.
    #------------------------------------------------------------------------------------

 

14.ground_truth和anchor绑定时的encode问题。。

15.上面那个问题也在内。训练不收敛。分类是正确的,但是,localizations,也就是box一直不收敛。

解决:

一:首先看了Smooth L1 loss,是正确的,没写错。虽然balancap的代码里用的是简化版的Smooth L1,但我用完全版肯定没问题。

二:看了训练的网络参数,是正常的。我想训练的一直在训练,不想训练的一直没在训练。

三:只用一种正样本来调试,发现问题了。绑定先验框和ground truth的时候出了问题。发现正样本的个数非常之多,并在正样本密集的图片内,几乎有一大半是正样本先验框。这跟常识和论文是不符的。

然后发现balancap的代码里有一行这个:

mask = tf.greater(jaccard, feat_scores)
mask = tf.logical_and(mask, feat_scores > -0.5)
mask = tf.logical_and(mask, label < num_classes)

问题就出在第二行。如果看过他的代码的话,就会发现feat_scores是永远大于0的。所以第二行是无效的行。在我的代码里把它优化掉了。

而SSD论文里要求的是,jaccard > 0.5, 也就是ground truth框和先验框IoU大于0.5的时候,才把这个先验框作为正样本。

这里是balancap的代码出了错误了。看他的issues里也有人反映无法训练的情况,估计是因为这个了。

 

改了之后就可以完成单正样本框选了。

上个图纪念一下,初步可以开始分清物体和背景了,不要在意bird分类,用来代表正样本的。。

开心

展开阅读全文

关于html转pdf所遇到一系列问题,求解答

04-21

首先直接将xhtml文件转换可以正常使用,也支持中文rn[code=Java]rnpackage com.ksoft.apps.client.action;rnrnimport java.io.File; rnimport java.io.FileOutputStream; rnimport java.io.OutputStream; rnrnimport org.xhtmlrenderer.pdf.ITextFontResolver; rnimport org.xhtmlrenderer.pdf.ITextRenderer; rnrnimport com.lowagie.text.pdf.BaseFont; rnrn/** rn* TODO class description * rn* rn* @author chaochen */ rnpublic class ITextRendererTest rn public static void main(String[] args) throws Exception rn String inputFile = "conf/template/test.xhtml"; rn String url = new File(inputFile).toURI().toURL().toString(); rn String outputFile = "firstdoc.pdf"; rn OutputStream os = new FileOutputStream(outputFile); rn ITextRenderer renderer = new ITextRenderer(); rn renderer.setDocument(url); rnrn // 解决中文支持问题 rn ITextFontResolver fontResolver = renderer.getFontResolver(); rn fontResolver.addFont("C:/Windows/Fonts/arialuni.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); rnrn // 解决图片的相对路径问题, 图片路径必须以file开头,指定对应Tomcat下项目rootpathrn renderer.getSharedContext().setBaseURL("file:/E:/apache-tomcat-6.0.16/apache-tomcat-6.0.16/webapps/apps-client/"); rn renderer.layout(); rn renderer.createPDF(os); rnrn os.close(); rn rn rnrnrn[/code]rn而后,开始琢磨直接将html代码转成pdf,参考网上找的一篇帖子iText和flying saucer结合生成pdf的技术 http://blog.csdn.net/shanliangliuxing/article/details/6833471rn然后发现我自己的ITextRenderer对象并未找到文章中所提到的setDocumentFromString()方法,rn而只发现setDocument(File file),setDocument(String uri),setDocument(Document doc2, String url),rnsetDocument(Document doc2, String url, NamespaceHandler nsh)这几个方法。难道是我得jar包版本错了么?rn我得项目里依赖德jar包:iText-2.0.8.jar、iTextAsian.jar、core-renderer.jar,求解答。rnrnrn然后我想,既然没找到setDocumentFromString()方法,那我就用setDocument(Document doc2, String url)方法试试吧。rnrnrn[code=Java]rnpackage com.ksoft.apps.client.action;rnrnimport java.io.ByteArrayInputStream;rnimport java.io.ByteArrayOutputStream;rnimport java.io.FileNotFoundException;rnimport java.io.FileOutputStream;rnimport java.io.InputStream;rnimport java.io.OutputStream;rnrnimport javax.xml.parsers.DocumentBuilder;rnimport javax.xml.parsers.DocumentBuilderFactory;rnimport javax.xml.transform.Transformer;rnimport javax.xml.transform.TransformerFactory;rnimport javax.xml.transform.dom.DOMSource;rnimport javax.xml.transform.stream.StreamResult;rnrnimport org.w3c.dom.Document;rnimport org.xhtmlrenderer.pdf.ITextFontResolver;rnimport org.xhtmlrenderer.pdf.ITextRenderer;rnrnrnrnimport com.lowagie.text.pdf.BaseFont;rnrnrnrnrnrnrnpublic class TestCase rnrn /**rn * @param argsrn */rn public static void main(String[] args) rn // TODO Auto-generated method sturn String encoding = "UTF-8";rn String outputFile = "firstdoc.pdf"; rn rn InputStream intream = null;rn Document doc = null;rn Document doc2 = null;rn try rn OutputStream out = new FileOutputStream(outputFile); rn rn rn StringBuffer html = new StringBuffer(); rn // DOCTYPE 必需写否则类似于 这样的字符解析会出现错误 rn html.append(""); rn html.append("").rn append("") rn .append(" ")rn .append(" ") rn .append("") rn .append(""); rn html.append(" 支持中文!"); rn html.append(""); rnrnrn DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();rn ByteArrayOutputStream bos = new ByteArrayOutputStream();rn Transformer transformer = TransformerFactory.newInstance().newTransformer();rn ITextRenderer renderer = new ITextRenderer();rn ITextFontResolver fontResolver = renderer.getFontResolver();rn rn intream = new ByteArrayInputStream(html.toString().getBytes(encoding));rn doc = (Document) builder.parse(intream); transformer.setOutputProperty("encoding", encoding);rn transformer.transform(new DOMSource(doc), new StreamResult(bos));rn intream = new ByteArrayInputStream(bos.toString().getBytes());rn doc2 = (Document) builder.parse(intream);rn // 解决中文支持问题 rn fontResolver.addFont("C:/Windows/Fonts/ARIALUNI.TTF", rn BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); rn rn rn // 解决图片的相对路径问题 rn renderer.getSharedContext().setBaseURL("file:/E:/apache-tomcat-6.0.16/apache-tomcat-6.0.16/" +rn "webapps/apps-client/"); rn rn rn renderer.setDocument(doc2, null);rn // renderer.getSharedContext().setBaseURL("file:/c:/");rn renderer.layout();rn rn renderer.createPDF(out, true);rn rn out.flush();rn out.close();rn catch (Exception ex) rn ex.printStackTrace();rn rn rnrnrn[/code]rnrn调试的时候,发现在将html代码转成Document时候特别慢,就是红色字体的那行代码,请教有优化办法么?doc = (Document) builder.parse(intream);rn另外发现这样做又不支持中文了,我在重新查证那篇博文,发现引用了arialuni.ttf字体,必须在html代码里的body标签增加个stylern rn但是这样的话就没办法生成Document对象了,顿时卡壳,求思路,求解惑rn 论坛

没有更多推荐了,返回首页