Алгоритм — HackerX https://hackerx.ru Блог о программировании, СУБД, сетях и алгоритмах. Уроки и статьи по разным языкам программирования Wed, 11 Jul 2018 07:15:23 +0000 ru-RU hourly 1 https://wordpress.org/?v=4.9.8 Machine Learning: Зачем нужно машинное обучение https://hackerx.ru/machine-learning-python/ https://hackerx.ru/machine-learning-python/#respond Thu, 07 Dec 2017 15:29:12 +0000 https://hackerx.ru/?p=933 На заре появления «интеллектуальных» приложений многие системы использовали жесткие правила «if» и «else» для обработки данных или корректировки информации, введенной пользователем. Вспомните о спам фильтре, чья работа состоит в том, чтобы переместить соответствующие входящие сообщения электронной почты в папку «Спам». Вы можете составить черный список слов, которые будут идентифицировать письмо как спам. Это пример использования […]

The post Machine Learning: Зачем нужно машинное обучение appeared first on HackerX.

]]>
На заре появления «интеллектуальных» приложений многие системы использовали жесткие правила «if» и «else» для обработки данных или корректировки информации, введенной пользователем. Вспомните о спам фильтре, чья работа состоит в том, чтобы переместить соответствующие входящие сообщения электронной почты в папку «Спам». Вы можете составить черный список слов, которые будут идентифицировать письмо как спам. Это пример использования системы экспертных правил для разработки «интеллектуального» приложения. Разработка правил принятия решений в ручном режиме допустимо в некоторых задачах, особенно в тех, где люди четко понимают процесс моделирования. Однако, использование жестких решающих правил имеет два основных недостатка:

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

Один из примеров, где этот жесткий подход потерпит неудачу – это распознавание лиц на изображениях. На сегодняшний день каждый смартфон может распознать лицо на изображении. Тем не менее, распознавание лиц была нерешенной проблемой, по крайней мере, до 2001 года. Основная проблема заключается в том, что способ, с помощью которого компьютер «воспринимает» пиксели, формирующие изображение на компьютере, очень сильно отличается от человеческого восприятия лица. Эта разница в принципе не позволяет человеку сформулировать подходящий набор правил, описывающих лицо с точки зрения цифрового изображения.

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


Какие задачи можно решить с помощью машинного обучения

Наиболее успешные алгоритмы машинного обучения – это те, которые автоматизируют процессы принятия решений путем обобщения известных примеров. В этих методах, известных как обучение с учителем или контролируемое обучение ( supervised learning ), пользователь предоставляет алгоритму пары объект-ответ, а алгоритм находит способ получения ответа по объекту. В частности, алгоритм способен выдать ответ для объекта, которого он никогда не видел раньше, без какой-либо помощи человека. Если вернуться к примеру классификации спама с использованием машинного обучения, пользователь предъявляет алгоритму большое количество писем (объекты) вместе с информацией о том, является ли письмо спамом или нет (ответы). Для нового электронного письма алгоритм вычислит вероятность, с которой это письмо можно отнести к спаму.

Алгоритмы машинного обучения, которые учатся на парах объект-ответ, называются алгоритмами обучения с учителем, так как «учитель» показывает алгоритму ответ в каждом наблюдении, по которому происходит обучение. Несмотря на то, что создание набора с объектами и ответами – это часто трудоемкий процесс, осуществляемый вручную, алгоритмы обучения с учителем интерпретируемы и качество их работы легко измерить. Если вашу задачу можно сформулировать в виде задачи обучения с учителем, и вы можете создать набор данных, который включает в себя ответы, вероятно, машинное обучение решит вашу проблему.

Примеры задач машинного обучения с учителем:

Определение почтового индекса по рукописным цифрам на конверте.

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

Определение доброкачественности опухоли на основе медицинских изображений.
Здесь объектом будет изображение, а ответом – диагноз, является ли опухоль доброкачественной или нет. Чтобы создать набор данных для построения модели, вам нужна база медицинских изображений. Кроме того, необходимо мнение эксперта, поэтому врач должен просмотреть все изображения и решить, какие опухоли являются доброкачественными, а какие – нет. Помимо анализа изображения может понадобиться дополнительная диагностика для определения доброкачественности опухоли.

Обнаружение мошеннической деятельности в сделках по кредитным картам.
Здесь объект – запись о транзакции по кредитной карте, а ответ — информация о том, является ли транзакция мошеннической или нет. Предположим, вы – учреждение, выдающее кредитные карты, сбор данных подразумевает сохранение всех транзакций и запись сообщений клиентов о мошеннических транзакциях.

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

Алгоритмы обучения без учителя или неконтролируемого обучения (unsupervised algorithms) – это еще один вид алгоритмов, который мы рассмотрим в этой книге. В алгоритмах обучения без учителя известны только объекты, а ответов нет. Хотя есть много успешных сфер применения этих методов, их, как правило, труднее интерпретировать и оценить.

Примеры задач машинного обучения без учителя:

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

