Aspiring Data Science
275 subscribers
348 photos
9 videos
5 files
1.14K links
Заметки экономиста о программировании, прогнозировании и принятии решений, научном методе познания.
Контакт: @fingoldo

I call myself a data scientist because I know just enough math, economics & programming to be dangerous.
Download Telegram
#python #npl #spellchecking #bayes

Это мы брали ранговые оценки вероятностей, для смягчения приора. Если же сильно поверить Берту и взять абсолютные оценки, Дубай улетает за первую десятку. Я не знаю, если честно, насколько хорошо Берты откалиброваны по вероятностям, может, @tech_priestess подскажет?

По итогу внёс в либу contextualSpellCheck предложение новой функциональности. А ну как удастся прокрасться в контрибьюторы почти что Spacy. )
#python #langdetect #fasttext

Мне трудно поверить в это, но в 2023 у питоновского сообщества, похоже, нет нормальных оффлайновых детекторов языка.
Ну что это за хрень, из 4 либ, представленных в статье, только Гугл переводчик (онлайновый) понимает, что, блять, строка "Safe delivery" - это английский, а не датский и не суахили?

P.S.:

fastText справился! ) используйте его, не тратьте время на остальной мусор. Пример в комментах.

https://towardsdatascience.com/4-python-libraries-to-detect-english-and-non-english-language-c82ad3efd430
#python #langdetect #fasttext #googletranslate

Странно, я был уверен, что гугл переводчик это топ, там же большие языковые модели, нейросети, все такое. Но он походу в 10 раз больше ошибается, чем fasttext.
#python #codegems

Как передать питоновскому скрипту список в качестве параметра:

parser.add_argument('-l','--list', nargs='+', help='<Required> Set flag', required=True)
# Use like:
# python arg.py -l 1234 2345 3456 4567
#profiling #optimisation #python #speed #sklearn #bollocks

Эскалёрновские волшебники-программисты в деле. Столкнулся с неприемлемо низкой скоростью построения отчёта классификационных метрик на 8M примеров. 15 секунд, ну куда это годится? Проверил кирпичики расчётов по нисходящей. Матрица ошибок считается за полторы секунды. Это чем же надо угандошить процессор, чтобы простое деление пары чисел и упаковка в словарь выполнялись больше 10 секунд и делали расчёты в ДЕСЯТЬ раз длиннее? Такое и специально не сразу сделаешь.
#optimisation #sklearn #python #numba #codegems

Итак, то, что у кудесников машинного обучения считается 15 СЕКУНД, на самом деле должно занимать 50 МИЛЛИСЕКУНД. Но зато они сотни строк качественного кода написали, наверное, покрытого тестами, и прочим. Почему я считаю это важным? Да потому что мне предстоит обсчитывать сотни моделей, и оказалось, что качество обучения (classification report, roc auc, калибрация по всему сету + в разбивке по группам) на test set оценивается для 1 модели.. 5 минут, и основным тормозом был classification_report. Мне вовсе не улыбается платить за кластер, ожидающий сотни и тысячи раз по 5 минут. Спасибо, что у нас хотя бы есть numpy и numba. Без нумбы, кстати, этот код на языке программирования, созданном "гениальным" Ван Россумом, выполняется даже не знаю сколько, я прождал минут 5-10 и забил.

Скорее всего, напрасная трата времени, но всё же запостил issue. Как обычно, похерят, видимо.
#optimization #ml #metrics #python #numba #codegems

В общем, sklearn-овские метрики оказались слишком медленными, пришлось их переписать на numba. Вот пример classification_report, который работает в тысячу раз быстрее и поддерживает почти всю функциональность (кроме весов и микровзвешивания). Также оптимизировал метрики auc (алгоритм взят из fastauc) и calibration (считаю бины предсказанные vs реальные, потом mae/std от их разностей). На 8M сэмплов всё работает за ~30 миллисекунд кроме auc, та ~300 мс. Для сравнения, scikit-learn-овские работают от нескольких секунд до нескольких десятков секунд.

@njit()
def fast_classification_report(
y_true: np.ndarray, y_pred: np.ndarray, nclasses: int = 2, zero_division: int = 0
):
"""Custom classification report, proof of concept."""

N_AVG_ARRAYS = 3 # precisions, recalls, f1s

# storage inits
weighted_averages = np.empty(N_AVG_ARRAYS, dtype=np.float64)
macro_averages = np.empty(N_AVG_ARRAYS, dtype=np.float64)
supports = np.zeros(nclasses, dtype=np.int64)
allpreds = np.zeros(nclasses, dtype=np.int64)
misses = np.zeros(nclasses, dtype=np.int64)
hits = np.zeros(nclasses, dtype=np.int64)

