python - 最小化涉及大型加权矩阵的平方和的最快方法
问题描述
我需要最小化两个大(10000 x 40000)矩阵之间的平方和:Σ(XA)^2,其中 X 是两个矩阵(10000 x 20000)的串联,每个段单独加权(W),参见图片内在功能。.
还有一个约束条件是权重之和必须等于 1 (W1 + W2 = 1)。我目前在 scipy optimize 中使用 SLSQP 方法来获得最佳权重值,但在我的计算机上处理大约需要 10 分钟。有没有更好的方法来做到这一点,不会花这么长时间?我还在下面附上了我正在使用的代码。
from scipy.optimize import minimize
import numpy
def objective(W,X1,X2,A):
W1=W[0]
W2=W[1]
X=numpy.hstack((W1*X1,W2*X2))
return numpy.sum((X-A)**2)
def constraint1(W):
W1=W[0]
W2=W[1]
return W1+W2-1
x0=[[1,0]]
cons = {'type': 'eq', 'fun':constraint1}
#Random data only used for purposes of example
segment_1 = numpy.random.rand(10000, 20000)
segment_2 = numpy.random.rand(10000, 20000)
A = numpy.random.rand(10000, 40000)
sol=minimize(objective,x0[0],args=(segment_1,segment_2,A),method='SLSQP',constraints=cons)
解决方案
介绍
好的......有很多潜在的改进,我只是接触阻力最小的路径(由于懒惰和信息稀少)。
如果您非常关心性能,请考虑如何快速计算梯度(符号/代数;在基于 SLSQP 的代码中没有隐藏的数值微分)。
提示:比较 SLSQPnfev
以nit
查看数值微分的开销!
方法
- 您只对优化两个变量的凸组合感兴趣
- 这很容易映射到标量优化
- 优化
W1
(有界)并且W2
是隐含的!
代码(未优化的破解)
原装零件
from scipy.optimize import minimize
import numpy
numpy.random.seed(0)
from time import perf_counter as pc
"""
ORIGNAL CODE
"""
def objective(W,X1,X2,A):
W1=W[0]
W2=W[1]
X=numpy.hstack((W1*X1,W2*X2))
return numpy.sum((X-A)**2)
def constraint1(W):
W1=W[0]
W2=W[1]
return W1+W2-1
x0=[[1,0]]
cons = {'type': 'eq', 'fun':constraint1}
#Random data only used for purposes of example
segment_1 = numpy.random.rand(1000, 20000)
segment_2 = numpy.random.rand(1000, 20000)
A = numpy.random.rand(1000, 40000)
# MODIFICATION: make instance more interesting! != ~0.5/0.5 solution
segment_1 *= 1.3
start_time = pc()
sol = minimize(objective,x0[0],args=(segment_1,segment_2,A),method='SLSQP',constraints=cons)
end_time = pc()
print(sol)
print('secs: {}'.format(end_time - start_time))
修改的部分(与上面相同的源/文件)
"""
ALTERNATIVE CODE hacked around ORIGINAL CODE
"""
from scipy.optimize import minimize_scalar
def solve_alternative(ojective_func, segment_1, segment_2, A):
objective_func_wrapper = lambda x: ojective_func(
(x, 1.0-x), segment_1, segment_2, A)
x = minimize_scalar(objective_func_wrapper, method='Bounded', bounds=(0, 1))
return x
start_time = pc()
sol = solve_alternative(objective, segment_1, segment_2, A)
end_time = pc()
print(sol)
print('secs: {}'.format(end_time - start_time))
示例输出(尺寸缩小以在类似平板电脑的设备上运行)
fun: 6280656.612055224
jac: array([-2736633.5 , -2736633.375])
message: 'Optimization terminated successfully.'
nfev: 19
nit: 3
njev: 3
status: 0
success: True
x: array([0.45541614, 0.54458386])
secs: 32.6327816
fun: 6280656.612055217
message: 'Solution found.'
nfev: 6
status: 0
success: True
x: 0.45541616584551015
secs: 9.930487200000002
推荐阅读
- javascript - 如果 iframe 存在,Javascript onclick,将其删除并创建新的 iframe?
- python - Python从正面展望中获取分组值
- python - 用python说话时将语音转换为文本
- wordpress - 打开我的网站时如何加载我自己的网站文件而不是 WordPress 网站
- r - 垂直对齐单元格以位于底部的柔性表
- java - 应用程序中抛出 NoUniqueBeanDefinitionException
- tensorflow - tf api 用法:stop_if_no_decrease_hook
- php - 使用 pdo sqlsrv 驱动程序调用 mssql 存储过程,并在过程中进行多查询
- javascript - 尝试在命令行中运行时,javascript 程序的输出为“未定义”
- python - 如何遍历python中的无序对