
## 定义

### binary网络的梯度
    1. 预测变化对整体损失 L 的影响程度, 参数θ在当前点的变化对损失值的影响方向和幅度
    2. grad物理含义：loss L = 0 的时候，需要的变化量
    3. w = w - grad * lr 若梯度为正，权重应该减小
    4. w_grad = output_grad * input, input越大，grad越大，w调整的量越大
        1. input越大->对weight的放大倍数越大->才能达到loss=0的调整量
        2. 所以，weight的调整比例应该越大，才能弥补小input的loss=0
    5. 梯度的大小反应了影响损失的“快慢”
        1. 梯度大​​ → 损失曲面陡峭 → 微小变化导致损失剧烈波动
        2. 梯度大，微小变化就可以使得loss变化一个单位
        2. 梯度大，和loss的关系越相关
    6. input的梯度计算
        1. 对于repeat的操作，需要对grad_output进行sum
        2. 对于bits->index的操作，需要对grad_output进行repeat

## 问题

* 在一串的binary lut网络中插入一层，交换各个channel之间的数据，生成新的相同数量的channel
    1. 效果很差
        1. 好像是破坏了训练，可能是训练的方法不对,梯度下降不适合这种模型
        2. 最终分类是10，10个输出之间有关系就会很差？
    2. 模型总是在把原来的信息进行repeat，不影响最终的精度，进行全连接就有动态选择就很差
    3. 最后一层的repeat数量对精度的影响
        1. >10 因为前面的数量不够，导致精度不如10
        2. >1 and <10 因为10个输出结果中间有交叉数据（可能是最后一层交叉导致的），导致精度不如10
        3. 为什么 最后一层，10 x 80 精度不如 1 x 80 ？？？？
* LUT层梯度计算的问题
    1. 发现LUT的反向计算grad_weight没有考虑weight本来的正负符号，grad表示的是>0的置信度
        1. 考虑梯度符号之后，由于整个选择的梯度是一个，没有机会变换到别的
        2. weight_grad:后面一级计算的grad_input，对于当前weight的grad是一样的，没有机会变换到别的
        3. 当前的选择不可信后的grad会导致直接0/1整体取反,而不会改变分布
    2. 输出级别用于criterion的LUT的梯度计算和基于Binary的输出1概率的梯度的计算方式不一样
        1. LUT的是输出1的概率，不能直接和criterion的梯度进行下降
    3. grad input的目标是，要不要更换别的index
        1. 梯度的大小表示更换别的index的程度
        2. 梯度正负无所谓，需要随机？
    4. repeat是选择不同的weight，index是同样的，如果repeat出来的loss sum等0，那么这个index的不能下降，梯度等0

* unfold输出的维度不对
    1. LUT不是对卷积核进行计算,更容易收敛，但是精度没有更高
    2. LUT不是对卷积核进行计算,不容易收敛，精度差不多
* 好像只有AdamW优化器可以优化参数，明显收敛
* LUT的输出进行二值化对精度有影响，大概93->81
* LUT参数初始化为1.0，收敛速度非常快，好像比随机精度高，大概81->93
* 把input的Repeat从LutGroup移到Lut里面后
    1. 训练的收敛速度快很多（最快3epoch基本能收敛）
    2. 稳定性很大，对lr不敏感
    3. Repeat的反向由Lut统一处理，而不是pytorch自动反向，可能修复了一些维度处理的错误
        1. 经过这个改动后，把grad_input计算回归到原来的方式 grad_input = grad_output，发现精度提升非常大
        2. 原来的方式可能因为一些代码的bug导致的，learning rate的设置也不敏感了, 权重的初始化值也不敏感了
* **增加全连接的映射Lut不能提高模型最终精度的问题**