Автоматически c нежелательных выходов терминала при решении задачи оптимизации cvxpy - PullRequest
1 голос
/ 26 мая 2020

Пытаясь решить проблему логистической c регрессии с помощью cvxpy, я получил несколько выводов терминала при вызове функции resolve (), хотя распечатки не были запрограммированы. Более того, никакая информация о проблеме не выводилась на терминал, даже если для параметра verbose было задано значение true и невозможно получить доступ к оптимальному значению. вполне понятно, что это такое.

Проблема была определена следующим образом в минимальном примере кода:

import numpy as np
import cvxpy as cp

y_vec = np.random.choice([0, 1], size=(728,), p=[9./10, 1./10])
M_mat = np.random.choice([0, 1], size=(728,801), p=[9./10, 1./10])
beta = cp.Variable(M_mat.shape[0])
objective = 0
for i in range(400):
    objective += y_vec[i] * M_mat[:, i].T @ beta - \
        cp.log(1 + cp.exp((M_mat[:, i].T @ beta)))

prob = cp.Problem(cp.Maximize(objective))
prob.solve(verbose=True)
print("Optimal var reached",  beta.value)

Оба y_vec и M_mat являются numpy массивами с типом данных int64. Обе являются матрицами выбора для задачи классификации, состоящими только из 0 и 1. Для целей минимального примера кода они генерируются случайным образом для воспроизведения ошибки. Кроме того, M_mat[:, i].T @ beta был проверен на получение скаляра, как и предполагалось.

Когда я выполняю код, я получаю распечатки множества подобных распечаток с завершением программы после определенного числа.

Конец распечатки терминала, после чего программа завершается

Здесь показан только конец распечаток после завершения программы. Но есть много блоков формы log(1.0 + exp([ 0. 0. ...... 0.] * var0)), в которых эта выходная последовательность имеет ту же длину, что и переменная beta.

Я нахожу этот результат довольно запутанным. Как я могу прийти к единому вектору для бета-аргумента оптимизации? Любая помощь приветствуется!

Ответы [ 2 ]

2 голосов
/ 28 мая 2020

Ваша первоначальная формулировка проблемы не соответствует DCP . Я признаю, что результат далек от идеала; CVXPY печатает выражения, несовместимые с DCP, но их так много, что вывод бесполезен. Заменив 400 в вашем for l oop на 1, вы получите следующий результат, который более полезен, потому что он умещается в окне вашего терминала.

The objective is not DCP. Its following subexpressions are not:
log(1.0 + exp([0. 0. 1. 0. 0. 1. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
 0. 0. 0. 1. 0. 0. 0. 0. 0. 1. 0. 1. 0. 1. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0.
 1. 0. 0. 0. 0. 1. 0. 0. 1. 0. 0. 0. 0. 0. 0. 1. 1. 0. 0. 0. 0. 0. 0. 0.
 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
 0. 1. 0. 0. 0. 0. 0. 0. 1. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 1. 0.
 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 1. 0. 0. 0.
 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0.
 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0.
 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
 1. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 1. 0. 0. 0. 0. 0.
 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 1. 0. 0.
 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
 0. 0. 0. 0. 0. 1. 1. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0.
 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 1. 0. 0.
 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 1. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 1. 0. 1. 0. 0. 0. 0. 0. 0.
 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0.
 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
 0. 0. 0. 0. 0. 0. 0. 1. 0. 1. 1. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 1.
 0. 0. 0. 1. 0. 0. 1. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0.
 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 1. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0.
 0. 1. 0. 0. 1. 0. 1. 0. 0. 1. 1. 0. 1. 0. 0. 0. 1. 0. 0. 0. 1. 0. 1. 0.
 0. 0. 1. 0. 0. 0. 0. 1. 0. 0. 1. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0.
 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 1. 1. 0. 0.
 0. 0. 0. 0. 1. 1. 0. 0.] @ var6400))

1 голос
/ 27 мая 2020

После некоторых проб и ошибок я обнаружил, что использование функции cvxpy.logisti c () каким-то образом приводит к успешному вычислению решения с желаемым выходным вектором.

Это было достигнуто переформулировкой целевой функции следующим образом:

objective = 0
for i in range(400):
    objective += y_vec[i] * M_mat[:, i].T @ beta - cp.logistic(M_mat[:, i].T @ beta)

Хотя обе реализации должны быть математически одинаковыми в соответствии с Atomi c Функции - CVXPY это приводит к совершенно разным результатам. Почему это так, я не знаю. Я надеюсь, что решение тем не менее может быть полезно для кого-то, и мне любопытно узнать больше, почему поведение так отличается, если кто-то знает больше.

...