python - numpy 查找矩阵行中所有数字对组合的乘积
问题描述
我得到了一个 nxm 矩阵,我的目标是找到所有特征的“叉积”,特别是乘积矩阵中的每一行的形式为 x ij jx ij' , j < j', j = 1, . . . , 米, j' = (j + 1), . . . , m 使得结果行是该行中所有对组合的乘积。有没有一种优雅的方法可以使用 numpy 函数而不是 python 循环来做到这一点?
编辑:示例
[1, 2, 3, 4]
应该成为
[1*2, 1*3, 1*4, 2*3, 2*4, 3*4]
这给了:
[2, 3, 4, 6, 8, 12]
解决方案
基本上,您想要生成包含原始集合的 2 个元素的所有可能子集。
简短的回答:
# With m = 4
c = np.multiply(*np.add(np.triu_indices(4,1),1))
任何输入数组的通用解决方案:
如果 usingitertools
是一个选项,那么您可以使用:
import numpy as np
import itertools
x = list(itertools.combinations([1,2,3,4], 2))
c = np.prod(x,-1)
c
输出:
array([ 2, 3, 4, 6, 8, 12])
从文档:
itertools.combinations(iterables,r)
:按排序顺序返回 r 长度的元组,没有重复的元素。
中的元素个数c
对应于二项式系数 C(n,k)
:n
choose k
、 wheren = len([1,2,3,4])
和k = 2
。
注意到itertools.combinations()
只隐藏了 for 循环,但由于这个问题没有封闭形式的公式,所以 for 循环是不可避免的。
Numpy 唯一的解决方案:
在您的特定情况下,您的可迭代对象是n
正整数套装,[1,2,3,4,...,n]
那么您会注意到上三角二维长度矩阵的正索引n-1
将产生与以下相同的结果combinations
:
# Number of elements in your array
n = 4
# Upper triangular matrice
x = np.triu(np.ones([n-1,n-1]))
# Get the result
c = np.prod(np.argwhere(x)+np.arange(1,3),-1)
并再次c
输出:
array([ 2, 3, 4, 6, 8, 12])
或者(在@Nachikel 的帮助下,我不知道存在np.triu_indices()
)一个班轮:
c = np.multiply(*np.add(np.triu_indices(4,1),1))
基准测试:
以及使用 itertools:
编码:
import numpy as np
import itertools
import timeit
import matplotlib.pyplot as plt
def itertools1(m):
x = list(itertools.combinations(np.arange(1,m+1), 2))
np.prod(x,-1)
def numpy1(m):
n = m-1
x = np.triu(np.ones([n,n]))
np.prod(np.argwhere(x)+np.arange(1,3),-1)
def numpy2(m):
np.multiply(*np.add(np.triu_indices(m,1),1))
def benchmark_time(m):
SETUP_CODE = '''
from __main__ import numpy1
from __main__ import numpy2
from __main__ import itertools1
'''
x = np.zeros([3,len(m)])
for ind, m in enumerate(m):
print('For m = {}'.format(m))
TEST_CODE = '''
itertools1({})
'''.format(m)
# timeit.repeat statement
times = timeit.repeat(setup = SETUP_CODE,
stmt = TEST_CODE,
repeat = 10,
number = 50)
x[0,ind] = np.average(times)
print('Itertools1 give:\t{} s'.format(np.round(np.average(times),3)))
TEST_CODE = '''
numpy1({})
'''.format(m)
times = timeit.repeat(setup = SETUP_CODE,
stmt = TEST_CODE,
repeat = 10,
number = 50)
x[1,ind] = np.average(times)
print('Numpy1 give:\t\t{} s'.format(np.round(np.average(times),3)))
TEST_CODE = '''
numpy2({})
'''.format(m)
times = timeit.repeat(setup = SETUP_CODE,
stmt = TEST_CODE,
repeat = 10,
number = 50)
x[2,ind] = np.average(times)
print('Numpy2 give:\t\t{} s\n'.format(np.round(np.average(times),3)))
return x
m = np.arange(10,150,10)
x = benchmark_time(m)
plt.plot(m,x.T)
plt.legend(('itertools', 'numpy triu', 'numpy triu_indices'))
plt.xlabel('m')
plt.ylabel('sec')
plt.show()
推荐阅读
- ios - 我可以制作类似 ExpressibleByKeyPathLiteral 的东西吗?
- unit-testing - 如何为 Bot Framework nodejs v4 对话框编写单元测试
- angular - 事件发射器角度
- typescript - XOR 神经网络有时输出 0.5
- angular - 在 Ionic4 上,如何将字符串中除介词以外的所有单词的首字母大写?
- python - 在 Python 3.5 / Ipython 7.3.0 中显示两位数的数值
- google-maps - onRegionChange 时 React Native Maps 调用 api 请求
- python - Google Speech-to-Text API:语音识别缺失或信心不足
- r - 创建列以填充其他列的匹配项
- java - 如何引用调用方法的变量