Python压缩迭代器和Adagrad更新

时间:2017-04-05 06:03:04

标签: c# python

我试图理解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 dparammem正在zip函数之外进行修改。

这些for循环场景中这些变量如何运作?

5 个答案:

答案 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列表中的内容压缩,因此无论它们在何处都无关紧要,只要您通过其名称/标签正确处理它们即可。请注意,这可能不适用于intstr等不可变类型。请参阅此答案以获取更多解释 - 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'>数据类型的第一列。这是一个相当深刻的操作。