openlang

sum(X) на матрице из одной строки

Функция берёт матрицу наблюдений, строки - наблюдения, столбцы - признаки, и нормирует каждый столбец через X ./ sum(X). Долго работала без вопросов. Потом пришёл ввод из одной строки.

sum идёт по первой размерности, размер которой не равен 1. У матрицы 1 на n это вторая размерность. Вместо строки сумм по столбцам выходит одно число. Ни ошибки, ни предупреждения.

X = [1 2 3; 4 5 6];
sum(X)       % [5 7 9]
X = [1 2 3];
sum(X)       % 6, not [1 2 3]
sum(X, 1)    % [1 2 3]

Деление прошло молча, делить на скаляр можно всегда. Каждый столбец должен был стать единицей. Вышла строка, отмасштабированная так, чтобы её сумма была единицей. Числа от нуля до единицы, на вид нормальные.

Лечится явной размерностью, sum(X, 1). То же для mean и остальных функций, которые выбирают размерность по данным. Форма результата не должна зависеть от того, сколько строк случайно пришло. Ладно, теперь размерность пишется в каждом вызове, даже там, где приходят только большие матрицы.

Разговор продолжается 6

Следуя доводам
  1. Ссылка на ответ

    В Фортране ранг задаётся объявлением. sum(a, dim=1) для массива ранга 2 даёт ранг 1 при любых размерах, и при одной строке тоже. Ошибка здесь в том, что размерность выбирается по размерам. Передавайте размерность каждый раз, во вспомогательных функциях тоже.

  2. Ссылка на ответ

    У max есть второй выход, и с ним всё хуже. Для матрицы [m, i] = max(X) даёт для каждого столбца строку, где стоит максимум. Для X из одной строки получается один максимум, а i становится номером столбца. Переменная та же, смысл другой, и если следующая строка выбирает по i наблюдение, теперь она выбирает признак. [m, i] = max(X, [], 1) оставляет i номером строки, так что при одной строке это вектор единиц, по одной на столбец.

  3. Ссылка на ответ

    В Julia решили наоборот. sum(X; dims=1) всегда возвращает матрицу из одной строки, даже когда в X одна строка, так что форма сохраняется ценой вызова vec, если нужен обычный вектор.

  4. Ссылка на ответ

    То есть форму результата решают данные, которые прислал вызывающий. Прелесть, функция, у которой тип возврата зависит от везения. Хотя справедливости ради, sum(X, 1) - это три лишних символа, а какую размерность выбирают, в документации сказано прямо.

  5. Ссылка на ответ

    Про max в точку, а в той же функции нашлась другая беда. По аналогии с sum(X, 1) там было написано max(X, 1). Это не размерность. Это поэлементный максимум с единицей, всё, что меньше единицы, подтянулось к 1. Ни ошибки, ни предупреждения, форма та же. Правильно max(X, [], 1), с пустым местом под второй аргумент. Поиск по коду max( и min( с двумя аргументами нашёл три места. Два оказались настоящим поэлементным сравнением, а одно той же ошибкой.

  6. Ссылка на ответ

    Похоже, оба случая поймал бы один маленький тест. Вход из одной строки со значениями меньше единицы и проверка формы и значений результата. max(X, 1) на нём видно сразу, sum(X) тоже. Можно добавить и вход без строк, когда будет решено, что функция должна на нём вернуть. Для начала случай с одной строкой, наверное, покроет обе найденные ошибки.

Другие стороны того же вопроса

  1. na.rm = TRUE на группе, где всё NA

    Итоги по группам через tapply(x, g, sum, na.rm = TRUE), и одна группа вернулась с 0. Все значения в ней NA. Ни одного измерен…

    Ответы 4r
  2. Цикл, который выделял память на каждый столбец

    Срезы в Julia копируют. Это известно, но внутри цикла вылетело из головы. Возьмём функцию, которая идёт по столбцам матрицы и…

    Ответы 4julia
  3. f2py копирует мой C-массив при каждом вызове

    Передаю массив NumPy в подпрограмму на Фортране через f2py. Массив создан как обычно, np.zeros((n, m)), то есть в C-порядке.…

    Ответы 3fortran