采用以下示例:
boltzmann <- function(x, t=0.1) { exp(x/t) / sum(exp(x/t)) }
z=rnorm(10,mean=1,sd=0.5)
exp(z[1]/t)/sum(exp(z/t))
[1] 0.0006599707
boltzmann(z)[1]
[1] 0.0006599707
exp
函数中的boltzmann
似乎对元素和向量进行操作,并知道何时做正确的事情。 sum
“展开”输入向量并在值上应用表达式吗?有人可以解释这在R中是如何工作的吗?
编辑:感谢您对R n00b的所有评论,澄清和耐心。总之,对于我来自其他语言的原因,这个原因并不是很明显。以python为例。您首先计算总和,然后计算向量中每个元素的值。
denom = sum([exp(v / t) for v in x])
vals = [exp(v / t) / denom for v in x]
而R是sum(exp(x/t))
可以内联计算。
答案 0 :(得分:4)
An Introduction to R,Section 2.2: Vector arithmetic中解释了这一点。
矢量可用于算术表达式,在这种情况下 操作是逐个元素执行的。载体中出现的载体 相同的表达不需要都具有相同的长度。如果他们不是, 表达式的值是一个与长度相同的向量 表达式中出现的最长向量。更短的向量 表达式回收根据需要(可能是分数) 直到它们匹配最长矢量的长度。特别是a 常数只是重复。所以使用上面的赋值命令
x <- c(10.4, 5.6, 3.1, 6.4, 21.7) y <- c(x, 0, x) v <- 2*x + y + 1
生成一个长度为11的新向量v,通过加在一起构造, 元素逐元素,2 * x重复2.2次,y重复一次,然后 1次重复11次。
答案 1 :(得分:3)
如果分别评估分子和分母,这可能会更清楚:
x = rnorm(10,mean=1,sd=0.5)
t = .1
exp(x/t)
# [1] 1.845179e+05 6.679273e+03 4.379369e+06 1.852623e+06 9.960374e+02
# [6] 1.359676e+09 6.154045e+03 1.777027e+01 1.070003e+04 6.217397e+04
sum(exp(x/t))
# [1] 2984044296
由于分子是长度为10的向量,分母是长度为1的向量,因此除法返回长度为10的向量。
由于你有兴趣将它与Python进行比较,想象一下将以下两条规则添加到Python中(顺便说一句,这些规则类似于numpy
中数组的用法):
如果您将列表除以数字,它会将列表中的所有项目除以数字:
[2, 4, 6, 8] / 2
# [1, 2, 3, 4]
Python中的函数exp
是“矢量化的”,这意味着当它应用于列表时,它将应用于列表中的每个项目。但是,总和仍然按照您的预期方式运作。
exp([1, 2, 3]) => [exp(1), exp(2), exp(3)]
在这种情况下,想象一下如何在Python中评估此代码:
t = .1
x = [1, 2, 3, 4]
exp(x/t) / sum(exp(x/t))
使用这两个简单的规则将遵循以下简化:
exp([v / t for v in x]) / sum(exp([v / t for v in x]))
[exp(v / t) for v in x] / sum([exp(v / t) for v in x])
现在你知道它是如何知道差异的吗?
答案 2 :(得分:1)
向量化在R中有几个略微不同的含义。
这可能意味着接受矢量输入,转换每个元素,并返回一个矢量(如exp
那样)。
它还可以表示接受向量输入并计算一些摘要统计量,然后返回标量值(如mean
那样)。
sum
符合第二种行为,但也有第三种向量化行为,它会在输入中创建一个摘要统计量。例如,尝试sum(1, 2:3, 4:6)
。