#numpy #stats #percentile
А Вы задумывались, что вообще-то для вычисления перцентилей/квантилей есть КУЧА методов? По дефолту идёт линейный, но в доках в общем случае для неизвестного распределения рекомендуется median_unbiased.
Облом состоит в том, что numba параметр method не поддерживает.
А Вы задумывались, что вообще-то для вычисления перцентилей/квантилей есть КУЧА методов? По дефолту идёт линейный, но в доках в общем случае для неизвестного распределения рекомендуется median_unbiased.
Облом состоит в том, что numba параметр method не поддерживает.
👍1
#numpy #bugs
Нампай тож свалился на этом проекте )) Захотел 4 эксбибайта памяти.
https://github.com/numpy/numpy/issues/23564
Нампай тож свалился на этом проекте )) Захотел 4 эксбибайта памяти.
https://github.com/numpy/numpy/issues/23564
GitHub
BUG: Memory Overflow in np.histogram with bins="auto" · Issue #23564 · numpy/numpy
Describe the issue: Something is wrong with the "auto" option. Reproduce the code example: import numpy as np hist, bin_edges = np.histogram( np.array( [ -4.24264069e00, -5.55111512e-17, ...
#numpy
В нампай, оказывается, можно легко докинуть нулей к массиву, хоть слева, хоть справа.
В нампай, оказывается, можно легко докинуть нулей к массиву, хоть слева, хоть справа.
A = np.array([1,2,3,4,5])
np.pad(A, (2, 3), 'constant')
# array([0, 0, 1, 2, 3, 4, 5, 0, 0, 0])✍1
#optimisation #numba #numpy #auc #fastauc
Ещё немного про оптимизацию. В попытке найти быструю реализацию roc_auc набрёл на библу factauc, где автор не поленился и сделал numba-оптимизированную, и даже сишную реализации. В сишную он явно вложился, вон сколько кода, и не напрасно: она получилась самой быстрой, почти вдвое быстрее нумбовской (что меня уже насторожило). Проверил на своём массивчике 8M float-ов, действительно самые тормозные catboost и sklearn (больше 2 секунд), фастаук уже позволяет прыгнуть до 0.6 секунды с нумба и до 0.4 с Си++. Глянул нумбовскую реализацию, а там argsort закомпилирован. Вспомнилось, что раньше нумба замедляла эту функцию. Вынес argsort "за скобки" njit-компилятора, и вуаля, С++ реализация побита, 0.3 секунды )) Даже неловко было сообщать автору, но что поделаешь.
P.S. Всеволод сказал, что на неделе предлагаемое улучшение потестит и, если что, в fastauc замёрджит )
Ещё немного про оптимизацию. В попытке найти быструю реализацию roc_auc набрёл на библу factauc, где автор не поленился и сделал numba-оптимизированную, и даже сишную реализации. В сишную он явно вложился, вон сколько кода, и не напрасно: она получилась самой быстрой, почти вдвое быстрее нумбовской (что меня уже насторожило). Проверил на своём массивчике 8M float-ов, действительно самые тормозные catboost и sklearn (больше 2 секунд), фастаук уже позволяет прыгнуть до 0.6 секунды с нумба и до 0.4 с Си++. Глянул нумбовскую реализацию, а там argsort закомпилирован. Вспомнилось, что раньше нумба замедляла эту функцию. Вынес argsort "за скобки" njit-компилятора, и вуаля, С++ реализация побита, 0.3 секунды )) Даже неловко было сообщать автору, но что поделаешь.
P.S. Всеволод сказал, что на неделе предлагаемое улучшение потестит и, если что, в fastauc замёрджит )
❤1🔥1
#numpy #numba #codegems #calloc
Итак, выяснилось, что numpy.zeros делегирует вызов сишной calloc, и на самом деле читит. Если тестировать инициализацию массива с реальной записью хотя бы 1 элемента, всё стаёт на свои места. .zeros() чуть медленнее остальных, .fill(0) несущественно быстрее двоеточий. Но удивительно, что нумба медленнее в 2-8 раз.
Итак, выяснилось, что numpy.zeros делегирует вызов сишной calloc, и на самом деле читит. Если тестировать инициализацию массива с реальной записью хотя бы 1 элемента, всё стаёт на свои места. .zeros() чуть медленнее остальных, .fill(0) несущественно быстрее двоеточий. Но удивительно, что нумба медленнее в 2-8 раз.
shape = (10000, 10000)
a = np.zeros(shape, dtype=np.int64)
def alloc_new(a):
a = np.zeros(shape, dtype=np.int64)
a[500, 500] = 1
return a
def numpy_fancy_assign(a):
a[:, :] = 0
a[500, 500] = 1
return a
def numpy_fill(a):
a.fill(0)
a[500, 500] = 1
return a
def cyclces_assign(a):
for i in range(a.shape[0]):
for j in range(a.shape[1]):
a[i, j] = 0
a[500, 500] = 1
return a
njitted_funcs = []
funcs = (alloc_new, numpy_fancy_assign, numpy_fill, cyclces_assign)
for func in funcs:
njitted_func = njit(func)
njitted_func(a) # test call
njitted_funcs.append(njitted_func)✍1
#numpy #numba #codegems #zeros
История с zeros не закончилась )) Открылись новые факты. Я подумал, нумба показалась медленной из-за переключения контекста, поэтому внутри каждой функции выше просто сделал цикл до 10, чтобы основную работ вести внутри контекста. К примеру,
Выводы из прошлого поста подтвердились: numba-версии действительно медленнее numpy-евских, КРОМЕ
Оптимальная тактика на сегодня: массив создавать надо вне numba с помощью .zeros(), а обнулять его вызовом
История с zeros не закончилась )) Открылись новые факты. Я подумал, нумба показалась медленной из-за переключения контекста, поэтому внутри каждой функции выше просто сделал цикл до 10, чтобы основную работ вести внутри контекста. К примеру,
def numpy_fancy_assign(a):
for _ in range(10):
a[:, :] = 0
a[500, 500] = 1
return a
и т.д.Выводы из прошлого поста подтвердились: numba-версии действительно медленнее numpy-евских, КРОМЕ
a[:, :] = 0, которая одна-единственная при выполнении в контексте numba в 5 раз быстрее зануляет numpy-массив, чем сам numpy. Оптимальная тактика на сегодня: массив создавать надо вне numba с помощью .zeros(), а обнулять его вызовом
a[:, :] = 0 внутри numba (если, конечно, это надо делать много раз). Feature request чтобы нумба редиректила на np.zeros.#featureselection #entropy #histogram #binning #diogenes #astropy
Один важнейший аспект своего отборщика признаков я совершенно упустил - это построение гистограмм для оценки энтропии и взаимной информации. Для улавливания связей на этапе тестирования мне хватало равномерного разбиения (непрерывной переменной) на N бинов, я просто для быстроты разработки взял KbinsDiscretizer с параметром strategy='uniform' и n_bins=4. Но даже там есть ещё варианты quantile и kmeans, их я думал потестить позже. Однако при попытке различить коллинеарные факторы на более "оригинальные" и "зависимые"/"зашумлённые" такого простого подхода перестало хватать. Да и кто сказал, что хорошо использовать одно и то же число бинов для всех факторов?
Я вспомнил про формулы Стёрджеса и прочие, довольно много вариаций оказалось реализовано в нампае. Астропай порадовал наличием расчёт байесовской гистограммы с переменным размером бина. Я заценил на своих данных, посмотрим, какая будет дискриминирующая способность всех этих подходов.
Один важнейший аспект своего отборщика признаков я совершенно упустил - это построение гистограмм для оценки энтропии и взаимной информации. Для улавливания связей на этапе тестирования мне хватало равномерного разбиения (непрерывной переменной) на N бинов, я просто для быстроты разработки взял KbinsDiscretizer с параметром strategy='uniform' и n_bins=4. Но даже там есть ещё варианты quantile и kmeans, их я думал потестить позже. Однако при попытке различить коллинеарные факторы на более "оригинальные" и "зависимые"/"зашумлённые" такого простого подхода перестало хватать. Да и кто сказал, что хорошо использовать одно и то же число бинов для всех факторов?
Я вспомнил про формулы Стёрджеса и прочие, довольно много вариаций оказалось реализовано в нампае. Астропай порадовал наличием расчёт байесовской гистограммы с переменным размером бина. Я заценил на своих данных, посмотрим, какая будет дискриминирующая способность всех этих подходов.
#pandas #optimization #joblib #numpy #memmap
Хорошие новости! после экспериментов выяснилось, что в последних версиях joblib умеет дампить в общую память не просто отдельные массивы numpy, а (что не указано в доке) и целиком фреймы пандас!
И даже не обязательно прописывать операции вручную. Достаточно просто передать фрейм в конструктор Parallel joblib-a как параметр, и, если он больше max_nbytes, joblib его автоматически сдампит и правильно загрузит уже в рабочих процессах! Советую в качестве temp_folder указывать быстрый NVME SSD диск, типа Parallel(n_jobs=32,max_nbytes=0, temp_folder=r'R:\Temp' ). В моих тестах отработали по сути все базовые типы столбцов: int, float, datetime, categorical.
Единственное - проблема со сложными типами, вроде массива массивов numpy (итоговый тип object), такое не работает и включается обычная сериализация. Но этого желать было бы уж слишком нереалистично, я и так не могу себе представить, как удалось победить нерадивых программистов пандас, ведь раньше даже просто инитнуть фрейм с разнородными типами столбцов было невозможно без копирования.
Вывод: если у Вас не экзотические типы данных и есть nvme, большие фреймы в свежих версиях библиотек можно спокойно передавать как параметры, и они не буду побайтово сериализоваться, более того, RAM будет расходоваться в десятки раз экономнее.
Хорошие новости! после экспериментов выяснилось, что в последних версиях joblib умеет дампить в общую память не просто отдельные массивы numpy, а (что не указано в доке) и целиком фреймы пандас!
И даже не обязательно прописывать операции вручную. Достаточно просто передать фрейм в конструктор Parallel joblib-a как параметр, и, если он больше max_nbytes, joblib его автоматически сдампит и правильно загрузит уже в рабочих процессах! Советую в качестве temp_folder указывать быстрый NVME SSD диск, типа Parallel(n_jobs=32,max_nbytes=0, temp_folder=r'R:\Temp' ). В моих тестах отработали по сути все базовые типы столбцов: int, float, datetime, categorical.
Единственное - проблема со сложными типами, вроде массива массивов numpy (итоговый тип object), такое не работает и включается обычная сериализация. Но этого желать было бы уж слишком нереалистично, я и так не могу себе представить, как удалось победить нерадивых программистов пандас, ведь раньше даже просто инитнуть фрейм с разнородными типами столбцов было невозможно без копирования.
Вывод: если у Вас не экзотические типы данных и есть nvme, большие фреймы в свежих версиях библиотек можно спокойно передавать как параметры, и они не буду побайтово сериализоваться, более того, RAM будет расходоваться в десятки раз экономнее.
👍2