Сегментирование клиентов на группы с похожими предпочтениями.
Имея набор записей о клиентах, вы можете определить группы клиентов со схожими предпочтениями. Для торгового сайта такими группами могут быть «родители», «книгочеи» или «геймеры». Поскольку вы не знаете заранее о существовании этих групп и их количестве, у вас нет ответов.

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

The post Machine Learning: Зачем нужно машинное обучение appeared first on HackerX.

]]>
https://hackerx.ru/machine-learning-python/feed/ 0
Теория сложности алгоритмов https://hackerx.ru/complexity-theory-algorithms/ https://hackerx.ru/complexity-theory-algorithms/#respond Sun, 30 Jul 2017 19:13:39 +0000 https://hackerx.ru/?p=208 Кратко говоря, теория сложности — это наука о том, насколько сложны алгоритмы. Чтобы быть полезным, у любого алгоритма должно быть 3 ключевых свойства: Он должен быть корректен. Какой от него толк, если он не дает правильные ответы. Хороший алгоритм должен быть понятен. Даже самый лучший алгоритм не даст пользы, если его слишком сложно реализовать на компьютере. Хороший алгоритм должен быть эффективным. Даже […]

The post Теория сложности алгоритмов appeared first on HackerX.

]]>
Кратко говоря, теория сложности — это наука о том, насколько сложны алгоритмы. Чтобы быть полезным, у любого алгоритма должно быть 3 ключевых свойства:

  1. Он должен быть корректен. Какой от него толк, если он не дает правильные ответы.
  2. Хороший алгоритм должен быть понятен. Даже самый лучший алгоритм не даст пользы, если его слишком сложно реализовать на компьютере.
  3. Хороший алгоритм должен быть эффективным. Даже если алгоритм дает корректный результат, он не сильно поможет, если для этого потребуется тысячи лет или миллиард терабайтов памяти.

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

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

Второй тип — это пространственное сложность. Некоторые алгоритмы использует много памяти или дисковое пространство. Например, хеш таблицы используют больше пространство чем другие структуры данных и это позволяет им находит элементы очень быстро. Другие алгоритмы могут использовать и другие ресурсы, например, алгоритму может требоваться сетевое взаимодействие, в этом случае программа может быть ограничена ширеной канала. Еще алгоритмы могут полагаться на графические ресурсы и также на другие типы оборудование, например, принтеры, 3D принтеры, CPU, сенсоры и другие.

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



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

Теперь вы знаете о типах сложности и условиях, которые могут дать разное поведение. Возможно, вы задались вопросом — Зачем об этом беспокоиться? действительно ли нужно анализировать алгоритм, чтобы доказать его поведение? Нельзя ли просто выполнить его и посмотреть, подходит или нет? Ответ — конечно можно! Попробуйте алгоритм и посмотрите, что произойдет. Но если алгоритм недостаточно быстро работает или у вас недостаточно памяти, то вы потратите много времени. А можно было сразу предсказать, что алгоритм работать не будет. Это одна из причин изучать сложность алгоритмов, уметь предсказывать их поведение. Другая причина — это сравнение производительности с другими алгоритмами. Если вы знаете, что вы будете сортировать уже по большей части отсортированные данные, то используйте сортировку пузырьком, она плоха для рандомных данных, но быстро работает, если данные в основном сортированы.

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

The post Теория сложности алгоритмов appeared first on HackerX.

]]>
https://hackerx.ru/complexity-theory-algorithms/feed/ 0
Нотация «большое О». Изучение производительности алгоритмов https://hackerx.ru/big-o-notation/ https://hackerx.ru/big-o-notation/#respond Tue, 26 Jan 2016 16:22:13 +0000 https://hackerx.ru/?p=224 Нотацию «большое О» можно использовать для изучение производительности алгоритмов. Обычно она рассматривает верхнюю границу производительности алгоритмов, то есть рассматривается поведение в худшем случае. Для практическово использование это самый безопасный способ рассмотрение производительности алгоритма. Если у алгоритма хорошее производительность «большое О», то можно смело его использовать в программе. Так же нотация «большое О» рассматривает асимптотическое поведение алгоритма. Асимптотическое поведение — это производительность алгоритма при росте размера задачи. Часто […]

The post Нотация «большое О». Изучение производительности алгоритмов appeared first on HackerX.

]]>
Нотацию «большое О» можно использовать для изучение производительности алгоритмов. Обычно она рассматривает верхнюю границу производительности алгоритмов, то есть рассматривается поведение в худшем случае. Для практическово использование это самый безопасный способ рассмотрение производительности алгоритма. Если у алгоритма хорошее производительность «большое О», то можно смело его использовать в программе.

Так же нотация «большое О» рассматривает асимптотическое поведение алгоритма. Асимптотическое поведение — это производительность алгоритма при росте размера задачи. Часто размер задачи обозначается как N. Чтобы описать асимптотическое поведение, нужно ответить на вопрос — что случится с производительностью алгоритма, если N сильно вырастет?

