Блог

Про всякое.

Шпаргалка по формам/алгоритмам нормализации Unicode текста

Алгоритмы нормализации в Unicode нужны для преобразования внутренней структуры текста, чтобы потом с ним было проще работать. Например, можно заменить несколько символов одним, убрать все диакритические знаки из текста и даже преобразовать похожие буквы в их аналоги.

Всего есть четыре таких алгоритма: NFD, NFC, NFKD, NFKC. Каждый в отдельности можно запускать на одной и той же строке много раз, и результат от этого никак не изменится. То есть они идемпотентны.

Работать с Unicode текстом будем при помощи страндартной Python библиотеки unicodedata.

1. NFD (Normalization Form Canonical Decomposition) или форма нормализации D.

Раскладывает составные символы на несколько простых в соответствии с таблицами декомпозиции. Если хотя бы один из получившихся символов тоже составной, раскладываем и его до тех пор, пока не получим последовательность простых символов. То есть, алгоритм работает рекурсивно.

Получившаяся разложенная последовательность сортируется в некотором порядке, пока не очень понял в каком именно.

for c in unicodedata.normalize("NFD", "ё"):
    print("'%s': %s" % (c, unicodedata.name(c)))

>> 'е': CYRILLIC SMALL LETTER IE
>> '̈': COMBINING DIAERESIS

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

2. NFC (Normalization Form Canonical Composition) или форма нормализации C.

Сначала выполняет NFD декомпозицию, а затем комбинирует полученные простые символы в составные. NFD декомпозиция тут нужна, чтобы разбить уже частично комбинированные символы на простые составляющие для последующей сортировки и обратной сборки.

for c in unicodedata.normalize("NFC", "ё"):
    print("'%s': %s" % (c, unicodedata.name(c)))

>> 'ё': CYRILLIC SMALL LETTER IO

Так можно быстро «приклеить» всю диакритику к буквам и получить из двух символов CYRILLIC SMALL LETTER IE и COMBINING DIAERESIS один CYRILLIC SMALL LETTER IO.

3. NFKD (Normalization Form Compatibility Decomposition) или форма нормализации KD.

Алгоритм, который выполняет NFD декомпозицию и заменяет похожие символы совместимыми аналогами, например, дробь ’¼’ заменяется на строку символов «1/4».

s = '⑲ ⁹ ¼'
print(unicodedata.normalize("NFKD", s))

>> 1 19 9 1/4

for c in list(s):
    print("'%s': %s - '%s'" % (c, unicodedata.name(c), unicodedata.normalize("NFKD", c)))

>> '⑲': CIRCLED NUMBER NINETEEN - '19'
>> ' ': SPACE - ' '
>> '⁹': SUPERSCRIPT NINE - '9'
>> ' ': SPACE - ' '
>> '¼': VULGAR FRACTION ONE QUARTER - '1⁄4'

После такой нормализации можно легко делать фильтрацию текста регэкспами, если его пытались усложнить и замаскировать от этого заменой похожих символов.

4. NFKC (Normalization Form Compatibility Composition) или форма нормализации KC.

Сначала выполняется совместимое разложение NFKD, а затем символы собираются вместе согласно NFC. Аналогично работе с NFC, можно быстро склеить всю диакритику с буквами, приведенными к некоторому базовому виду.

Проблемы NFKD и NFKC

При всем удобстве алгоритмов NFKD и NFKC, они не приводят некоторую часть визуально похожих символов к совместимым аналогам. Например, группу Negative Circled Number * из блока Enclosed Alphanumerics вполне можно привести к числам, но этого не происходит:

unicodedata.normalize("NFKC", "⓫ ⓯")

>> '⓫ ⓯'

А значит, если хочется сделать качественное приведение похожих символов, необходимое для многих задач, придется повозиться над своими таблицами замен.

6 сентября   Python   Unicode

Apple и успешный успех

Не прошло и четырех месяцев, как Apple наконец-то дозволила мне вступить в ряды Apple Developer Program. Я еще никогда так долго не старался кому-то всучить $99. И судя по Telegram чатикам, такая же проблема еще у кучи других разработчиков.

Apple и программисты. Холст. Масло.

Если не думать о технических накладках взимания платежей с российских банков, то, думается мне, это какой-то хитрый план по сокращению числа мошенников в App Store, ибо возникают такие проблемы в основном у чистых аккаунтов, без истории покупок. Не зря же техподдержка просит что-то приобрести в одном из магазинов эппла и ждать.

