Как стать автором
Обновить
65
0
Алексей Шаграев @ashagraev

Пользователь

Отправить сообщение

Но это добавит +1 проверку на каждый цикл, а они довольно дорогие (особенно в таком простом алгоритме).

Мне кажется, основная проблема — в использовании SQL-базы (тем более, MySQL) на интерактивном трафике. Можно очень долго заниматься оптимизациями, но глобально это не изменит того факта, что SQL-базы тяжело масштабируются в целом.

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

Это один из вариантов, но файлики — это может быть в целом не очень удобно, и с ними бывают свои приколы. Одна из стандартных архитектур в таком случае — это SQL-база, которая служит в роли ground truth, и NoSQL-базы, которые служат собственно интерфейсом к данным. Может быть некий батч-процесс, запускаемый очень часто (например, несколько раз в минуту), который вытягивает нужные данные из SQL-базы, раскладывает правильным образом по NoSQL-базам, и те в свою очередь уже занимаются обслуживанием запросов. Это существенно более гибко, чем файлики, потому что размер файлика со временем может начать неконтролируемо расти, да и просто раскладывать его по куче машин — проблематично и чревато всякого рода проблемами типа "на части машин остался старый вариант файла, а никто не заметил".

На самом деле, вместо прослойки из NoSQL-баз может быть простой сервис, который собирает in-memory версию (тот самый "json") и отдаёт его напрямую из памяти. В части случаев это удобнее. Такой сервис асинхронным background-тредом ходит в SQL-базу и регулярно обновляет свой стейт, а наружу торчит интерфейс, который на каждый запрос делает несколько хеш-лукапов в памяти — это тоже очень быстро, бесконечно горизонтально масштабируется, ну и в этом сервисе можно писать любую бизнес-логику.

Самое главное — никаких, никаких, никогда никаких синхронных запросов в SQL-базу на интерактивном трафике.

Да, я поблагодарил за код другого человека и остался при своём мнении о валидности реализации из поста, верно. Замечу только, что предложенное в комментариях решение тоже является верным (о чём я писал), хотя и не подходит для потоковой обработки.

Это вот вечная беда переписки: любое текстовое сообщение можно прочитать с возможной интонацией, и именно эта интонация определит, как будет воспринято исходное сообщение. Я очень, очень-очень стараюсь писать так, чтобы мои сообщения не выглядели высокомерными, надменными и вот это всё, но не всегда это получается :(

Во всяком случае, могу заверить, что у меня никогда нет желания как-то обидеть собеседника или продемонстрировать собственное превосходство. Так что, если я кого-то задел — прошу прощения, это не было целенаправленно. Я правда хотел разобраться.

Вот именно в таком виде, как я описал, — скорее для senior+ позиций. При этом вполне может быть, что о том же самом говорят и с middle, и с junior, просто сам разговор получается существенно иным — меньше тем покрывается, с меньшей глубиной, сам разговор в меньшей степени направляется кандидатом и в большей степени проводящим собеседование.

Это на самом деле логично. ML — очень обширная тема, и её нельзя знать целиком (хотя я бы ожидал на фоне ваших заслуг знания про ROC-AUC или PR-AUC :), поэтому на таких секциях лучше давать задачи из тех областей, что знакомы кандидату. Я так всегда и делаю :)

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

Блестящий материал! Спасибо огромное! :) Прочитал прямо на одном дыхании и много нового полезного для себя понял.

Спасибо, это очень круто! Я не знал раньше об этом свойстве функции Гудстейна.

Меня нанимали прямо во время пандемии. Летом 2020-го.


Но это довольно типично как минимум для биг-теха (и поэтому я думаю, что это скорее правильно, чем нет). Если я много писал на С++ и использовал много разных фреймворков, скорее всего, я смогу освоиться с C# и другими фреймворками. Ну и наоборот.

Ну я тут рискну не согласиться, хотя, очень может оказаться, что мы на самом деле об одном и том же и спорим только о терминах. Например, как именно вы ограничиваете понимание слова "технология". Если его понимать в узком смысле конкретных языков, фреймворков и прочего, то я с вами не согласен. Если в более широком смысле, условно говоря, создания высоконагруженных систем, то быть экспертом в такого рода технологии — вне всяких сомнений, правильный выбор.


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


Грубо говоря, GDBT — это очень хорошо, но в современных реалиях стоит уметь и в BERT. А уж сколько всего сменилось за десять лет в ML, во фронтенде, в облаках, в бекенде — и не перечислить.


Если уж слишком держаться за специфику, вы просто ограничиваете себя в том, на какие позиции можете претендовать и рискуете через небольшое время обнаружить себя неконкурентоспособным на рынке, потому что мода уже сменилась и сейчас все используют что-то новое (и по-другому).


При найме уж слишком много внимания уделять конкретной технологии не стоит по той же причине и хорошие компании уже давно так не делают. Опыт адаптации под новые условия важнее, чем умение использовать конкретный фреймворк. Я много лет программировал на C++ и Python, а теперь в основном пишу на Golang в драматически новом окружении и чувствую себя прекрасно. Те, кто меня нанимал, понимал, что человеку с опытом освоиться на новом стеке вполне возможно за небольшое время — так и произошло.

