读 《d2l:Chapter3. 线性神经网络 》随笔
讲一下Softmax回归
先说说自带mnist等库中的one-hot encoding
就是:一个向量,分量 (Row) == 类别
如:
A、B、C
对应 \((1, 0, 0)\)、\((0, 1, 0)\)、\((0, 0, 1)\)
softmax的用处:
\(softmax\)运算将输出变换成一个合法的类别预测分布
\(O = XW+b\)
\(Y=softmax(O)\)
由\(Softmax\)计算,可知
\(Loss(y, \hat y)=log\sum_{k=1}^qexp(o_k)-\sum_{j-1}^qy_jo_j\)
拓展:
CrossEntropyError
我们可以把交叉熵想象为“一个主观相信分布为为 \(Q\) 的观察者,在亲眼看到来自真实分布 \(P\) 的数据时,所感受到的平均惊异程度。
描述实际输出(概率)与期望输出(概率)的距离。交叉熵的值越小,两个概率分布就越接近。
(这里我交了PR,试图改掉原书中的这段落原本稀里糊涂的描述,但是似乎这本书的项目21年后没有更新了qwq)
极大似然估计(MLE)
- 似然性 \(L(θ|x)\) \(则是从观测结果\)\(x\)出发,分布函数的参数为 \(θ\)的可能性大小。
- \(L(θ|x)=P(X=x|θ)=p(x|θ)\)
- \(MLE:\hat\theta = \underset {\theta}{{arg\,max}}~lnL(X|\mu, \sigma)\)
- 统计学(十一)——最大似然估计 - 郝hai - 博客园
SoftMax 怎么来的?
先说Softmax函数:
其中:
- \(o_j\):模型原始的"得分"(logits),没有归一化,可以是任意实数
- 使用\(exp\)将得分正数化
- 把模型的原始输出转换成概率
再说交叉熵损失函数:
这是损失函数,衡量预测有多"糟糕",值越小说明预测越准。
- 其中 \(y_j\) 为真实标签中第\(j\)个类别的值(0或1)
- \(\hat y_j\) 为 模型预测的第\(j\)个类别的概率(0到1之间)
- \(q\) 为总数据库中的类别总数
- 而因为概率在0-1之间,\(log\) 值为负,加负号让损失为正
如果真实标签是y = [1, 0, 0],而模型预测ŷ = [0.7, 0.2, 0.1]
则有如下计算:
合起来就是: 在多分类问题中,我们先用softmax把模型的原始输出转成概率分布,然后用交叉熵损失来衡量这个概率分布与真实标签的差异。
然而,当 \(o_k\) 非常大时,很可能导致 \(softmax\) 值超出数据范围,甚至出现 \(NaN\) 。这就是 上溢 。为此,我们可以在每一项减去一个\(max(o_k)\)
但此时,会出现一些很小的负数。故 \(\hat y_j\) 有可能为 \(0\) ,从而 \(\log(\hat y_j)\) 为 \(-\inf\) 。这对反向传播非常不利。这就是 下溢 。
为此,我们避免计算 \(\exp(o_j - \max(o_k))\) ,直接使用 \(o_j - \max(o_k)\) ,因为 \(log(\exp(\cdot))\) 被抵消了,如下公式所展示的。
这就是 \(LogSumExp技巧\) 。
具体而言,就是这样变化:
而有
def softmax(X):
X_exp = torch.exp(X)
partition = X_exp.sum(1, keepdim=True)
return X_exp / partition
你可以对他求导:
细嗦Cross Entropy Error的实现
例如:
def cross_entropy(y_hat, y):
return -torch.log(y_hat[range(len(y_hat)), y])
y = torch.tensor([0, 2]) # 真实标签:样本0的类别是0,样本1的类别是2
y_hat = torch.tensor([[0.1, 0.3, 0.6], # 样本0的预测概率
[0.3, 0.2, 0.5]]) # 样本1的预测概率
>>> cross_entropy(y_hat, y)
一个是 \(0.1\),一个是 \(0.5\)。
进行 \(-log\) 运算后得到了 tensor([2.3026, 0.6931])
注:为了防止偏差大时出现 \(log(0)\) 之类的运算,应该给他每一项加上一个 \(\epsilon=10^{-8}\)。
如何评估训练精度 / 模型拟合效果?
def accuracy(y_hat, y): #@save
"""计算预测正确的数量"""
if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:
y_hat = y_hat.argmax(axis=1)
cmp = (y_hat.type(y.dtype) == y) #若涉及浮点数,可以用 ε 判断
return float(cmp.type(y.dtype).sum())
有:
y = torch.tensor([0, 2]) #答案真实选择
y_hat = torch.tensor([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]]) #预测选择
# 预测的最大值的ind分别在2、2,只有一个与y真实答案相同。故accuracy = 1 / 2
accuracy(y_hat, y) / len(y) #0.5

浙公网安备 33010602011771号