В общем, мой алгоритм первой покупки подписки на ADP:

  1. Одинаково заполнить Billing и Shipping адрес везде, где только можно: App Store, iTunes и собственно во время оформления самой подписки.
  2. Попробовать совершить покупку подписки с любой банковской карты. Был слух, что лучше процессятся платежи с Mastercard, но это не точно.
  3. Если покупку отклонили, то попробовать купить подписку с карты любого другого банка. Это нужно, чтобы доказать, что проблемы не с конкретной картой конкретного банка.
  4. Если покупку отклоняют и аккаунт без истории, то нужно что-то приобрести в App Store минимум на $10, а лучше чуть больше. Если есть такая покупка, то все становится проще и ждать 3 месяца скорее всего не придется, а значит пропускаем следующие 2 шага.
  5. Попробовать позвонить в саппорт, но скорее всего вас пошлют нахер отправят ждать 90 дней, ибо им нужен Order ID любой покупки старше 90 дней. Из практики, звонить лучше чем писать письмо, ибо становится сильно понятнее, что делать дальше, да и проще как-то общаться вживую, а письма как правило игнорят очень долго. Ага, нужен разговорный английский.
  6. Ждем 90 дней.
  7. Звоним в саппорт заново, называем им свой Order ID.
  8. Скорее всего вас попросят отправить скан любого Government Issued ID, то бишь в случае РФ это загранпаспорт. Вам пришлют ссылку, куда надо будет загрузить документ. Ждем несколько дней.
  9. Через неделю после отправки я еще раз позвонил в саппорт, где мне в прямом эфире подтвердили что я это я, кек. Заявку перенаправили в финансовый отдел и сказали ждать до двух недель.
  10. Деньги наконец-то списали и прислали счет за покупку и письмо от менеджера с извинениями за ожидания. Списывают деньги с последней карты по которой вы хотели купить подписку на ADP.
  11. Однако, саму подписку не активировали и через день я еще раз написал менеджеру сообщение с Order ID из своего счета и буквально через 20 минут подписка была активирована.
  12. Вы великолепны, это успех.

Вот в общем, это всё и теперь можно с таким же успехом биться за модерацию своего приложения.

Очистка речи от закадрового шума нейронными сетями c FFmpeg

Для очистки аудио файла содержащего человеческую речь от закадрового шума, перед автоматическим распознаванием, пару раз использовал библиотеку RNNoise в связке с FFmpeg.

Для работы с ней надо использовать фильтр LV2 с плагином-оберткой speech-denoiser над RNNoise.

Пример:

ffmpeg -i $INPUT -af 'lv2=p=https\\://github.com/lucianodato/speech-denoiser' $OUTPUT

P.S. FFmpeg должен быть собран с --enable-lv2

27 августа   ffmpeg

Тинькофф Пульс

Датасет для генератора финансовых мемов на нейросетях можно взять из Тинькофф Пульса. Бесконечный кек-поток на все случаи жизни.

2020   Tinkoff.ru

Keras 2.3 & TensorFlow 2

При обновлении до Keras >= 2.3 и Tensorflow >= 2.0 в старых многопоточных приложениях может начать выскакивать ошибка:

AttributeError: '_thread._local' object has no attribute 'value'

Решить ее можно заменив импорты

from keras import что_нужно

на

from tensorflow.keras import что_нужно

UPD: Если после обновления появилось вот такое:

Error : Failed to get convolution algorithm. This is probably because cuDNN failed to initialize, so try looking to see if a warning log message was printed above.

Весьма вероятно, что cuDNN теперь не подходит по версии для TensorFlow ибо старовата. Найти нужную версию можно тут.

UPD 2: При обновлении cuDNN еще можно заметить, что в официальной инструкции установки на linux из архива не указано, что после копирования нужно сделать симлинки на so’шники. Иначе после sudo ldconfig будет ошибка (далее, вместо библиотеки версии 7, подставьте свою):

/usr/local/cuda/lib64/libcudnn.so.7 is not a symbolic link

Т.е. надо:

$ cd /usr/local/cuda/lib64/

$ ls -lha libcudnn*
-rwxr-xr-x 1 root root 374M июн 13 04:27 libcudnn.so
-rwxr-xr-x 1 root root 374M июн 13 04:27 libcudnn.so.7
-rwxr-xr-x 1 root root 374M июн 13 04:27 libcudnn.so.7.6.5
-rw-r--r-- 1 root root 373M июн 13 04:27 libcudnn_static.a

$ sudo rm libcudnn.so libcudnn.so.7
$ sudo ln libcudnn.so.7.6.5 libcudnn.so.7
$ sudo ln libcudnn.so.7 libcudnn.so
$ sudo ldconfig
Ранее Ctrl + ↓