По-моему, тут штука не в том, чтобы учить что-то "техническое": и математика, и алгоритмы являются просто инструментами, которые полезно знать, чтобы ставить и затем решать задачи хорошо. Чтобы придумать подстановку — нужно всё-таки немного другое :)


На мой вкус, чтобы хорошо справляться с постановкой задач, нужно хорошо понимать цель (чего хотим добиться) и физику процесса (как бы я решал сам, без привлечения инструментов). После этого алгоритмы становятся просто способом автоматизации и повышения качества, для чего они, собственно, и нужны.


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

Вполне. Я сейчас написал вот так и зашло с очень хорошим запасом:


package main

import (
    "bufio"
    "fmt"
    "os"
    "strconv"
)

func main() {
    scanner := bufio.NewScanner(os.Stdin)
    last := 0

    scanner.Scan()
    count, _ := strconv.Atoi(scanner.Text())
    for i := 0; i < count; i++ {
        scanner.Scan()
        current, _ := strconv.Atoi(scanner.Text())
        if i == 0 || last != current {
            fmt.Println(current)
        }
        last = current
    }
}

Я бы не хотел углубляться в детали, т.к. в них много чего можно улучшить. Но, коротко говоря, это эвристика, учитывающая общую вероятность решения задачи (формула, предсказывающая её, обучается только на содержании задач) и персональную вероятность решения задачи (эта формула использует ещё дополнительно информацию об истории успешных и неуспешных решений пользователя).

Вы совершенно правильно всё пишете! Такая проблема вполне может возникнуть. Мы это регулируем тем, что оптимизируем вероятность хорошего решения целикового экзамена, в котором представлены разные темы. Но вообще надо отдельно это проверить, вы совершенно правы.

В приложениях, где кластера являются неотъемлемой частью продукта, лоскутные кластера очень вредны =)


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

Есть два важных класса метрик, которые я не рассматривал :) При этом они упоминаются в цитирующейся статье.


Это информационные метрики на основе энтропии (к этому классу относится описанная вами) и метрики на основе edit distance. В цитируемой статье оба класса коротко рассматриваются, основной проблемой является то, что для них не выполнено условие Rag Bag.


У этих метрик хорошие аналитические свойства, поэтому многие их, действительно, используют. Я в свою очередь их не люблю за то, что не вижу ясного соответствия между физическим смыслом происходящего на сервисе и физическим смыслом метрики. Из-за этого никогда их и не использовал =)

Если я всё правильно понял, это BCubed Precision. Для отдельного элемента BCP равняется в точности вероятности того, что другой случайный элемент из того же кластера относится к тому же эталону, что и выбранный элемент, а интегральный показатель — простое усреднение, эквивалентное равновероятному выбору элементов.


Эта метрика очень хорошая, но учитывает только точность соответствий, но не полноту, так что не может использоваться изолированно.

Вот спасибо! Я писал про то, что один из символов не попадёт в часть, которая подвергается итерации, поэтому количества вхождений различных символов будут различными для $k>1$, но далее выразил эту мысль неаккуратно. Сейчас исправил =)


И опечатку тоже.

Тут очень много интересных связей с другими вопросами, и я понял, что даже простое их упоминание увеличит объём статьи раза в два. Так то пришлось отсекать)
Ну я так скажу: иногда стоит немного обобщить и вынести в библиотеку, а иногда не стоит, т.к. для каждого использования придётся как-то докручивать, и это превратит жизнь в ад. Бывает так, что простые вещи проще реализовать по месту.

Приведу другой пример, но очень похожий. За свою жизнь мне пришлось несколько раз реализовывать [DSU](https://en.wikipedia.org/wiki/Disjoint-set_data_structure). При этом, конечно, у нас есть библиотечная реализация DSU, которую я всякий раз пытался использовать, но не получалось. Дело в том, что всякий раз вместе с каждой операцией надо было делать что-то ещё, что не ложилось в стандартный интерфейс структуры. Теоретически, это можно было бы сделать через наследование и какие-то доопределения, но в таких случаях сложность реализации значительно превосходила сложность реализации собственно DSU, плюс терялась локальность кода, плюс местами появлялись сайд-эффекты. Всякий раз я смотрел на это, немного грустил и реализовывал по месту (благо, на написание DSU уходит примерно 2 минуты с ноля). К счастью, штука простая и немногословная, так что структура с добавленной в неё DSU'шностью содержала, типа, 5% кода про DSU и 95% про остальное.

Ну и фактор времени надо учитывать. Если пытаться обобщать и класть в библиотеки вообще всё, что мы пишем, скорость разработки упадёт, наверное, раз этак в пять. Даже если оставить за скобками конкурентность среды, реализовать в 5 раз меньше классных штук за жизнь не устраивает даже лично меня!

Информация

В рейтинге
Не участвует
Откуда
Лимассол, Government controlled area, Кипр
Дата рождения
Зарегистрирован
Активность