我试图理解Andrej Karpathy作为指南给出的优秀代码:https://gist.github.com/karpathy/d4dee566867f8291f086
我是python的新手,还在学习!
我正在尽力从链接中了解以下代码:
# perform parameter update with Adagrad
for param, dparam, mem in zip([Wxh, Whh, Why, bh, by],
[dWxh, dWhh, dWhy, dbh, dby],
[mWxh, mWhh, mWhy, mbh, mby]):
mem += dparam * dparam
param += -learning_rate * dparam / np.sqrt(mem + 1e-8) # adagrad update
我已阅读zip function并做了一些简短测试,试图了解其工作原理。
到目前为止我所知道的,5次迭代,param == Wxh在第一次迭代但不在那里......
理想情况下,我正在尝试将此代码转换为C#,为此,我需要了解它。
在引用Python iterator and zip时,我们将每个数组的每个项目相乘:
param = Wxh * dWxh * mWxh
但是变量param
dparam
和mem
正在zip函数之外进行修改。
这些for循环场景中这些变量如何运作?
答案 0 :(得分:1)
用zip编写一个简单的for循环将帮助你学到很多东西。
例如:
for a, b, c in zip([1,2,3],
[4,5,6],
[7,8,9]):
print a
print b
print c
print "/"
此功能将打印:1 4 7/2 5 8/3 6 7
这样zip函数只需将这三个列表放在一起,然后使用三个变量param,dparam,mem来引用不同的列表。
在每次迭代中,这三个变量引用相应列表中的某个项目,就像for i in [1, 2, 3]:
一样。
这样,你只需要写一个for循环而不是三个,来为每个参数更新grads:Wxh,Whh,Why,bh,by。
在第一次迭代中,只有遵循adagrad规则使用dWxh和mWxh更新Wxh。其次,使用dWhh和mWhh更新Whh,等等。
答案 1 :(得分:1)
zip
做了什么?
引自官方文件:
Zip返回一个元组列表,其中第i个元组包含第i个元组 来自每个参数序列或迭代的元素。归来了 list的长度被截断为最短参数的长度 序列
这意味着,
>>> zip(["A", "B"], ["C", "D"], ["E", "F"])
[('A', 'C', 'E'), ('B', 'D', 'F')]
所以现在,当你循环时,你实际上有一个元组列表。内容如。
# These are strings here but in your case these are objects
[('Wxh', 'dWxh', 'mWxh'), ('Whh', 'dWhh', 'mWhh'), ('Why', 'dWhy', 'mWhy'),
('bh', 'dbh', 'mbh'),('by', 'dby', 'mby')]
到目前为止我所知道的,第一次迭代时有5次迭代,param == Wxh 但不是......
你是对的,现在让我们分析你的循环。
for param, dparam, mem in m:
print(param, dparam, mem)
# Which prints
('Wxh', 'dWxh', 'mWxh')
('Whh', 'dWhh', 'mWhh')
('Why', 'dWhy', 'mWhy')
('bh', 'dbh', 'mbh')
('by', 'dby', 'mby')
这意味着,在每次迭代中,params
获取第零个索引元组值,dparam
获取第一个,mem
获得第二个。
现在,当我在for循环范围内输入param
时,我得到了
>>> param
'by'
这意味着params仍然保留对by
对象的引用。
来自官方文件:
for循环对目标中的变量进行赋值 名单。 [...]循环时,不会删除目标列表中的名称 完了,但如果序列是空的,它们就不会存在 完全由循环分配。
答案 2 :(得分:1)
任何序列(或可迭代的)都可以使用简单的赋值操作解压缩到变量中。唯一的要求是变量和结构的数量与序列匹配。例如:
for param, dparam, mem in zip([Wxh, Whh, Why, bh, by],
[dWxh, dWhh, dWhy, dbh, dby],
[mWxh, mWhh, mWhy, mbh, mby]):
mem += dparam * dparam
param += -learning_rate * dparam / np.sqrt(mem + 1e-8)
lets say:
iterable1 = [Wxh, Whh, Why, bh, by]
iterable2 = [dWxh, dWhh, dWhy, dbh, dby]
iterable3 = [mWxh, mWhh, mWhy, mbh, mby]
here zip() returns [(Wxh, dWxh, mWxh), (Whh, dWhh, mWhh), (Why, dWhy, mWhy), (bh, dbh, mbh), (by, dby, mby)]
on 1st iteration:
param, dparam, mem = (Wxh, dWxh, mWxh)
so,
param = Wxh
dparam = dWxh
mem = mWxh
mem = mem + (dparam * dparam) = mWxh + (dWxh * dWxh)
param = param + (-learning_rate * dparam / np.sqrt(mem + 1e-8)) = Wxh + (-learning_rate * dWxh / np.sqrt(mWxh + (dWxh * dWxh) + 1e-8)
on 2nd iteration:
param, dparam, mem = (Whh, dWhh, mWhh)
so,
param = Whh
dparam = dWhh
mem = mWhh
an so on.
在这种情况下,zip()按照标准文档是“zip()创建一个迭代器,聚合来自每个iterables的元素。返回元组的迭代器,其中第i个元组包含每个元素的第i个元素参数序列或迭代。所以,对于你的情况
$platformi = $_POST['platformi'];
答案 3 :(得分:0)
Python仅将变量视为标签或名称标签。由于您已将list
列表中的内容压缩,因此无论它们在何处都无关紧要,只要您通过其名称/标签正确处理它们即可。请注意,这可能不适用于int
或str
等不可变类型。请参阅此答案以获取更多解释 - Immutable vs Mutable types。
答案 4 :(得分:0)
谢谢大家的精彩答案!
我的蟒蛇技能很差,所以我很抱歉!
import numpy as np
print('----------------------------------------')
print('Before modification:')
a = np.random.randn(1, 3) * 1.0
print('a: ', a)
b = np.random.randn(1, 3) * 1.0
print('b: ', b)
c = np.random.randn(1, 3) * 1.0
print('c: ', c)
print('----------------------------------------')
for a1, b1, c1 in zip([a, b, c], [a, b, c], [a, b, c]):
a1 += 10 * 0.01
b1 += 10 * 0.01
c1 += 10 * 0.01
print('a1 is Equal to a: ', np.array_equal(a1, a))
print('a1 is Equal to b: ', np.array_equal(a1, b))
print('a1 is Equal to c: ', np.array_equal(a1, c))
print('----------------------------------------')
print('After modification:')
print('a: ', a)
print('b: ', b)
print('c: ', c)
print('----------------------------------------')
输出:
----------------------------------------
Before modification:
a: [[-0.79535459 -0.08678677 1.46957521]]
b: [[-1.05908792 -0.90121069 1.07055281]]
c: [[ 1.18976226 0.24700716 -0.08481322]]
----------------------------------------
a1 is Equal to a: True
a1 is Equal to b: False
a1 is Equal to c: False
----------------------------------------
a1 is Equal to a: False
a1 is Equal to b: True
a1 is Equal to c: False
----------------------------------------
a1 is Equal to a: False
a1 is Equal to b: False
a1 is Equal to c: True
----------------------------------------
After modification:
a: [[-0.69535459 0.01321323 1.56957521]]
b: [[-0.95908792 -0.80121069 1.17055281]]
c: [[ 1.28976226 0.34700716 0.01518678]]
jyotish完全正确,并回答了我所遗漏的事情!谢谢!
对于C#,我想我会在这里看一下Parallel.For
实现。
编辑:
对于其他人也学习,我也发现看到这段代码很有用:
import numpy as np
print('----------------------------------------')
print('Before modification:')
a = np.random.randn(1, 3) * 1.0
print('a: ', a)
b = np.random.randn(1, 3) * 1.0
print('b: ', b)
c = np.random.randn(1, 3) * 1.0
print('c: ', c)
print('----------------------------------------')
for a1, b1, c1 in zip([a, b, c], [a, b, c], [a, b, c]):
a1[0][0] = 10 * 0.01
print('a1 is Equal to a: ', np.array_equal(a1, a))
print('a1 is Equal to b: ', np.array_equal(a1, b))
print('a1 is Equal to c: ', np.array_equal(a1, c))
print('----------------------------------------')
print('After modification:')
print('a: ', a)
print('b: ', b)
print('c: ', c)
print('----------------------------------------')
输出:
----------------------------------------
Before modification:
a: [[-0.78734047 -0.04803815 0.20810081]]
b: [[ 1.88121331 0.91649695 0.02482977]]
c: [[-0.24219954 -0.10183608 0.85180522]]
----------------------------------------
a1 is Equal to a: True
a1 is Equal to b: False
a1 is Equal to c: False
----------------------------------------
a1 is Equal to a: False
a1 is Equal to b: True
a1 is Equal to c: False
----------------------------------------
a1 is Equal to a: False
a1 is Equal to b: False
a1 is Equal to c: True
----------------------------------------
After modification:
a: [[ 0.1 -0.04803815 0.20810081]]
b: [[ 0.1 0.91649695 0.02482977]]
c: [[ 0.1 -0.10183608 0.85180522]]
----------------------------------------
如您所见,仅修改我正在使用的<class 'numpy.ndarray'>
数据类型的第一列。这是一个相当深刻的操作。