二维数组的乘积之和python

The sum of the products of a two-dimensional array python

我有 2 个包含一百万个元素的数组(根据具有每个像素亮度的图像创建) 我需要得到一个数字,它是同名数组元素的乘积之和。也就是说,A(1,1) * B(1,1) + A(1,2) * B(1,2)... 在循环中,python从循环(j1)中取出最后一个变量的值并开始运行通过它,然后将倒数第二个变量加1并再次运行最后一个,依此类推.我怎样才能让它计算同名的元素? res1, res2 - 数组(特别是 - numpy.ndarray) 或许这方面有现成的功能,但我需要尽可能开放,没有现成的。

sum = 0
for i in range(len(res1)):
    for j in range(len(res2[i])):
        for i1 in range(len(res2)):
                for j1 in range(len(res1[i1])):
                    sum += res1[i][j]*res2[i1][j1]

解决方案 1:

import numpy as np

a,b = np.array(range(100)), np.array(range(100))

print((a * b).sum())

方案二(更开放,因为使用了pd.DataFrame):

import pandas as pd
import numpy as np

a,b = np.array(range(100)), np.array(range(100))

df = pd.DataFrame(dict({'col1': a, 'col2': b}))

df['vect_product'] = df.col1 * df.col2

print(df['vect_product'].sum())

在我的回答的第一部分,我将解释如何直接修复您的代码。您的代码几乎是正确的,但在逻辑上存在一个大错误。在我回答的第二部分,我将解释如何使用 numpy 解决您的问题。 numpy 标准 python 包来处理数字数组。如果您要处理大量数字,没有理由不使用 numpy。

修复您的代码

您的代码使用 4 个嵌套的 for 循环,索引 ij 迭代第一个数组,索引 i1j1 迭代第二个数组。

因此,您将第一个数组中的每个元素 res1[i][j] 与第二个数组中的每个元素 res2[i1][j1] 相乘。这不是你想要的。您只想将第一个数组中的每个元素 res1[i][j] 与第二个数组中的相应元素 res2[i][j] 相乘:您应该对第一个和第二个数组使用相同的索引。因此应该只有两个嵌套的 for-loops.

s = 0
for i in range(len(res1)):
    for j in range(len(res1[i])):
        s += res1[i][j] * res2[i][j]

请注意,我将变量称为 s 而不是 sum。这是因为 sum 是 python 中的内置函数的名称。强烈建议隐藏内置名称。这是内置列表:https://docs.python.org/3/library/functions.html;不要使用该列表中的名称命名变量。

现在,一般来说,在 python 中,我们不喜欢在 for-loop 中使用 range(len(...))。如果您阅读 the official tutorial and its section on for loops,它表明 for-loop 可用于直接迭代元素,而不是索引。

例如,这里是如何在一个数组上迭代,对数组中的元素求和,而不使用 range(len(...)) 和索引:

# sum the elements in an array
s = 0
for row in res1:
    for x in row:
        s += x

这里row是整行,x是一个元素。我们根本不参考指数。

looping 的有用工具是内置函数 zipenumerate:

  • enumerate 如果您需要访问元素及其索引,则可以使用;
  • zip可用于同时迭代两个数组。

我不会展示 enumerate 的示例,但是 zip 正是您所需要的,因为您想要迭代两个数组:

s = 0
for row1, row2 in zip(res1, res2):
    for x, y in zip(row1, row2):
        s += x * y

你也可以使用内置函数 sum 来写这一切而没有 += 并且没有初始 = 0:

s = sum(x * y for row1,row2 in zip(res1, res2) for x,y in zip(row1, row2))

使用numpy

正如我在简介中提到的,numpy 是一个标准的 python 包,用于处理数字数组。一般来说,使用 numpy 对数组的操作比核心 python 中的数组循环要快得多。另外,使用 numpy 的代码通常比仅使用 core python 的代码更容易阅读,因为有很多有用的函数和方便的符号。例如,这里有一个简单的方法来实现你想要的:

import numpy as np

# convert to numpy arrays
res1 = np.array(res1)
res2 = np.array(res2)

# multiply elements with corresponding elements, then sum
s = (res1 * res2).sum()

相关文档:

使用 numpy 的两个简单快速的选项是:(A*B).sum()np.dot(A.ravel(),B.ravel())。第一种方法对 AB 的 element-wise 乘法的所有元素求和。 np.sum()默认为sum(axis=None),所以我们会得到一个数字。在第二种方法中,您在两个矩阵中创建一维视图,然后应用 dot-product 方法获取单个数字。

import numpy as np

A = np.random.rand(1000,1000)
B = np.random.rand(1000,1000)

s = (A*B).sum()  # method 1
s = np.dot(A.ravel(),B.ravel())  # method 2

第二种方法应该非常快,因为它不会创建 AB 的新副本,而是查看它们,因此不会分配额外的内存。