损失函数要能够通过一个数值衡量两个分布的差异 这里说的损失函数指AI是计算两个分布之间差异的函数 在框架中就是一个API调用,它背后有很强的数学理论支撑, 可以看作一种算法思想,一个数学公式的代码实现 损失函数要方便求导 深度学习中通过梯度下降法优化参数, mse这样的函数没问题 但作差再求绝对值,理论上也可以衡量两个分布的差异,但0的位置有两个导数,不方便求导处理 MAE: 绝对值, - 以绝对值的方式避免正负相冲 - 因求导代价大,故在工程上不常用; MSE :回归问题 - 以平方的方式避免正负相冲 - 以1为界线,会让小的更小,大的更大 - 因求导方便,工程上常用 交叉熵:多分类问题,本质还是按类别计算差异后再相加, CTC 10个常用的损失函数及Python代码实现! https://zhuanlan.zhihu.com/p/631580046 |
损失函数求是的两个数据分布之间的差异:模型输出 与 真实数据 深度学习中是批量计算,比如批次数为64,指的是64个模型输出与对应的真实数据形成的64对数据之间的计算 批次以矩阵的形成计算,矩阵的计算的最小单位是向计算,即一个模型输出与一个真实数据之间的计算 说到底,最小的有意义的单元还是一个模型输出与对应的真实数据之间的计算 批次为64,最终得到64个结果 - 此时会对批次结果求均值/求sum 化为一个单值的结果 - 即以整体的视角看待两个分布之间的差异 |
深度学习的基本结构有三步: 正向传播:配合损失函数,构建一个计算图,得到一个损失值 反射传播:在构建的计算图中,从损失函数这一步开始为每一个变量求一次梯度 梯度下降:或者叫参数优化,就是让参数向着预期的方向进一步,W=W-lr*W.grad 有这样一个问题,如果损失函数无限制下降怎么办? - 比如,0,-1,-2,.... - 这样函数就没有最小值了 实际上,负数只是数的一个维度/方向,0才是 确定的数中 唯一 一个 比无穷小还要小的 数/常量 这里期望的函数最小值就是0,就是认为两个分布完全重合/一致的时候,损失函数的差异为0 所以在设置损失函数的时候,会让结果呈现为 正值 加绝对值,平方就是常用的技巧 |
|
|
pad不参与损失函数计算
for epoch in range(1): for i, (x, y) in enumerate(loader): # x = [8, 50] # y = [8, 51] # 在训练时,是拿y的每一个字符输入,预测下一个字符,所以不需要最后一个字 # 主要还是因为y是51,x是50,二者要保持一致 # [8, 50, 39] pred = model(x, y[:, :-1]) # [8, 50, 39] -- [400, 39] # 多少个单词,展平到单词维度,准备按批次计算偏差 pred = pred.reshape(-1, 39) # [8, 51] -- [400] # y[:,0]为SOS标记的索引 y = y[:, 1:].reshape(-1) # 忽略pad,忽略一个批次中所有的PAD select = y != dict_y['<PAD>'] pred = pred[select] #选出pred中所有单词位置的向量 y = y[select] #选出y中所有单词的索引,形成一个新的全是单词索引的向量 #pred[-1,dict_count],y单词索引向量 #比如,y[0]=2,one hot转标签向量为[0,0,1],期望模型输出的向量为[0,0.2,0.8],最好是[0,0.1,0.9], #损失减少的方向就是index=2位置上的数据尽量接近1,其他位置尽量逼近0 loss = loss_func(pred, y) optim.zero_grad() loss.backward() optim.step() if i % 1000 == 0: # [select, 39] -- [select] pred = pred.argmax(1) correct = (pred == y).sum().item() accuracy = correct / len(pred) lr = optim.param_groups[0]['lr'] print(epoch, i, lr, loss.item(), accuracy)
重全局轻个体
这里同样也说明一个情况: 损失函数的计算不是按某个样本向量 而是按批次,一次计算一批向量,同时更新一批向量的梯度