Update demo and readme.
This commit is contained in:
		
							parent
							
								
									eed28ac06e
								
							
						
					
					
						commit
						9a8434df61
					
				| 
						 | 
				
			
			@ -0,0 +1,65 @@
 | 
			
		|||
import torch
 | 
			
		||||
 | 
			
		||||
data_size = 20
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
torch.manual_seed(1234)
 | 
			
		||||
x_data = torch.abs(torch.randn((data_size)))
 | 
			
		||||
y_data = 10 * x_data
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MUL(torch.autograd.Function):
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def forward(ctx, input, weight):
 | 
			
		||||
        ctx.save_for_backward(input, weight)
 | 
			
		||||
        return input * weight
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def backward(ctx, grad_output):
 | 
			
		||||
        input, weight = ctx.saved_tensors
 | 
			
		||||
        grad_weight = input * grad_output
 | 
			
		||||
        grad_input = weight * grad_output
 | 
			
		||||
        print(f"grad_output:{grad_output.item():.4f}")
 | 
			
		||||
        return grad_input, grad_weight
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class LinearModel(torch.nn.Module):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        super().__init__()
 | 
			
		||||
        self.weight = torch.nn.Parameter(torch.tensor([[1.0]]), requires_grad=True)
 | 
			
		||||
 | 
			
		||||
    def forward(self, x):
 | 
			
		||||
        return MUL.apply(x, self.weight)
 | 
			
		||||
        return x * self.weight
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
model = LinearModel()
 | 
			
		||||
criterion = torch.nn.MSELoss()
 | 
			
		||||
optimizer = torch.optim.SGD(model.parameters(), lr=1.0)
 | 
			
		||||
loss_history = []
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
for step in range(data_size):
 | 
			
		||||
    y_pred = model(x_data[step])
 | 
			
		||||
 | 
			
		||||
    # loss = criterion(y_pred, y_data[step])
 | 
			
		||||
    # loss = y_data[step] / y_pred - 1.0
 | 
			
		||||
    # loss = torch.abs(y_data[step] - y_pred)
 | 
			
		||||
    # loss = y_data[step] - y_pred
 | 
			
		||||
    loss = (y_data[step] - y_pred) * (y_data[step] - y_pred)
 | 
			
		||||
 | 
			
		||||
    loss_history.append(loss.item())
 | 
			
		||||
 | 
			
		||||
    optimizer.zero_grad()
 | 
			
		||||
    loss.backward()
 | 
			
		||||
 | 
			
		||||
    if (step + 1) % 1 == 0:
 | 
			
		||||
        w = model.weight.item()
 | 
			
		||||
        print(
 | 
			
		||||
            f"Step {step+1}: w={w:.4f}  loss={loss.item():.6f}  input:{x_data[step]:.4f}  output:{y_pred.item():.4f}  label:{y_data[step].item():.4f}  w_grad:{model.weight.grad.item():.4f}"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    optimizer.step()  # w = w - lr * ∇w[5](@ref)
 | 
			
		||||
 | 
			
		||||
test_x = torch.tensor([[5.0]])
 | 
			
		||||
print(f"\n预测结果: x=5 → y={model(test_x).item():.2f}")
 | 
			
		||||
| 
						 | 
				
			
			@ -1,13 +1,39 @@
 | 
			
		|||
 | 
			
		||||
## 定义
 | 
			
		||||
 | 
			
		||||
### 梯度
 | 
			
		||||
    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的关系越相关
 | 
			
		||||
 | 
			
		||||
## 问题
 | 
			
		||||
 | 
			
		||||
1. 在一串的binary lut网络中
 | 
			
		||||
* 在一串的binary lut网络中
 | 
			
		||||
    1. 如果每个卷积的channel相互之间没有关系
 | 
			
		||||
    2. 中间插入一层,交换各个channel之间的数据,生成新的相同数量的channel
 | 
			
		||||
    3. 方法2的效果很差
 | 
			
		||||
        1. 好像是破坏了训练,可能是训练的方法不对
 | 
			
		||||
        1. 好像是破坏了训练,可能是训练的方法不对,梯度下降不适合这种模型
 | 
			
		||||
        2. 最终分类是10,10个输出之间有关系就会很差?
 | 
			
		||||
2. unfold输出的维度不对
 | 
			
		||||
* 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. 梯度正负无所谓,需要随机?
 | 
			
		||||
 | 
			
		||||
* unfold输出的维度不对
 | 
			
		||||
    1. LUT不是对卷积核进行计算,更容易收敛,但是精度没有更高
 | 
			
		||||
    2. LUT不是对卷积核进行计算,不容易收敛,精度差不多
 | 
			
		||||
* 好像只有AdamW优化器可以优化参数,明显收敛
 | 
			
		||||
* LUT的输出进行二值化对精度有影响,大概94->81
 | 
			
		||||
		Loading…
	
		Reference in New Issue