随着脚本运行,机柜里的显卡啸叫声瞬间拔高了一个八度,那是硅基芯片在极限负荷下的哀鸣。
这一次,没有显存报错。数千个流处理器开始疯狂吞吐数据,机房里的温度直线上升,热浪滚滚而来。
“跑起来了!”程新竹惊喜地喊道,擦了擦额角的汗珠,兴奋地脱掉了卫衣,露出了里面粉色的HelloKitty短袖T恤衫。
屏幕上的进度条开始移动。
Loss损失函数曲线开始生成。
但是,仅仅过了几分钟,林允宁的脸色就变得比刚才更难看。
那条代表模型误差的Loss曲线,并没有像预期那样下降,反而在震荡了几次后,直接冲上了天际。
紧接着,屏幕上跳出了一行行令人绝望的字符:
Loss:NaN
Gradient:NaN
NaNNotaNumber,非数。
这意味着计算溢出了。
梯度在几十层的反向传播中,要么消失成了零,要么爆炸成了无穷大。
"ZETT。。。。。。"
林允宁盯着那些NaN,感觉像是被嘲讽了一样。
这不是硬件问题,这是算法的数学缺陷。
随着网络层数的加深,每一层参数的微小变化,都会导致输出数据的分布发生剧烈偏移。
这就好比是在打靶。
第一层射偏了一点点,第二层又偏了一点点。。。。。。
到了第50层,那个偏差已经被放大了无数倍,子弹早就不知道飞到哪里去了。
这叫“内部协变量偏移”InternalCovariateShift。
靶子一直在乱晃,枪手根本瞄不准。
林允宁试着调低学习率,试着更换初始化方法,试着加各种正则化手段。
没用。
那个NaN就像是个诅咒,顽固地霸占着屏幕。
如果不解决这个问题,深层网络就是个不可训练的废品。
时间一分一秒地过去。
很快到了深夜两点。
机房里的轰鸣声依旧,热得像蒸笼,但满头大汗的林允宁已经盯着那个NaN看了整整两个小时。
常规的方法已经试了个遍,他甚至尝试了梯度裁剪等等稀奇古怪的野路子。
结果还是没有改进。
只要层数一深,数据分布就会乱套。
"LA"
一杯冰咖啡放在了手边。
程新竹拉过一把椅子坐在他旁边,手里捧着厚厚的病理报告和生物化学工具书,准备陪着他熬夜,顺便查阅P450酶的资料。
“别急,慢慢来。”
程新竹喝了一口自己的抹茶拿铁,看着屏幕上乱跳的曲线,随口嘟囔道,“这AI跟养细胞似的,真娇气。