Предположите, что вам нужно отсортировать список чисел у вас есть несколько алгоритмов, которые можно использовать. Если список содержит два числа, то есть N=2, то в этом случае не важно какой алгоритм вы используете. Любой алгоритм это сделает за несколько микросекунд.Теперь представим, что в списке есть 10 чисел (N=10), это тоже небольшой список и любой алгоритм будет достаточно быстро сортировать. А предположим, что в списке 100 чисел или 1000 или миллион, тут все становится интереснее.

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

Нотация «большое О» рассматривает производительность алгоритма при росте задачи, потому что только тогда мы сильно беспокоимся. Так как выяснить нотацию «большое О» для алгоритма? Нужно следовать 5 правилам.

  1. Если алгоритм выполняет f(N) шагов для какой то математической функции f, то у алгоритма производительность порядка f от N. Пишется так: O(f(N)).

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

Пример на языке JavaScript:

var max = value[0];
 
for ( var i = 0; i < N; i++ ) {
    if ( value[i] > max ) {
        max = value[i];
    }
}

Переменная max содержит первое значение из массива. Затем выполняется цикл по массиву значений. Если находится значение больше чем max, то max обновляется этим значением. Для массива содержащий N элементов, цикл выполняет N шагов. У этого алгоритма поведение O(N). Это просто линейная функция O(N) = N.

  1. Если алгоритм выполняет f(N) шагов а затем g(N) шагов то у него поведение O(f(N) + g(N)).

Давайте рассмотрим этот алгоритм для нахождение максимального и минимального значение в массиве.

var max = value[0];
 
for ( var i = 0; i < N; i++ ) {
    if ( value[i] > max ) {
        max = value[i];
    }
}


var min = value[0];

for ( var i = 0; i < N; i++ ) {
    if ( value[i] < min ) {
        min = value[i];
    }
}

Начинаем как и раньше, находя максимальное значение. А затем выполняем практически те же шаги, чтобы найти минимальное. Код сначало выполняет N шагов а потом еще раз выполняет N шагов. Его поведение O(N + N) или O(2N).

Если алгоритм выполняет какие то шаги а потом еще какие то, то эти поведение суммируется.

  1. Если функция f больше функций g: f(N) > g(N), то можно для больших задач упростит:  O(f(N) + g(N)) = O(f(N)).

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

Предположим, что алгоритм выполняется N2 шагов а затем еще N шагов. Функция N2 больше чем N для больших N-ов, так что производительность этого алгоритма N2. Чтобы понять почему так, давайте рассмотрим кое-какие цифры.

N N2 N2 + N %N
 10  100  110  10%
 100  10,000  10,100  1%
 1,000  1,000,000  1,001,000  0.1%
 10,000  100,000,000  100,010,000  0.01%
 100,000  10,000,000,000  10,000,100,000  0.001%

А теперь давайте посчитаем сколько шагов нужно программе когда N = 10, N2 = 100 и N2 + N = 110. На этом этапе дополнительное N — это только 10%-ов от общего количество шагов.

Мы видим из таблицы, что при росте задачи дополнительно выполняемые шаги N добавляют все меньше и меньше процентов к общему количеству шагов.

Если этот алгоритм используется в программе, то времени потраченные на дополнительные шаги N будет все меньше и меньше. Например, если N = 100,000 и программе требуется час для выполнение, то дополнительные шаги добавляют лишь третью часть секунды. Об этом просто не стоит беспокоиться.

Обратите внимание, также это правило означает, что можно игнорировать константы, добавляемые к функции: O(C + f(N)) = O(f(N)). Константа C — это тоже функция с константным значением. Поскольку константа меньше чем любая функция, которая увеличивается при увеличение N, можно игнорировать константу.

  1. Если алгоритм выполняет g(N) шагов для каждого из f(N) шагов, то это поведение O(f(N) × g(N)). × Знак умножения.

Вот этот алгоритм определяет есть ли в массиве два одинаковых значение.

for ( var i = 1; i < N; i++ ) {
    for ( var j = 1; j < N; i++ ) {
        if ( i != j && value[i] == value[j] ) {
              return true;
        }
    }
}

Первый цикл проходится по N элементов в массиве, для каждого из элементов второй цикл (внутренние) тоже проходится по N элементов в массиве. Это означает, что поведение алгоритма O(N × N) или O(N2).

  1. Можно игнорировать умножение на константи: O(C × f(N)) = O(f(N)) и O(f(C × N)) = O(f(N)).

Представим, что один алгоритм выполняет порядка N2 шагов а другой 2 × N2 шагов. Даже когда N большое, второму алгоритму понадобится два раза больше времени чем первому. В этом случае нотация «большое О» не позволяет сравнить эти два алгоритма, но их можно сравнить с алгоритмами у которых другая нотация «большое О». Для больших N оба будут медленнее чем алгоритмы O(N) и оба будут быстрее чем алгоритмы O(N2).

Это были правила нотации «большого О». В следующих статьях мы продолжим разговор об алгоритмах.

The post Нотация «большое О». Изучение производительности алгоритмов appeared first on HackerX.

]]>
https://hackerx.ru/big-o-notation/feed/ 0