精华内容
下载资源
问答
  • float的精度和取值范围

    万次阅读 多人点赞 2019-06-16 12:11:00
    关于float的精度和取值范围这个问题,我查询了很多次,每次都是用完就忘了,等到再使用的时候还需要再次查询,关键是这个问题大家给出的结果并不都是一致的,我得从众多的资料当中选择出正确的观点,这还要额外花...

    前言

    关于float的精度和取值范围这个问题,我查询了很多次,每次都是用完就忘了,等到再使用的时候还需要再次查询,关键是这个问题大家给出的结果并不都是一致的,我得从众多的资料当中选择出正确的观点,这还要额外花一些时间,所以我决定也总结一次,方便我以后拿来直接用了,如果能给大家带来帮助那就更好了。下面提到一些说法很多都是我个人的理解,如果大家有疑义,欢迎讨论。

    精度限制

    首先考虑下为什么会产生精度问题,是因为存储数据的空间有限,以一个四字节整数int n;为例,一共有32位,取值范围是 [-2147483648‬, 2147483647] ,一共是4,294,967,296种可能,它的精度可以说是小数点后一位都不保留,也就是只有整数,换句话说变量n可以表示实数范围内的4,294,967,296个数值。

    如果换成float类型呢?一个变量float f所能表示多少个数呢?实际上由于存储空间未发生变化,同样是4字节32位,那么float类型也只能表示,或者说精确表示4,294,967,296个数值(真实情况由于一些特殊的规则,最终所表示的数字个数还要少),说到这里很多人可能会疑惑,因为他知道float可以表示比4,294,967,296大的数,同时也能表示小数,如果只有4,294,967,296种可能,那究竟是怎么做到的呢?

    这里也就开始提到精度了,整数很好理解,每个数字的间隔都是1,int类型所表示的4,294,967,296个数字都是等间距的,步长为1。而float也只能表示4,294,967,296个数字,同时要表示比int还大的范围,一个很直观的想法就是把间距拉大,这样范围就大了,但是float还要表示小数,像0.2、0.4这样的数字间距明显要小于1啊,想要存储小数貌似要把间距缩小,这就和前面矛盾了啊。

    实际上float类型存储数据的间隔不是等间距的,而是在0的附近间距小,在远离0的位置间距大,为什么会这样,一会我们看一下float类型数据的存储规则就明白了,这里先来看一下int类型和float类型所表示数字的范围对比,这只是一个示意图。

    //int
               [ *         *         *         0         *         *         * ]
    //float
    [ *          *    *    *   *  *  * * * * * 0 * * * * *  *  *   *    *    *          * ]
    

    上面的示意图就是两者表示数字范围的差异,每个星号*就表示一个数字,float通过这种不等间距的分布,既扩大了范围也表示了小数,那么有没有问题呢?

    当然有问题,饭就这么多,人多了自然不够吃了,因为远离0的位置间距越来越大,当要表示间距中间的一个数字时,只能找它附近离它最近的一个可以表示的数字来代替,这就导致了精度问题,比如我给一个float类型变量分别赋值为 4294967244 和 4294967295 ,再次输出时都变成了 4294967296,因为超过了精度,所以只能找最接近的数字代替。

    float存储方式

    这部分内容基本上各篇文章说的都一致,我也简单描述下,后面根据这部分的定义来推算一下float的精度和取值范围。

    首先我们知道常用科学计数法是将所有的数字转换成(±)a.b x 10c10^c 的形式,其中a的范围是1到9共9个整数,b是小数点后的所有数字,c是10的指数。而计算机中存储的都是二进制数据,所以float存储的数字都要先转化成(±)a.b x 2c2^c,由于二进制中最大的数字就是1,所以表示法可以写成(±)1.b x 2c2^c的形式,float要想存储小数就只需要存储(±),b和c就可以了。

    float的存储正是将4字节32位划分为了3部分来分别存储正负号,小数部分和指数部分的:

    1. Sign(1位):用来表示浮点数是正数还是负数,0表示正数,1表示负数。
    2. Exponent(8位):指数部分。即上文提到数字c,但是这里不是直接存储c,为了同时表示正负指数以及他们的大小顺序,这里实际存储的是c+127。
    3. Mantissa(23位):尾数部分。也就是上文中提到的数字b。

    三部分在内存中的分布如下,用首字母代替类型

    S E E E E E E E E M M M M M M M M M M M M M M M M M M M M M M
    0 1 0 0 0 0 0 0 1 1 0 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1

    float存储示例

    以数字6.5为例,看一下这个数字是怎么存储在float变量中的:

    1. 先来看整数部分,模2求余可以得到二进制表示为110。

    2. 再来看小数部分,乘2取整可以得到二进制表示为.1(如果你不知道怎样求小数的二进制,请主动搜索一下)。

    3. 拼接在一起得到110.1然后写成类似于科学计数法的样子,得到1.101 x 222^2

    4. 从上面的公式中可以知道符号为正,尾数是101,指数是2。

    5. 符号为正,那么第一位填0,指数是2,加上偏移量127等于129,二进制表示为10000001,填到2-9位,剩下的尾数101填到尾数位上即可

    S E E E E E E E E M M M M M M M M M M M M M M M M M M M M M M
    0 1 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    1. 内存中二进制数01000000 11010000 00000000 00000000表示的就是浮点数6.5

    float范围

    明白了上面的原理就可求float类型的范围了,找到所能表示的最大值,然后将符号为置为1变成负数就是最小值,要想表示的值最大肯定是尾数最大并且指数最大,
    那么可以得到尾数为 0.1111111 11111111 11111111,指数为 11111111,但是指数全为1时有其特殊用途,所以指数最大为 11111110,指数减去127得到127,所以最大的数字就是1.1111111 1111111 11111111 x 21272^{127},这个值为 340282346638528859811704183484516925440,通常表示成 3.4028235E38,那么float的范围就出来了:

    [-3.4028235E38, 3.4028235E38]

    float精度

    float 类型的数据精度取决于尾数,相信大家都知道这一点,但是精度怎么算我也是迷糊了好久,最近在不断尝试的过程中渐渐的明白了,首先是在不考虑指数的情况下23位尾数能表示的范围是[0, 22312^{23}-1],实际上尾数位前面还隐含了一个"1",所以应该是一共24位数字,所能表示的范围是[0, 22412^{24}-1](因为隐含位默认是"1",所以表示的数最小是1不是0,但是先不考虑0,后面会特殊介绍,这里只按一般值计算),看到这里我们知道这24位能表示的最大数字为2242^{24}-1,换算成10进制就是16777215,那么[0, 16777215]都是能精确表示的,因为他们都能写成1.b x 2c2^c的形式,只要配合调整指数c就可以了。

    16777215 这个数字可以写成1.1111111 11111111 1111111 * 2232^{23},所以这个数可以精确表示,然后考虑更大的数16777216,因为正好是2的整数次幂,可以表示1.0000000 00000000 00000000 * 2242^{24},所以这个数也可以精确表示,在考虑更大的数字16777217,这个数字如果写成上面的表示方法应该是 1.0000000 00000000 00000000 1 * 2242^{24},但是这时你会发现,小数点后尾数位已经是24位了,23位的存储空间已经无法精确存储,这时浮点数的精度问题也就是出现了。

    看到这里发现 16777216 貌似是一个边界,超过这个数的数字开始不能精确表示了,那是不是所有大于16777216的数字都不能精确表示了呢?其实不是的,比如数字 33554432 就可以就可以精确表示成1.0000000 00000000 00000000 * 2252^{25},说道这里结合上面提到的float的内存表示方式,我们可以得出大于 16777216 的数字(不超上限),只要可以表示成小于24个2的n次幂相加,并且每个n之间的差值小于24就能够精确表示。换句话来说所有大于 16777216 的合理数字,都是[0, 16777215]范围内的精确数字通过乘以2n2^n得到的,同理所有小于1的正数,也都是 [0, 16777215] 范围内的精确数字通过乘以2n2^n得到的,只不过n取负数就可以了。

    16777216 已经被证实是一个边界,小于这个数的整数都可以精确表示,表示成科学技术法就是1.6777216 * 10710^{7},从这里可以看出一共8位有效数字,由于最高位最大为1不能保证所有情况,所以最少能保证7位有效数字是准确的,这也就是常说float类型数据的精度。

    float小数

    从上面的分析我们已经知道,float可表示超过16777216范围的数字是跳跃的,同时float所能表示的小数也都是跳跃的,这些小数也必须能写成2的n次幂相加才可以,比如0.5、0.25、0.125…以及这些数字的和,像5.2这样的数字使用float类型是没办法精确存储的,5.2的二进制表示为101.0011001100110011001100110011……最后的0011无限循环下去,但是float最多能存储23位尾数,那么计算机存储的5.2应该是101.001100110011001100110,也就是数字 5.19999980926513671875,计算机使用这个最接近5.2的数来表示5.2。关于小数的精度与刚才的分析是一致的,当第8位有效数字发生变化时,float可能已经无法察觉到这种变化了。

    float特殊值

    我们知道float存储浮点数的形式是(±)1.b x 2c2^c,因为尾数位前面一直是个1,所以无论b和c取什么样的值,都无法得到0,所以在float的表示方法中有一些特殊的约定,用来表示0已经其他的情况。

    float的内存表示指数位数有8位,范围是[0, 255],考虑偏移量实际的指数范围是[-127,128],但实际情况下指数位表示一般数字时不允许同时取0或者同时取1,也就是指数位的实际范围是[-126,127],而指数取-127和128时有其特殊含义,具体看下面表格:

    符号位 指数位 尾数位 数值 含义
    0 全为0 全为0 +0 正数0
    1 全为0 全为0 -0 负数0
    0 全为0 任意取值f 0.f21260.f * 2^{-126} 非标准值,尾数前改为0,提高了精度
    1 全为0 任意取值f 0.f2126-0.f * 2^{-126} 非标准值,尾数前改为0,提高了精度
    0 全为1 全为0 +Infinity 正无穷大
    1 全为1 全为0 -Infinity 负无穷大
    0/1 全为1 不全为0 NaN 非数字,用来表示一些特殊情况

    总结

    1. float的精度是保证至少7位有效数字是准确的
    2. float的取值范围[-3.4028235E38, 3.4028235E38],精确范围是[-340282346638528859811704183484516925440, 340282346638528859811704183484516925440]
    3. 一个简单的测试float精度方法,C++代码中将数字赋值给float变量,如果给出警告warning C4305: “=”: 从“int”到“float”截断,则超出了float的精度范围,在我的测试中赋值为16777216及以下整数没有警告,赋值为16777217时给出了警告。
    展开全文
  • antd+react inputnumber 小数精度

    万次阅读 2021-01-25 13:31:24
    1、首先需要inputnumber对精度进行控制,这里精度控制在1-5 <Form.Item labelCol={{ span: 8 }} wrapperCol={{ span: 8 }} label={"流速小数位数"}> {form.getFieldDecorator('flowrateDecimallen', { ...

    antd+精度状态控制,会出现第一次点击聚焦仍然显示上一次值的情况。

    1、首先需要inputnumber对精度进行控制,这里精度控制在1-5

     <Form.Item labelCol={{ span: 8 }} wrapperCol={{ span: 8 }} label={"流速小数位数"}>
                        {form.getFieldDecorator('flowrateDecimallen', {
                          initialValue: objectData?.flowrateDecimallen,
                          rules: [
                            { validator: (rule: any, value: any, callback: any) => validateHeightAndMin(value, callback, '') }
                          ]
                        })(<InputNumber min={0} max={5} precision={0} placeholder={"请输入"} onChange={currentPrecisionChange}></InputNumber>)}
                      </Form.Item>
    

    2、受精度控制的inputnumber

    初始化数据:

      const initDymAttr = () => {
        dymAttr.flowrateInit = undefined
        dymAttr.flowInit = undefined
        dymAttr.cumulativeFlowMax = undefined
        dymAttr.cumulativeFlowMin = undefined
        dymAttr.currentSpeedMax = undefined
        dymAttr.currentSpeedMin = undefined
      }
    

    状态:

     const [currentPrecision, setCurrentPrecision] = useState<number | undefined>(5);
    
     <Form.Item labelCol={{ span: 8 }} wrapperCol={{ span: 8 }} label={"流速初值"}>
                        {form.getFieldDecorator('flowrateInit', {
                          initialValue: objectData?.flowrateInit,
                          rules: [
                            { validator: (rule: any, value: any, callback: any) => validateHeightAndMin(value, callback, '') }
                          ]
                        })(<InputNumber onChange={(value: any) => keyChange(value, "flowrateInit", "current")}
                          onFocus={currentNumberFocus} precision={currentPrecision} placeholder={"请输入"}></InputNumber>)}
                      </Form.Item>
    

    3、精度值变化响应函数:

      const currentPrecisionChange = (value: number | undefined) => {
        if (value != undefined && (value > 5 || value < 0)) {
          message.error("小数位为0-5位")
        }
        else {
          setCurrentPrecision(value)
        }
      }
    

    4、受控组件值变化响应函数:

      const keyChange = (value: any, attrName: string, attrType: string) => {
        if (dymAttr[attrName] != value) {
          dymAttr[attrName] = value
          if (dymAttr[attrName] != null && parseFloat(dymAttr[attrName]).toFixed(currentPrecision) != "NaN" && attrType == "current") {
            form.setFieldsValue({ [attrName]: parseFloat(dymAttr[attrName]).toFixed(currentPrecision) })
            const textDom: any = document.getElementById(attrName);
            textDom.focus()
          }
          else if (dymAttr[attrName] != null && parseFloat(dymAttr[attrName]).toFixed(flowPrecision) != "NaN" && attrType == "flow") {
            form.setFieldsValue({ [attrName]: parseFloat(dymAttr[attrName]).toFixed(flowPrecision) })
            const textDom: any = document.getElementById(attrName);
            textDom.focus()
          }
        }
      }
    

    5、受控组件聚焦响应函数:

      const currentNumberFocus = (e: any) => {
        var fieldName = e.target?.id
        if (dymAttr[fieldName] != null && parseFloat(dymAttr[fieldName]).toFixed(currentPrecision) != "NaN") {
          form.setFieldsValue({ [fieldName]: parseFloat(dymAttr[fieldName]).toFixed(currentPrecision) })
        }
      }
    
    展开全文
  • Java面试官:兄弟,你确定double精度比float低吗?

    万次阅读 多人点赞 2019-03-31 07:25:46
    “BigDecimal可以表示任意精度的小数,并对它们进行计算。但 要小心使用 BigDecimal(double) 构造函数,因为它会在计算的过程中产生舍入误差 。最好要使用基于整数或 String 的构造函数来创建BigDecimal对象。” ...

    我有一个朋友,叫老刘,戴着度数比我还高的近视镜,显得格外的“程序员”;穿着也非常“不拘一格”,上半身是衬衣西服,下半身是牛仔裤运动鞋。

    我和老刘的感情非常好,每周末我们都要在一起吃顿饭。这周,我们吃的是洛阳有名的吴家刀削面,席间他聊了一件蛮有趣的面试经历;我听得津津有味。

    散席的时候,老刘特意叮嘱我把他和面试者的对话整理一下发出来,因为他觉得这段对话非常的精彩,值得推荐给更多初学Java的年轻人。

    注:以下是老刘和面试者东丰的真实对话。如有雷同,请勿对号入座

    老刘:“东丰,你长期从事金融软件的开发,记录存款和金额之类的有关数据用哪种数据类型啊?”

    东丰:“当然用float啊,精确度比double高嘛。”

    老刘:“东丰,你确定double精度比float低吗?”

    东丰:“那当然啊,double只精确到小数点后两位,double这个单词的意思不就是二的意思吗?”

    老刘:“东丰,你右手边刚好有一本《Java核心技术卷1》,你翻到第35页,看一下。”

    东丰:“…哦,刘经理,不用了。不好意思,刚刚开个玩笑,为了缓和一下面试的紧张气氛。看您厚厚的眼镜片下藏着一双深邃的眼睛,我觉得您一定大有学问。在金融计算中,必须要使用BigDecimal,double和float都不适合。因为单单一个精度问题就能把人整晕了。”

    “我记得有一次,我碰巧要计算一个表达式a - b,a的值为2,b的值为1.1,我侄女五岁半都知道答案应该是0.9,结果程序算出来的结果竟然是0.89999…,我当时又气又激动,气的是计算机还没有我侄女靠谱,激动的是我竟然第一次找到了Java的bug。”

    “我赶紧把这个bug反馈到了沉默王二的青铜时代群,以为我要被大家点赞表扬了。结果收到了大佬们一致的无情的嘲笑!”

    “好在,群主二哥及时地安慰了我。他发我私信说:‘首先,计算机进行的是二进制运算,我们输入的十进制数字会先转换成二进制,进行运算后再转换为十进制输出。double和float提供了快速的运算,然而问题在于转换为二进制的时候,有些数字不能完全转换,只能无限接近于原本的值,这就导致了你看到的不正确的结果。’”

    “看到二哥的信息后,我沮丧的心情得到了很大的安慰。我于是就对使用浮点数和小数中的问题进行了深入地研究。”

    “BigDecimal可以表示任意精度的小数,并对它们进行计算。但要小心使用 BigDecimal(double) 构造函数,因为它会在计算的过程中产生舍入误差。最好要使用基于整数或 String 的构造函数来创建BigDecimal对象。”

    老刘:“哇,你回答得很好。那我们来看下一个问题。你应该知道2 / 0的时候程序会报java.lang.ArithmeticException的错误,那么你知道2.0 / 0的结果吗?”

    东丰:“刘经理,您这个问题难不倒我。结果是Infinity(英菲尼迪),不好意思,我的英语口语能力有限啊。其实就是无穷的意思。不仅有正无穷大,还有负无穷大,甚至还有一个叫做NaN的特殊值。NaN代表‘不是一个数字’。这些值的存在是为了在出现错误条件时,程序还可以用特定的值来表示所产生的结果。这些错误的情况包括算术溢出、给负数开平方根,还有您说的除以 0 等。”

    老刘:“东丰啊,你的发音比我好啊,挺准确的。”

    东丰:“刘经理您见笑了。”

    老刘:“我这还有一道关于数组的问题,你稍等一下,我在纸上写一下。”

    int[] a = {1, 2, 3, 4}
    int[] b = {2, 4}
    int[] c = {1, 3}
    int[] d = {2}
    

    “有这样四个数组,要求每个数组只留一个唯一的元素。也就是说,a、b、c、d四个数组之间的元素不能相同,你打算怎么做呢?”

    东丰:“刘经理,我能用一下您的凌美钢笔吗?”

    老刘:“可以啊,你请用。”

    东丰:“我大致演算了一下。说一下我的思路。d只能是2,b只能是4,a是1或者3,c是3或者1。遍历长数组,剔除长数组中含有的最短数组的元素。b中剔除d中的2还剩下4,a中剔除d中的2还剩下1、3、4,c中不含d中元素,所以不用剔除。剔除后b中还剩下一个4,d中是一个2。再次遍历剔除a中的4。最后a和c中只剩下1和3了,再分别剔除互异的数就行了。”

    “我觉得比较笨的作法,刘经理您觉得可行吗?”

    老刘:“可行,没有问题。那,你对变量和方法的命名有什么看法呢?请随意发挥啊。”

    东丰:“我在博客园上曾看到一个有意思的投票统计——选出平常工作时自己认为最难的事情,选项大致有:”

    • 写各种文档
    • 与客户沟通
    • 预估工作量
    • 给变量命名

    “投票结果完全出乎我的意料,排在第一的竟然是‘给变量命名’!变量命名实在是软件开发中最常见的一件事了,但这件事要想做好,还真是不容易啊。”

    “阿里巴巴Java开发手册中「强制」规定,方法名、参数名、成员变量、局部变量要统一使用lowerCamelCase风格,必须遵从驼峰形式。”

    localValue // 变量
    getHttpMessage() // 方法
    

    “有很长一段时间,我总是在纠结究竟是用拼音好还是用英语单词好的问题。后来我下定了决心:要么用拼音要么用英语单词,只要看到名字就能知道这个变量或者方法的用意就行了。”

    “有时候,确实很难给变量取一个好名字。这时候,我就会选择一种省时省力省心的做法——将变量名命名为类型名。比如说:”

    Map map;
    List list;
    

    “最好,变量声明的地方要离第一次使用的地方近。否则的话,代码阅读起来会很困难,因为人眼睛接受的屏幕高度是有限的。”

    老刘:“东丰啊,你非常的优秀。恭喜你,你的面试过了。你回去准备一下,下周一就可以来上班了。”

    再注:以上是老刘和面试者东丰的真实对话。如有雷同,请勿对号入座


    上一篇:对《Java核心技术卷一》读者的一些建议

    下一篇:请用面向对象的思想,谈一谈这次面试的过程

    谢谢大家的阅读,原创不易,喜欢就随手点个赞👍,这将是我最强的写作动力。如果觉得文章对你有点帮助,还挺有趣,就关注一下我的公众号「沉默王二」。

    展开全文
  • 精彩内容 ...43.5%mAP+65FPS 精度速度最优平衡, 各种调优手段释真香! 作者团队:Alexey Bochkovskiy&中国台湾中央研究院 论文链接: https://arxiv.org/pdf/2004.10934.pdf 代码链接: ...

    关注

    点击这里的链接,获取下面资料:

     

    资源二:深度学习视频教程
    
    1. “花书”深度学习圣经——动手学深度学习   
    2. 《计算机视觉深度学习入门》共5门视频   
    3. 《深度学习进阶视频课程》

     

    精彩内容

    YOLOv4来了!43.5%mAP+65FPS 精度速度最优平衡, 各种调优手段释真香!

    作者团队:Alexey Bochkovskiy&中国台湾中央研究院

    论文链接:

    https://arxiv.org/pdf/2004.10934.pdf

    代码链接:

    https://github.com/AlexeyAB/darknet

    这个很重要!预训练模型 + 作者训练好的模型 链接:

    YOLOV4 预训练模型 yolov4.conv.137 + yolov4-weights 网盘链接

     

    1 Introduction

     

    /可以说有许多技巧可以提高卷积神经网络(CNN)的准确性,但是某些技巧仅适合在某些模型上运行,或者仅在某些问题上运行,或者仅在小型数据集上运行;我们来码一码这篇文章里作者都用了哪些调优手段:

    • 加权残差连接(WRC)

    • 跨阶段部分连接(CSP)

    • 跨小批量标准化(CmBN)

    • 自对抗训练(SAT)

    • Mish激活

    • 马赛克数据增强

    • CmBN

    • DropBlock正则化

    • CIoU Loss

     

    有没有被惊到!

    经过一系列的堆料,终于实现了目前最优的实验结果:43.5%的AP(在Tesla V100上,MS COCO数据集的实时速度约为65FPS)。


    这篇文章的贡献如下:

    • 开发了一个高效、强大的目标检测模型。它使每个人都可以使用1080 Ti或2080 TiGPU来训练一个超级快速和准确的目标探测器。

    • 验证了在检测器训练过程中,最先进的Bag-of-Freebies和Bag-of-Specials 的目标检测方法的影响。

    • 修改了最先进的方法,使其更有效,更适合于单GPU训练,包括CBN、PAN、SAM等。


    总之一句话:速度差不多的精度碾压;精度差不多的速度碾压。

     

    2 Relate Works

     

    作者对现有目标检测算法进行了总结:


    目前检测器通常可以分为以下几个部分,不管是two-stage还是one-stage都可以划分为如下结构,只不过各类目标检测算法设计改进侧重在不同位置:

    作者把所有的调优手段分为了两大类“Bag of freebies(免费礼包)”和“Bag of specials(特价包)”,细品 还真形象。

     

    • Bag of freebies

    是指在离线训练阶段为了提升精度而广泛使用的调优手段,而这种技巧并不在推断中使用,不会增加推断时间。

    • 数据类:

    数据增强(random erase/CutOut/hide-and-seek/grid mask/MixUp/CutMix/GAN)

    数据分布:two-stage的有难例挖掘,one-stage的有focal loss。

    • 特征图类:

    DropOut/DropConnect/DropBlock

    • Bounding Box目标函数类:

    MSE/ IoU loss/l1、l2 loss/GIoU loss/DIoU loss/CIoU loss

     

    • Bag of specials

    是指在推断过程中增加的些许成本但能换来较大精度提升的技巧。

    • 增大感受野类:

    SPP/ASPP/RFB

    • 注意力类:

    Squeeze-and-Excitation (SE)/Spa-tial Attention Module (SAM)

    • 特征集成类:

    SFAM/ASFF/BiFPN

    • 激活函数类:

    ReLu/LReLU/PReLU/ReLU6/Scaled ExponentialLinear Unit (SELU)/Swish/hard-Swish/Mish 

    • 后处理类:

    soft NMS/DIoU NMS 

     

     

    3 YOLOv4 Method

     

    3.1 架构选择

    作者选择架构主要考虑几方面的平衡:输入网络分辨率/卷积层数量/参数数量/输出维度。

     

    一个模型的分类效果好不见得其检测效果就好,想要检测效果好需要以下几点:

    • 更大的网络输入分辨率——用于检测小目标

    • 更深的网络层——能够覆盖更大面积的感受野

    • 更多的参数——更好的检测同一图像内不同size的目标


    假设符合上面几点要求的backboone就是预期的backbone,作者对CSPResNext50和CSPDarknet53进行了比较,如表1所示,表明CSPDarknet53神经网络是作为目标检测backbone的最优选择。

    为了增大感受野,作者使用了SPP-block,使用PANet代替FPN进行参数聚合以适用于不同level的目标检测。
     

    最终YOLOv4的架构出炉:

    • backbone:CSPResNext50

    • additional block:SPP-block

    • path-aggregation neck:PANet

    • heads:YOLOv3的heads

     

    3.2 BoF(免费礼包)和BoS(特价包)的选择

     

    CNN常用的通用技巧:

     

    • 对于训练激活函数,由于PReLU和SELU更难训练,而ReLU6是专门为量化网络设计的,因此将上述其余激活函数从候选列表中删除。

    • 在reqularization方法上,发表Drop-Block的人将其方法与其他方法进行了详细的比较,其regularization方法取得了很大的成果。因此,作者毫不犹豫地选择DropBlock作为regularization方法。

    • 在归一化方法的选择上,由于关注的是只使用一个GPU的训练策略,所以没有考虑syncBN。

     

    3.3 其他改进


    为了使设计的检测器更适合于单GPU上的训练,作者做了如下的附加设计和改进:

    • 介绍了一种新的数据增强Mosaic法和Self-AdversarialTraining 
      自对抗训练法。

    • 应用遗传算法选择最优超参数。

    • 改进SAM,改进PAN,和交叉小批量标准化(CmBN),使我们的设计适合于有效的训练和检测

     

    • Mosaic法

    是一种将4张训练图片混合成一张的新数据增强方法,这样可以丰富图像的上下文信息。如下图所示:

    这种做法的好处是允许检测上下文之外的目标,增强模型的鲁棒性。此外,在每一层从4个不同的图像批处理标准化计算激活统计,这大大减少了对大mini-batch处理size的需求。

     

    • AdversarialTraining自对抗训练

    这是一种新的数据扩充技术,该技术分前后两个阶段进行。

    在第一阶段,神经网络改变原始图像而不是网络权值。通过这种方式,神经网络对自身执行一种对抗性攻击,改变原始图像,从而造成图像上没有目标的假象。
    在第二阶段,训练神经网络对修改后的图像进行正常的目标检测。

     

    • CmBN

    表示CBN的修改版本,如下图所示,定义为跨微批量标准化(CmBN)。这仅收集单个批中的小批之间的统计信息。

     

    • SAM改进

    将SAM从空间上的attention修改为点上的attention,并将PAN的short-cut连接改为拼接,分别如图5和图6所示:

     

    3.4 YOLOv4架构总结

     

    • YOLOv4 架构:

    Backbone: CSPDarknet53

    Neck: SPP [25], PAN 

    Head: YOLOv3

     

    • YOLOv4 使用的调优技巧:

    BoF

    backbone:CutMix和mosaic数据增强,DropBlock正则化,类标签平滑。

    detector:ciu -loss,CmBN, DropBlock正则化,Mosaic数据增强,自对抗训练,消除网格敏感性,为单个groundtruth使用多个anchors,余弦退火调度器,最优超参数,随机训练形状

     

    BoS

    backbone:Mish激活、跨级部分连接(CSP)、多输入加权剩余连接(MiWRC)。

    detector:Mish activation,SPP-block, SAM-block, PAN path-aggregation block,DIoU-NMS.

     

     

    4 Experiments

     

    • 4.1 实验建立

     

    在ImageNet图像分类实验中,默认的超参数如下:

    • 训练步骤为8,000,000;

    • 批量尺寸为128,

    • 小批量尺寸为32;

    • 采用多项式衰减学习速率调度策略,

    • 初始学习速率为0.1,

    • 热身步骤为1000;

    • momentum和weight衰减分别设置为0.9和0.005。

     

    在BoF实验中,还增加了50%的训练步骤,验证了混合、切分、镶嵌、模糊数据增强和标签平滑正则化方法。

     

    在BoS实验中,使用与默认设置相同的超参数。比较了LReLU、Swish和Mish激活函数的作用。所有实验均使用1080Ti或2080Ti GPU进行训练。

     

    MS COCO目标检测实验中,默认的超参数为:

    • 训练步骤为500500;

    • 采用初始学习速率0.01的步长衰减学习速率策略,在400000步和450000步分别乘以因子0.1;

    • momentum衰减为0.9,weight衰减为0.0005。

    • 所有的架构都使用一个GPU来执行批处理大小为64的多尺度训练,而小批处理大小为8或4取决于架构和GPU内存限制。

    除了使用遗传算法进行超参数搜索实验外,其他实验均使用默认设置。

    • 遗传算法利用YOLOv3-SPP进行带GIoU损失的训练,搜索300个epoch的min-val5k集。

    • 遗传算法实验采用搜索学习率0.00261、momentum0.949、IoU阈值分配ground truth 0.213、损失归一化器0.07。

     

    对于所有实验,只使用一个GPU训练,因此不会使用syncBN等优化多个gpu的技术。

     

    • 4.2 不同特征对分类器训练的影响

     

    具体来说,如Fugure7所示,类标签平滑、不同数据增强技术、双侧模糊、MixUp、CutMix和Mosaic的影响,以及不同激活的影响,如Leaky-ReLU(默认)、Swish和Mish。结果如下表所示:

     

     

    • 4.3不同特征对检测器训练的影响

    进一步研究不同的Bag-of-Freebies (BoF-detector)对detector训练精度的影响,如表4所示。通过研究在不影响FPS的情况下提高检测精度的不同特征。

     

    进一步研究不同的bag-specials(boss-detector)对检测器训练精度的影响,包括PAN、RFB、SAM、Gaussian YOLO(G)、ASFF,如表5所示。

     

    • 4.4 不同的backbone和预先训练的重量对检波器训练的影响

     

    • 4.5 不同的mini-batch size对检测器训练的影响

     

    5 Results

     

    • 与目前较前沿检测模型的比较:

    由于不同的方法使用不同架构的gpu进行推理时间验证,我们将yolov4运行在通常采用的Maxwell架构、Pascal架构和Volta架构的gpu上,并将其与其他最先进的方法进行比较。

     

     

    • 表8列出了使用Maxwell GPU的帧率比较结果,可以是GTX Titan X (Maxwell)或者Tesla M40 GPU。

     

    • 表9列出了使用Pascal GPU的帧率比较结果,可以是Titan X (Pascal)、Titan Xp、GTX 1080 Ti或Tesla P100 GPU。

     

    • 表10列出了使用VoltaGPU的帧率比较结果,可以是Titan Volta,也可以是Tesla V100 GPU。

     

     

    展开全文
  • 精度,单精度和半精度

    万次阅读 多人点赞 2017-11-17 09:56:29
    浮点数是计算机上最常用的数据类型之一,有些语言甚至...半精度是英伟达在2002年搞出来的,双精度和单精度是为了计算,而半精度更多是为了降低数据传输和存储成本。 很多场景对于精度要求也没那么高,例如分布式深
  • 精度和双精度的区别

    万次阅读 多人点赞 2019-02-26 16:56:24
    1、单精度和双精度的字节数不同。前者占4个字节;后者占8个字节。 2、单精度和双精度有效数字位数不同。前者为8位;后者为16位。 3、单精度和双精度表示的数的范围不同。前者的数值范围在-3.40E+38 到 +3.40E+...
  • 精度和单精度

    千次阅读 2018-10-04 11:02:07
    精度比单精度表示的位数大 精确的位数多, 简单地说, foat表示的小数点位数少,double能表示的小数点位数多! 如 float: 1.0001 double:1.0000000001Float为单精度,内存中占4个字节,有效数位是7位(因为有正负,...
  • 精度与双精度区别

    千次阅读 2019-06-20 17:35:17
    精度与双精度区别(1)在内存中占有的字节数不同(2)有效数字位数不同(3)所能表示数的范围不同(4)在程序中处理速度不同 (1)在内存中占有的字节数不同 单精度浮点数在机内占4个字节 双精度浮点数在机内占8个...
  • 绝对精度与相对精度概念

    千次阅读 2020-09-15 15:27:18
    一、绝对精度就是ROI5区域的深度平均值 绝对精度就是测量常见九宫格表示法中ROI5区域的深度平均值 二、相对精度就是81%FOV区域深度拟合成平面后,将该区域所有点到平面的距离绝对值看作正态分布,并将其标准差作为...
  • 精度和双精度问题

    2020-08-24 10:46:54
    一,什么是单精度和双精度精度数(float)是指计算机表达实数近似值的一种方式。VB中Single(单精度浮点型)变量存储为 IEEE 32 位(4 个字节)浮点数值的形式,它的范围在负数的时候是从 -3.402823E38 到 -1....
  • int mod(string a,int b)//高精度 a%b { int ans=0; for(char &c : a) ans=(10*ans+c-'0')%b; return ans; } string div(string a,int b)//高精度 a/b { int i,r=0; string ans(""); if(a
  • 精度/双精度

    千次阅读 2019-02-09 18:17:02
    不管float还是double 在计算机上的存储都遵循IEEE规范,...精度主要取决于尾数部分的位数,float为23位,除去全部为0的情况以外,最小为2的-23次方,约等于1.19乘以10的-7次方,所以float小数部分只能精确到后面6...
  • 精度精度: 单精度,也即float,一般在计算机中存储占用4字节,也32位,有效位数为7位;双精度(double)在计算机中存储占用8字节,64位,有效位数为16位。 IEEE754规范: 单精度格式:1位符号,8位指数,23...
  • 浮点数精度

    千次阅读 2019-03-18 19:07:32
    printf("%.2lf",a);//这里是将a四舍五入输出 计算几何头疼的地方一般...精度问题则不好说,有时候一个精度问题就可能成为一道题的瓶颈,简直“画龙点睛”。这些年的题目基本是朝着越来越不卡精度的方向发展了,但是...
  • https://blog.csdn.net/huodianyan/article/details/44341521 精度精度修饰符
  • 精度除单精度

    千次阅读 2016-03-18 23:36:58
    精度除单精度 传入参数约定:传入第一参数为string类型,第二个为int型,返回值为string类型 算法思想:模拟手工除法。 算法复杂度:o(n). #include #include using namespace std; string div(string a,int b...
  • 精度浮点数与双精度浮点数区别

    千次阅读 2020-04-06 15:14:35
    精度浮点数与双精度浮点数区别 1、所占的内存不同 单精度浮点数占用4个字节(32位)存储空间来存储一个浮点数,包括符号位1位,阶码8位,尾数23位。 而双精度浮点数使用 8个字节(64位)存储空间来存储一个浮点数...
  • 精度除高精度

    千次阅读 2016-03-18 23:30:36
    精度除法 1)高精度除高精度 传入参数约定:传入第一第二个参数均为string类型,第三个为int型,返回值为string类型 算法思想:倒置,试商,高精度减法。 算法复杂度:o(n^2). #include #include #include using ...
  • 因为它会出现产生多位数和计算精度损失。 在Java代码中我们可以有以下3种方式转化 parseFloat("123.2") parseInt("121"); parseDouble()但是我们找了JavaScript中的方法,我们发现js中只有将String转为int、...
  • c语言格式(双精度精度

    千次阅读 2018-07-13 16:03:53
    精度为f双精度为lf
  • 精度除以高精度

    千次阅读 2018-02-21 19:33:57
    本人大一新生一枚 寒假训练时遇到高精度这题一开始用滚动减法 T了十发 在其他人的博客上看到说要把除数扩大才行 但是其他大神写的代码实在看的是云里雾里 自己就用自己理解的方式写了一遍 正好有写个博客的打算 因为...
  • 精度,双精度浮点存储表示 剖析float型的精度丢失问题
  • BigDecimal 精度问题

    千次阅读 2020-10-13 17:07:10
    BigDecimal 精度问题 在使用BigDecimal过程中,暂时遇到两个问题,都是精度问题,一个是精度丢失,一个是精度显示问题。 精度丢失 BigDecimal创建对象有很多种方式: 通过double类型去声明bigdecimal对象时,就发生...
  • 精度float 和双精度double

    千次阅读 2016-08-12 15:56:37
    精度实数在内存中占32bit 有效数字为6~7位 双精度实数占内存单元为64bit 有效数字为15~16位 没有说明时,实型常量是作为双精度处理的,若要使用单精度需在后面加上字母f或F,如123.45f
  • 卷尺精度标准_钢卷尺精度等级介绍

    千次阅读 2020-12-31 10:26:19
    钢卷尺是我们日常生活中运用和使用的比较多的...下面,我们来了解一下钢卷尺的精度等级和钢卷尺的主要用途,不了解的可以参考一下钢卷尺的精度等级。一、钢卷尺精度等级完整的是Δ=±[(0.3+0.2L)+0.2]mm,式中:L...
  • 精度乘单精度

    千次阅读 2016-03-18 23:33:53
    精度乘单精度 传入参数约定:传入第一个参数为string类型,,第二个参数为int型,返回值为string类型 算法思想:倒置相乘,然后统一处理进位,再还原。 算法复杂度:o(n). #include #include #include...
  • 精度地图介绍

    万次阅读 2019-01-17 11:42:06
    精度地图地图简介格式标准高精度地图VS传统地图制作过程 地图简介 供无人驾驶车辆是用的电子地图,精度达到厘米级; Aopllo高精度地图教程,视屏地址:...
  • float为单精度实数,double为双精度实数 float的精度是6位有效数字,取值范围是10的-38次方到10的38次方,float占用4字节空间 double的精度是15位有效数字,取值范围是10的-308次方到10的308次方,double占用8...
  • 验证集精度高于训练集精度的原因

    千次阅读 2020-05-07 20:35:08
    训练集的数据做了一系列的...训练的精度是每个batch产生的,而验证的精度一般是一个epoch后产生的,验证时的模型是训练一个个batch之后的,有一个的滞后性;可以说训练得差不多的模型用来验证,当然精度要高一点。 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 152,143
精华内容 60,857
关键字:

精度