使用CVXPY遇TypeError与ValueError:变量与Numpy标量相乘问题
问题:使用CVXPY求解优化问题时遇到类型错误
原始代码
import numpy as np import cvxpy as cp N = 10 threshold = 0.3 p = 1 - threshold para_dim = 1000 para_mat = np.random.rand(para_dim, N) para_avg = np.expand_dims(np.mean(para_mat, axis=1), axis=1) A = np.random.rand(N, N) def dist(para_mat, para_avg): para_avr_arr = np.tile(para_avg, (1, N)) para_tmp = para_avr_arr - para_mat con_dist = 0 for i in range(N): con_dist += np.linalg.norm(para_tmp[:, i], 2) return con_dist/N def aggregation(para_mat, B, N): para_mat_new = np.zeros((para_dim, N)) for i in range(N): for j in range(N): for k in range(para_dim): para_mat_new[k, i] = (para_mat[k, j] - para_mat[k, i]) * B[i, j] return para_mat_new B = cp.Variable((N, N)) B_col_sum = cp.sum(B, axis=0) B_row_sum = cp.sum(B, axis=1) para_mat_new = aggregation(para_mat, B, N) obj = dist(para_mat_new, para_avg) cons = [] for i in range(N): cons += [B_col_sum[i] == 1, B_row_sum[i] == 1] cons += [B <= A, 0 <= B, B<= 1] prob = cp.Problem(cp.Minimize(obj), cons) prob.solve(method='dccp')
错误信息
TypeError: float() argument must be a string or a number, not 'multiply' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "Anaconda3\lib\site-packages\IPython\core\interactiveshell.py", line 3437, in run_code exec(code_obj, self.user_global_ns, self.user_ns) File "<ipython-input-2-53cd92582735>", line 1, in <module> runfile('participation.py', wdir='participation') File "plugins\python\helpers\pydev\_pydev_bundle\pydev_umd.py", line 198, in runfile pydev_imports.execfile(filename, global_vars, local_vars) # execute the script File "python\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile exec(compile(contents+"\n", file, 'exec'), glob, loc) File "participation.py", line 57, in <module> para_mat_new = aggregation(para_mat, B, N) File "participation.py", line 40, in aggregation para_mat_new[k, i] = (para_mat[k, j] - para_mat[k, i]) * B[i, j] ValueError: setting an array element with a sequence.
问题原因
- CVXPY变量与Numpy数组不兼容:B是CVXPY的
Variable对象,属于符号化变量,并非数值型数组。你试图将(para_mat[k,j]-para_mat[k,i])*B[i,j]这个CVXPY表达式赋值给Numpy数组para_mat_new的元素,但Numpy数组仅能存储数值,无法存储符号化的CVXPY表达式,因此触发错误。 - Numpy函数无法处理CVXPY变量:
dist函数中使用的np.linalg.norm仅支持数值型输入,不能处理CVXPY的符号化表达式。
修正方案
将aggregation和dist函数改写为使用CVXPY原生操作,避免混合使用Numpy和CVXPY的变量操作:
import numpy as np import cvxpy as cp N = 10 threshold = 0.3 p = 1 - threshold para_dim = 1000 para_mat = np.random.rand(para_dim, N) # 转换为CVXPY常量,适配符号化运算 para_mat_cp = cp.Constant(para_mat) para_avg = np.expand_dims(np.mean(para_mat, axis=1), axis=1) para_avg_cp = cp.Constant(para_avg) A = np.random.rand(N, N) def dist(para_mat_cp, para_avg_cp): # 使用CVXPY的tile实现重复操作 para_avr_arr = cp.tile(para_avg_cp, (1, N)) para_tmp = para_avr_arr - para_mat_cp con_dist = 0 for i in range(N): # 使用CVXPY的norm函数处理符号化变量 con_dist += cp.norm(para_tmp[:, i], 2) return con_dist/N def aggregation(para_mat_cp, B, N): # 用矩阵乘法替代三重循环,提升效率且符合CVXPY语法 diff_mat = para_mat_cp.T - cp.diag(para_mat_cp.T @ np.eye(N)) para_mat_new = (diff_mat @ B).T return para_mat_new B = cp.Variable((N, N)) B_col_sum = cp.sum(B, axis=0) B_row_sum = cp.sum(B, axis=1) para_mat_new = aggregation(para_mat_cp, B, N) obj = dist(para_mat_new, para_avg_cp) cons = [] for i in range(N): cons += [B_col_sum[i] == 1, B_row_sum[i] == 1] cons += [B <= A, 0 <= B, B<= 1] prob = cp.Problem(cp.Minimize(obj), cons) prob.solve(method='dccp')
关键修改点
- 将
para_mat和para_avg转换为CVXPY的Constant对象,确保所有运算都在CVXPY的符号化框架内进行。 - 改写
aggregation函数:用矩阵乘法替代三重循环,既提升运算效率,又避免将CVXPY表达式赋值给Numpy数组的错误。 - 在
dist函数中用cp.norm替代np.linalg.norm、cp.tile替代np.tile,适配CVXPY的符号化变量特性。
内容的提问来源于stack exchange,提问作者chuiyang meng
相关产品推荐
相关产品推荐

