Python奇怪联会

Python奇怪联会,python,arrays,for-loop,numpy,neural-network,Python,Arrays,For Loop,Numpy,Neural Network,我一直在学习安,但我正在读的书中有Python的例子。问题是我从未用Python编写过代码,这些代码对我来说太难理解: sizes = [3,2,4] self.weights = [np.random.randn(y, x) for x, y in zip(sizes[:-1], sizes[1:])] 我读了一些关于它的内容,发现randn()函数返回一个数组,其中包含y元素和x维度,这些维度由0到1之间的随机数填充zip()将两个阵列连接成一个阵

我一直在学习安,但我正在读的书中有Python的例子。问题是我从未用Python编写过代码,这些代码对我来说太难理解:

sizes = [3,2,4]
self.weights = [np.random.randn(y, x) 
                    for x, y in zip(sizes[:-1], sizes[1:])]

我读了一些关于它的内容,发现
randn()
函数返回一个数组,其中包含
y
元素和
x
维度,这些维度由0到1之间的随机数填充
zip()
将两个阵列连接成一个阵列
size[:-1]
返回最后一个元素,而
size[1:://code>返回不带第一个元素的数组


但是有了所有这些,我仍然无法向自己解释这将生成什么。

大小[:-1]
将返回子列表
[3,2]
(即,除最后一个之外的所有元素)

size[1://code>将返回子列表
[2,4]
(即除第一个元素外的所有元素)

zip([a,b],[c,d])
给出了
[(a,c)、(b,d)]

因此,压缩上述两个列表将为您提供
[(3,2)、(2,4)]

砝码的构造是一个复杂的过程。因此,该代码相当于

weights = []

for x,y in [(3,2), (2,4)]:
       weights.append(np.random.randn(y, x))
因此,最终结果将与

[ np.random.randn(2,3), 
  np.random.randn(4,2) ]

这段代码生成一个列表并将其分配给self.weights属性(这可能在一个类中?这可以解释self)。第二行是列表理解。它生成一个列表,将函数randn应用于变量对(x,y)

这里发生了很多事情

让我们分解这个表达式:正如您所说的,
zip
将创建一个元组列表,其中包含
大小的每个元素及其后续元素(最后一个除外)

理解列表的工作原理如下:元组在变量
x
y
中分解,并将这些变量传递到
np.random.randn
以创建随机矩阵列表

这些矩阵的特点是第一维度(行)的长度由
大小的每个元素指定,第二维度(列)的长度由以下元素指定

有趣的是,矩阵有相容的维数,可以按顺序相乘,但我想这不是目的。
权重
列表中每个矩阵的目的是指定完全连接的神经元层之间的权重。祝你好运看起来是个有趣的项目

后脚本 由于您是初学者:您可以添加
导入pdb;pdb.set_trace()
语句在代码中的任意位置获取断点。然后,您可以复制并粘贴任何表达式的不同部分,以查看结果。 例如:

ipdb>打印尺寸
[3, 2, 4]
ipdb>打印尺寸[:-1]
[3, 2]
ipdb>打印尺寸[1:]
[2, 4]
ipdb>打印zip(大小[:-1],大小[1:])
[(3, 2), (2, 4)]
ipdb>打印[np.random.randn(y,x)表示拉链中的x,y(大小[:-1],大小[1:])]
[数组([[0.25933943,0.59855688,0.49055744],
[0.94602292,-0.8012292,0.56352986]),数组([0.81328847,-0.53234407],
[-0.272656  , -1.24978881],
[-1.2306653 ,  0.56038948],
[ 1.15837792,  1.19408038]])]

让我们把它分成几块:


将是一个列表。也就是说,做一些垃圾的东西,你会得到一个元素列表。通常看起来是这样的:

self.weights = [some_func(x) for x in a_list]
这相当于:

self.weights = []
for x in a_list:
    self.weights.append(some_func(x))

a
b
的元素分段组合成元组对:

(a1, b1), (a2, b2), (a3, b3), ...

这将遍历上面讨论的元组对


这表示获取列表
大小的所有元素,除了最后一个项(
-1

这说明要获取列表
大小
的所有元素,但第一个项除外


所以,最后把这些拼凑在一起,你会得到:

self.weights = [np.random.randn(y, x) for x, y in zip(sizes[:-1], sizes[1:])] 

这是一个列表理解,从第二项到最后一项,从第一项到下一项到最后一项,遍历第一个大小的元组对,根据这两个参数创建一个随机数,然后附加到一个存储为
self的列表。权重
大小[:-1]
返回数组直到(即不包括)它的最后一个元素
size[-1]
返回数组的最后一个元素。是的,我知道了,因为其他答案需要解释很多。事实证明,我对-1和zip的理解是错误的。@ChadSimmons:为了让你的回答更清楚,我已经自由地添加了一些细节。如果您不喜欢,请随时恢复我的编辑。此答案不正确<[(3,2)、(2,4)]中的x、y的代码>与[3,2]中的x的代码>不同:\n\t对于[2,4]中的y的代码>不同:
。第一种方法使用元组展开,在循环的第一次迭代中将x和y分别设置为3和2,在第二次迭代中将x和y分别设置为2和4。这意味着总共有两次迭代。第二个(嵌套循环)的总迭代计数为4。此外,您错误地计算了
np.random.randn(x,y)
,而不是
np.random.randn(y,x)
。因此,此代码的输出应该是
[np.random.randn(2,3),np.random.randn(4,2)]
。修复了x,ytranspose@ChadSimmons你的答案还是错的。尝试运行代码和OPs代码,并比较输出。你:
[np.random.randn(2,3),np.random.randn(4,3),np.random.randn(2,2),np.random.randn(4,2)]
。OP:
[np.random.randn(2,3),np.random.randn(4,2)]
。感谢您的解释。是的,这是一个有趣的项目。对我来说有点太难了,但我现在正在处理。另外,数字(3,2,4)只是为了更清楚的解释,我随机选择了它们。
(a1, b1), (a2, b2), (a3, b3), ...
for x, y in zip(a, b):
sizes[:-1]
sizes[1:]
self.weights = [np.random.randn(y, x) for x, y in zip(sizes[:-1], sizes[1:])]