嵌套的 defaultdict - 更新值时出错
Nested defaultdict - Error when updating value
我有一本名为 dQalpha
的字典和另一本名为 dQbeta
的字典,它们分别计算工人的经验 dQalpha[worker]
和项目的难度 dQbeta[example]
。
我现在想添加一个名为 dQgamma
的新指标,它通过使用嵌套的 defaultdict dQgamma[worker][example]
来计算 worker 和 item 的相关性。
但是,如果我说 self.dQgamma=defaultdict(lambda: defaultdict(dict))
,我会收到错误消息
TypeError: float() argument must be a string or a number
如果我说 self.dQgamma=defaultdict(lambda: defaultdict(list))
,我会收到此错误消息
ValueError: setting an array element with a sequence.
有人可以帮忙吗?这是代码:
self.dQalpha={}
self.dQbeta={}
self.dQgamma=defaultdict(lambda: defaultdict(dict))
der = np.zeros_like(x)
i = 0
for worker in self.workers:
der[i] = -self.dQalpha[worker]
i = i + 1
for example in self.examples:
der[i] = -self.dQbeta[example]
i = i + 1
for worker in self.workers:
for example in self.examples:
der[i] = self.dQgamma[worker][example] #VALUE ERROR HERE
i = i + 1
return der
更新
如果我说 self.dQgamma=defaultdict(lambda: defaultdict(der.dtype))
,我得到
NameError: global name 'der' is not defined
编辑
def gradientQ(self, dtype):
self.optimize_df(x)
self.dQalpha={}
self.dQbeta={}
self.dQgamma=defaultdict(lambda: defaultdict(x.dtype))
#ERROR TypeError: first argument must be callable
for example, worker_label_set in self.e2wl.items():
dQb = 0
for (worker, label) in worker_label_set:
for tlabel in self.prior.keys():
sigma = self.sigmoid(self.alpha[worker]*self.expbeta(self.beta[example]))
delta = self.kronecker_delta(label,tlabel)
dQb = dQb + self.e2lpd[example][tlabel]*(delta-sigma)*self.alpha[worker]*self.expbeta(self.beta[example])\
*self.expgamma(self.gamma[worker][example])
self.dQbeta[example] = dQb - (self.beta[example] - self.priorbeta[example])
for worker, example_label_set in self.w2el.items():
dQa = 0
for (example, label) in example_label_set:
for tlabel in self.prior.keys():
sigma = self.sigmoid(self.alpha[worker]*self.expbeta(self.beta[example]))
delta = self.kronecker_delta(label,tlabel)
dQa = dQa + self.e2lpd[example][tlabel]*(delta-sigma)*self.expbeta(self.beta[example])\
*self.expgamma(self.gamma[worker][example])
self.dQalpha[worker] = dQa - (self.alpha[worker] - self.prioralpha[worker])
for worker, example_label_set in self.w2el.items():
for example, worker_label_set in self.e2wl.items():
dQg = 0
for tlabel in self.prior.keys():
sigma = self.sigmoid(self.alpha[worker]*self.expbeta(self.beta[example])*\
self.expgamma(self.gamma[worker][example]))
delta = self.kronecker_delta(label, tlabel)
dQg = dQg + self.e2lpd[example][tlabel]*(delta-sigma)*self.alpha[worker]*self.expbeta(self.beta[example])\
*self.expgamma(self.gamma[worker][example])
self.dQgamma[worker][example] = dQg - (self.gamma[worker][example] - self.priorgamma[worker][example])
def optimize_df(self,x):
# unpack x
i=0
for worker in self.workers:
self.alpha[worker] = x[i]
i = i + 1
for example in self.examples:
self.beta[example] = x[i]
i = i + 1
for worker in self.workers:
for example in self.examples:
self.gamma[worker][example] = x[i]
i = i + 1
self.gradientQ(x.dtype)
# pack x
der = np.zeros_like(x)
i = 0
for worker in self.workers:
der[i] = -self.dQalpha[worker] #Flip the sign since we want to minimize
i = i + 1
for example in self.examples:
der[i] = -self.dQbeta[example] #Flip the sign since we want to minimize
i = i + 1
for worker in self.workers:
for example in self.examples:
der[i]= self.dQgamma[worker][example] #Flip the sign since we want to minimize #TODO: fix
i = i + 1
return der
self.dQgamma[worker][example]
返回的值是字典或列表(取决于您声明它的方式)。
您尝试将其影响到一个需要标量的 numpy 数组。
这就是你出错的原因。
您应该声明 dQgamma
以使其 returns 成为您数组的兼容值:
self.dQgamma=defaultdict(lambda: defaultdict(der.dtype.type))
编辑
在下面的所有评论之后,我更新我的答案。
首先,其实是一个numpy.dtype
对象不可调用,您必须检索它的 type
可调用的属性。
所以我编辑了上面的代码块以匹配正确的语法。
然后,这是一个完整的示例,说明如何能够在函数中使用数组类型(我更改了一些命名以匹配 PEP8
约定。
from collections import defaultdict
import numpy as np
class MyClass:
def gradient(self, dtype):
self.d_qgamma=defaultdict(lambda: defaultdict(dtype.type))
print("Unset first level value:", self.d_qgamma[0])
print("Unset second level value:", self.d_qgamma[0][0])
self.d_qgamma['a'] = defaultdict(dtype.type, {'z': dtype.type(42)})
print("Set first level value:", self.d_qgamma['a'])
self.d_qgamma['b']['a'] = dtype.type("42")
print("Set second level value:", self.d_qgamma['b']['a'])
print("d_qgamma:", self.d_qgamma)
def optimize_df(self, x):
self.gradient(x.dtype)
der = np.zeros_like(x)
der[0] = self.d_qgamma['b']['a']
return der
if __name__ == '__main__':
print("der:", MyClass().optimize_df(np.zeros(4, np.float32)))
Unset first level value: defaultdict(<class 'numpy.float32'>, {})
Unset second level value: 0.0
Set first level value: defaultdict(<class 'numpy.float32'>, {'z': 42.0})
Set second level value: 42.0
d_qgamma: defaultdict(<function MyClass.gradient.<locals>.<lambda> at 0x7fcfd1663050>, {0: defaultdict(<class 'numpy.float32'>, {0: 0.0}), 'a': defaultdict(<class 'numpy.float32'>, {'z': 42.0}), 'b': defaultdict(<class 'numpy.float32'>, {'a': 42.0})})
der: [42. 0. 0. 0.]
如您所见,您将 numpy.dtype
类型的 x.dtype
传递给 gradient
函数。
然后,您可以使用此 dtype
对象并将其可调用的 type
属性检索到:
将其传递给您的 defaultdict
构造函数
self.d_qgamma=defaultdict(lambda: defaultdict(dtype.type))
转换您想要存储的任何值
self.d_qgamma['b']['a'] = dtype.type("42")
此处字符串 "42"
被转换为 float
,值为 42.0
。
我有一本名为 dQalpha
的字典和另一本名为 dQbeta
的字典,它们分别计算工人的经验 dQalpha[worker]
和项目的难度 dQbeta[example]
。
我现在想添加一个名为 dQgamma
的新指标,它通过使用嵌套的 defaultdict dQgamma[worker][example]
来计算 worker 和 item 的相关性。
但是,如果我说 self.dQgamma=defaultdict(lambda: defaultdict(dict))
,我会收到错误消息
TypeError: float() argument must be a string or a number
如果我说 self.dQgamma=defaultdict(lambda: defaultdict(list))
,我会收到此错误消息
ValueError: setting an array element with a sequence.
有人可以帮忙吗?这是代码:
self.dQalpha={}
self.dQbeta={}
self.dQgamma=defaultdict(lambda: defaultdict(dict))
der = np.zeros_like(x)
i = 0
for worker in self.workers:
der[i] = -self.dQalpha[worker]
i = i + 1
for example in self.examples:
der[i] = -self.dQbeta[example]
i = i + 1
for worker in self.workers:
for example in self.examples:
der[i] = self.dQgamma[worker][example] #VALUE ERROR HERE
i = i + 1
return der
更新
如果我说 self.dQgamma=defaultdict(lambda: defaultdict(der.dtype))
,我得到
NameError: global name 'der' is not defined
编辑
def gradientQ(self, dtype):
self.optimize_df(x)
self.dQalpha={}
self.dQbeta={}
self.dQgamma=defaultdict(lambda: defaultdict(x.dtype))
#ERROR TypeError: first argument must be callable
for example, worker_label_set in self.e2wl.items():
dQb = 0
for (worker, label) in worker_label_set:
for tlabel in self.prior.keys():
sigma = self.sigmoid(self.alpha[worker]*self.expbeta(self.beta[example]))
delta = self.kronecker_delta(label,tlabel)
dQb = dQb + self.e2lpd[example][tlabel]*(delta-sigma)*self.alpha[worker]*self.expbeta(self.beta[example])\
*self.expgamma(self.gamma[worker][example])
self.dQbeta[example] = dQb - (self.beta[example] - self.priorbeta[example])
for worker, example_label_set in self.w2el.items():
dQa = 0
for (example, label) in example_label_set:
for tlabel in self.prior.keys():
sigma = self.sigmoid(self.alpha[worker]*self.expbeta(self.beta[example]))
delta = self.kronecker_delta(label,tlabel)
dQa = dQa + self.e2lpd[example][tlabel]*(delta-sigma)*self.expbeta(self.beta[example])\
*self.expgamma(self.gamma[worker][example])
self.dQalpha[worker] = dQa - (self.alpha[worker] - self.prioralpha[worker])
for worker, example_label_set in self.w2el.items():
for example, worker_label_set in self.e2wl.items():
dQg = 0
for tlabel in self.prior.keys():
sigma = self.sigmoid(self.alpha[worker]*self.expbeta(self.beta[example])*\
self.expgamma(self.gamma[worker][example]))
delta = self.kronecker_delta(label, tlabel)
dQg = dQg + self.e2lpd[example][tlabel]*(delta-sigma)*self.alpha[worker]*self.expbeta(self.beta[example])\
*self.expgamma(self.gamma[worker][example])
self.dQgamma[worker][example] = dQg - (self.gamma[worker][example] - self.priorgamma[worker][example])
def optimize_df(self,x):
# unpack x
i=0
for worker in self.workers:
self.alpha[worker] = x[i]
i = i + 1
for example in self.examples:
self.beta[example] = x[i]
i = i + 1
for worker in self.workers:
for example in self.examples:
self.gamma[worker][example] = x[i]
i = i + 1
self.gradientQ(x.dtype)
# pack x
der = np.zeros_like(x)
i = 0
for worker in self.workers:
der[i] = -self.dQalpha[worker] #Flip the sign since we want to minimize
i = i + 1
for example in self.examples:
der[i] = -self.dQbeta[example] #Flip the sign since we want to minimize
i = i + 1
for worker in self.workers:
for example in self.examples:
der[i]= self.dQgamma[worker][example] #Flip the sign since we want to minimize #TODO: fix
i = i + 1
return der
self.dQgamma[worker][example]
返回的值是字典或列表(取决于您声明它的方式)。
您尝试将其影响到一个需要标量的 numpy 数组。 这就是你出错的原因。
您应该声明 dQgamma
以使其 returns 成为您数组的兼容值:
self.dQgamma=defaultdict(lambda: defaultdict(der.dtype.type))
编辑
在下面的所有评论之后,我更新我的答案。
首先,其实是一个numpy.dtype
对象不可调用,您必须检索它的 type
可调用的属性。
所以我编辑了上面的代码块以匹配正确的语法。
然后,这是一个完整的示例,说明如何能够在函数中使用数组类型(我更改了一些命名以匹配 PEP8
约定。
from collections import defaultdict
import numpy as np
class MyClass:
def gradient(self, dtype):
self.d_qgamma=defaultdict(lambda: defaultdict(dtype.type))
print("Unset first level value:", self.d_qgamma[0])
print("Unset second level value:", self.d_qgamma[0][0])
self.d_qgamma['a'] = defaultdict(dtype.type, {'z': dtype.type(42)})
print("Set first level value:", self.d_qgamma['a'])
self.d_qgamma['b']['a'] = dtype.type("42")
print("Set second level value:", self.d_qgamma['b']['a'])
print("d_qgamma:", self.d_qgamma)
def optimize_df(self, x):
self.gradient(x.dtype)
der = np.zeros_like(x)
der[0] = self.d_qgamma['b']['a']
return der
if __name__ == '__main__':
print("der:", MyClass().optimize_df(np.zeros(4, np.float32)))
Unset first level value: defaultdict(<class 'numpy.float32'>, {})
Unset second level value: 0.0
Set first level value: defaultdict(<class 'numpy.float32'>, {'z': 42.0})
Set second level value: 42.0
d_qgamma: defaultdict(<function MyClass.gradient.<locals>.<lambda> at 0x7fcfd1663050>, {0: defaultdict(<class 'numpy.float32'>, {0: 0.0}), 'a': defaultdict(<class 'numpy.float32'>, {'z': 42.0}), 'b': defaultdict(<class 'numpy.float32'>, {'a': 42.0})})
der: [42. 0. 0. 0.]
如您所见,您将 numpy.dtype
类型的 x.dtype
传递给 gradient
函数。
然后,您可以使用此 dtype
对象并将其可调用的 type
属性检索到:
将其传递给您的
defaultdict
构造函数self.d_qgamma=defaultdict(lambda: defaultdict(dtype.type))
转换您想要存储的任何值
self.d_qgamma['b']['a'] = dtype.type("42")
此处字符串
"42"
被转换为float
,值为42.0
。