# count stats
for true_class, predicted_class in zip(y_true, y_pred):
supports[true_class] += 1
allpreds[predicted_class] += 1
if predicted_class == true_class:
hits[predicted_class] += 1
else:
misses[predicted_class] += 1

# main calcs
accuracy = hits.sum() / len(y_true)
balanced_accuracy = np.nan_to_num(hits / supports, copy=True, nan=zero_division).mean()

recalls = hits / supports
precisions = hits / allpreds
f1s = 2 * (precisions * recalls) / (precisions + recalls)

# fix nans & compute averages
i=0
for arr in (precisions, recalls, f1s):
np.nan_to_num(arr, copy=False, nan=zero_division)
weighted_averages[i] = (arr * supports).sum() / len(y_true)
macro_averages[i] = arr.mean()
i+=1

return hits, misses, accuracy, balanced_accuracy, supports, precisions, recalls, f1s, macro_averages, weighted_averages
#python #codegems #fs #expandvars

Пошёл тестировать BAMT. Пример из руководства выпал с ошибкой, смотрю, он пытается создать файл

C:\Users\Roman\BAMT\Nodes_data

Посмеялся, думаю, щас заведу им issue чтоб по дефолту заменили на какое-нить

%%LOCALAPPDATA%%\aimclub\BAMT\Nodes_data

Но сначала сам заменил локально, потестить:


PermissionError Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_3236\1667079916.py in <module>
----> 1 bn.fit_parameters(data)

C:\ProgramData\Anaconda3\lib\site-packages\bamt\networks\base.py in fit_parameters(self, data, dropna, n_jobs)
489
490 if not os.path.isdir(STORAGE):
--> 491 os.makedirs(STORAGE)
492
493 # init folder

C:\ProgramData\Anaconda3\lib\os.py in makedirs(name, mode, exist_ok)
213 if head and tail and not path.exists(head):
214 try:
--> 215 makedirs(head, exist_ok=exist_ok)
216 except FileExistsError:
217 # Defeats race condition when another thread created the path

C:\ProgramData\Anaconda3\lib\os.py in makedirs(name, mode, exist_ok)
213 if head and tail and not path.exists(head):
214 try:
--> 215 makedirs(head, exist_ok=exist_ok)
216 except FileExistsError:
217 # Defeats race condition when another thread created the path

C:\ProgramData\Anaconda3\lib\os.py in makedirs(name, mode, exist_ok)
213 if head and tail and not path.exists(head):
214 try:
--> 215 makedirs(head, exist_ok=exist_ok)
216 except FileExistsError:
217 # Defeats race condition when another thread created the path

C:\ProgramData\Anaconda3\lib\os.py in makedirs(name, mode, exist_ok)
223 return
224 try:
--> 225 mkdir(name, mode)
226 except OSError:
227 # Cannot rely on checking for EEXIST, since the operating system

PermissionError: [WinError 5] Access is denied: '%LOCALAPPDATA%'

Оказалось, питон на винде, в отличие от Проводника, не поддерживает сокращения типа %LOCALAPPDATA%. Получается, перед работой с файловой системой надо сначала любой путь пропускать через os.path.expandvars в качестве лучшей практики.

А лучше всего место для хранения настроек, раз уж локальная директория не подходит, получить с помошью platformdirs :

>>> from platformdirs import *
>>> appname = "SuperApp"
>>> appauthor = "Acme"
>>> user_data_dir(appname, appauthor)
'C:\\Users\\trentm\\AppData\\Local\\Acme\\SuperApp'
>>> user_data_dir(appname, appauthor, roaming=True)
'C:\\Users\\trentm\\AppData\\Roaming\\Acme\\SuperApp'
>>> user_cache_dir(appname, appauthor)
'C:\\Users\\trentm\\AppData\\Local\\Acme\\SuperApp\\Cache'
>>> user_log_dir(appname, appauthor)
'C:\\Users\\trentm\\AppData\\Local\\Acme\\SuperApp\\Logs'
>>> user_documents_dir()
'C:\\Users\\trentm\\Documents'
>>> user_downloads_dir()
'C:\\Users\\trentm\\Downloads'
>>> user_pictures_dir()
'C:\\Users\\trentm\\Pictures'
>>> user_videos_dir()
'C:\\Users\\trentm\\Videos'
>>> user_music_dir()
'C:\\Users\\trentm\\Music'
>>> user_desktop_dir()
'C:\\Users\\trentm\\Desktop'
>>> user_runtime_dir(appname, appauthor)
'C:\\Users\\trentm\\AppData\\Local\\Temp\\Acme\\SuperApp'