我正在学习神经网络。
当我转置特征时,得到以下输出:
import torchdef activation(x): return 1/(1+torch.exp(-x))### 生成一些数据torch.manual_seed(7) # 设置随机种子以确保可预测性# 特征是5个随机正态变量features = torch.randn((1, 5))# 我们数据的真实权重,再次是随机正态变量weights = torch.randn_like(features)# 以及一个真实的偏置项bias = torch.randn((1, 1))product = features.t() * weights + biasoutput = activation(product.sum())
tensor(0.9897)
然而,如果我转置权重,我得到不同的输出:
weights_prime = weights.view(5,1)prod = torch.mm(features, weights_prime) + biasy_hat = activation(prod.sum())
tensor(0.1595)
为什么会这样?
更新
我看到了这个:
y = activation((features * weights).sum() + bias)
为什么一个矩阵features(1,5)可以与另一个矩阵weights(1,5)相乘而不需要先转置weights?
更新2
在阅读了几篇文章后,我意识到
matrixA * matrixB 与 torch.mm(matrixA,matrixB) 和 torch.matmul(matrixA,matrixB) 是不同的。
有人能确认我对这三者之间的理解吗?
-
所以 * 表示逐元素乘法,而 torch.mm() 和 torch.matmul() 是矩阵乘法。
-
torch.mm() 和 torch.matmul() 之间的区别:mm() 专门用于2维矩阵,而 matmul() 可以用于更复杂的情况。
-
在上述链接中提到的Udacity编程练习中,神经网络需要逐元素乘法。
更新3
为了帮助有同样困惑的人,这里是视频截图:
这是视频链接: https://www.youtube.com/watch?time_continue=98&v=6Z7WntXays8&feature=emb_logo
回答:
查看 https://pytorch.org/docs/master/generated/torch.nn.Linear.html
在torch中,典型的线性(全连接)层使用形状为 (N,*,in_features)
的输入特征和形状为 (out_features,in_features)
的权重,产生形状为 (N,*,out_features)
的输出。这里N是批量大小,*是任何数量的其他维度(可能为零)。
实现方式是:
output = input.matmul(weight.t())
所以,答案是根据惯例,你的公式都不正确;标准公式是上面的那个。
由于你是从头开始实现的,你可以使用非标准形状;只要保持一致,它可能会工作,但我并不推荐这样做来学习。你的代码中1和5代表什么不清楚,但可能是你想要5个输入特征和一个输出特征,批量大小为1。在这种情况下,标准形状应该是输入 = torch.randn((1, 5))
,批量大小=1,输入特征=5,权重 = torch.randn((5, 1))
,输入特征=5,输出特征=1。
权重永远不应该与特征具有相同形状;因此 weights = torch.randn_like(features)
没有意义。
最后,对于你的实际问题:
“在神经网络中应转置特征还是权重?” – 在torch的惯例中,你应该转置权重,但首先用特征进行matmul操作。其他框架可能有不同的惯例;只要权重的in_features维度与输入的num_features维度相乘,它就会工作。
“为什么会这样?” – 这两个是完全不同的计算;没有理由认为它们会产生相同的结果。
“所以 * 表示逐元素乘法,而 torch.mm() 和 torch.matmul() 是矩阵乘法。” – 是的;mm是仅限矩阵-矩阵的,matmul是向量-矩阵或矩阵-矩阵,包括批处理版本的相同 – 检查文档以了解matmul可以做的一切(这有点多)。
“torch.mm() 和 torch.matmul() 之间的区别:mm() 专门用于2维矩阵,而 matmul() 可以用于更复杂的情况。” – 是的;最大的区别是matmul可以广播。当你特别意图这样做时使用它;使用mm来防止意外广播。
“在上述链接中提到的Udacity编程练习中,神经网络需要逐元素乘法。” – 我对此表示怀疑;这可能是Udacity代码中的一个错误。这段代码 weights = torch.randn_like(features)
在任何情况下看起来都像是错误;权重的维度与特征的维度具有不同的含义。