Машинное обучение и нейронные сети - страница 68

 

4.4 Data Broadcast NumPy (L04: Научные вычисления в Python)



4.4 Data broadcast в NumPy (L04: Научные вычисления в Python)

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

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

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

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

 

4.5 Расширенное индексирование NumPy — представления и копии памяти (L04: Научные вычисления в Python)



4.5 Расширенное индексирование NumPy — представления и копии памяти (L04: Научные вычисления в Python)

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

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

Чтобы проиллюстрировать это, давайте рассмотрим простой пример. Предположим, у нас есть двумерный массив с двумя строками и тремя столбцами. Для удобства я назначу первую строку отдельной переменной с именем «first_row». Теперь важный момент: присваивание первой строки переменной создает представление, а не новый объект. Это означает, что эта переменная просто указывает на расположение исходного массива в памяти. Следовательно, если мы изменим значения в этой переменной, мы также изменим соответствующие значения в исходном массиве.

Чтобы продемонстрировать это, давайте увеличим каждый элемент в переменной «first_row» на 99. Выполнение этой операции не только изменит значения в переменной, но и перезапишет значения в первой строке исходного массива. Такое поведение служит намеком на то, что мы работаем с представлением, а не с независимым объектом. Не знать об этом может быть опасно, так как легко непреднамеренно перезаписать значения в исходном массиве при работе с представлением.

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

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

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

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

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

Логические маски в NumPy — это эффективный и мощный способ фильтрации массивов на основе определенных условий. Булева маска — это просто массив логических значений NumPy (True или False), который имеет ту же форму, что и исходный массив. Применяя логическую маску к исходному массиву, мы можем выбрать элементы, удовлетворяющие заданному условию, и отбросить остальные.

Чтобы создать логическую маску, мы сначала определяем условие, которое возвращает логическое значение для каждого элемента в массиве. Например, предположим, что у нас есть массив с именем arr:

import numpy as np
arr = np.array([1, 2, 3, 4, 5])
Мы можем создать логическую маску на основе условия, например, выбрав только те элементы, которые больше 3:
mask = arr > 3
Результирующая логическая маска, маска, будет [False, False, False, True, True]. Каждый элемент в маске соответствует одной и той же позиции в исходном массиве, указывая, является ли условие истинным или ложным для этого элемента.

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

filtered_arr = arr[mask]
Результирующий filtered_arr будет [4, 5], который содержит только элементы больше 3 из исходного массива.

Логические маски можно комбинировать с помощью логических операторов, таких как & (и), | (или) и ~ (не) для создания более сложных условий. Например:

mask = (arr > 2) & (arr < 5)
filtered_arr = arr[mask]
Это условие выбирает элементы, которые больше 2 и меньше 5, в результате чего filtered_arr имеет значение [3, 4].

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

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

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

 

4.6 Генераторы случайных чисел NumPy (L04: Научные вычисления в Python)



4.6 Генераторы случайных чисел NumPy (L04: Научные вычисления в Python)

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

Начнем с простого примера. Мы начнем с импорта NumPy, библиотеки, которую мы будем использовать для генерации случайных чисел. В NumPy есть модуль random, который содержит различные функции для рисования случайных чисел. Хотя документация, на которую мы будем ссылаться, немного устарела, она содержит полезный список различных функций и их описания.

Одной из часто используемых функций является random.rand, которая генерирует случайные выборки из равномерного распределения. Указав форму желаемого массива (например, 2x3), эта функция создаст двумерный массив, заполненный случайными числами из равномерного распределения.

NumPy также предлагает другие функции, такие как random.random, который генерирует случайные числа с плавающей запятой в полуоткрытом интервале [0, 1]. Вы также можете брать случайные выборки из разных распределений, таких как стандартное нормальное распределение, используя функцию random.randn.

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

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

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

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

Хотя старый класс random_state по-прежнему широко используется, сообщество NumPy теперь рекомендует использовать новый генератор случайных чисел. Этот новый генератор использует другой метод генерации случайных чисел, но для большинства простых приложений выбор между ними не будет иметь заметного значения. Самое главное — установить случайное начальное число для воспроизводимости.

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

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

 

4.7 Изменение формы массивов NumPy (L04: Научные вычисления в Python)



4.7 Изменение формы массивов NumPy (L04: Научные вычисления в Python)

Наконец, мы приближаемся к завершению серии NumPy. Осталось всего три видео, и мы подошли к важной теме: изменению массивов NumPy. Изменение формы массивов имеет решающее значение, когда нам нужно преобразовать наши данные в желаемую форму, например, преобразовать матрицу в вектор или наоборот. Я кратко упомянул эту концепцию во вводной лекции, где обсуждал MNIST. Чтобы проиллюстрировать этот процесс, давайте рассмотрим упрощенный пример.

Представьте, что у нас есть массив размером 28 на 28, представляющий изображение. Обычно каждый элемент массива соответствует значению пикселя. Однако для простоты предположим, что каждый элемент представляет собой всего лишь одну цифру. Итак, у нас есть массив 28 на 28, представляющий цифровое изображение. Однако, если мы хотим использовать этот массив в качестве вектора признаков для классификатора, нам нужно преобразовать его в один длинный вектор с 784 элементами (28 * 28). Каждый обучающий пример будет изображением, и каждое изображение будет иметь 784 признака.

Изменение формы массива можно выполнить с помощью функции изменения формы в NumPy. Например, мы можем преобразовать вектор 1, 2, 3, 4, 5, 6 в матрицу 2 на 3:

array([[1, 2, 3],
       [4, 5, 6]])
Важно отметить, что размеры, указанные при изменении формы, должны соответствовать общему количеству элементов в исходном массиве. Если размеры неверны, произойдет ошибка. Например, попытка преобразовать вектор из 6 элементов в матрицу 3 на 3 приведет к ошибке, поскольку элементов недостаточно.

При изменении формы массива создается представление памяти, а не новый массив. Это представление памяти позволяет нам манипулировать измененным массивом без дублирования данных. Чтобы убедиться в этом, мы можем использовать функцию np.may_share_memory, хотя она не всегда может дать 100% точный результат.

Использование -1 в качестве измерения при изменении формы — удобная функция в NumPy. Он действует как заполнитель, позволяя методу определить подходящее измерение на основе общего количества элементов. Например, если у нас есть вектор с шестью элементами и мы изменим его форму, используя -1, 2, -1 будет заменено на 3, так как есть только один способ упорядочить три строки с двумя столбцами, чтобы получить шесть элементов. Эта концепция заполнителя работает с произвольным количеством измерений.

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

В NumPy есть несколько способов сгладить массив. Функция reshape с -1 создает представление памяти, а функция flatten также сглаживает массив, но создает копию. Другая функция, ravel, также используется для выравнивания массивов. Определение различий между этими функциями было бы хорошим тестом для самооценки.

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

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

 

4.8 Операторы сравнения и маски NumPy (L04: Научные вычисления в Python)



4.8 Операторы сравнения и маски NumPy (L04: Научные вычисления в Python)

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

Начнем с простого примера. Предположим, у нас есть массив NumPy [1, 2, 3, 4] для простоты. Мы можем определить маску для выбора определенных значений из массива. Эта маска будет логическим массивом, что означает, что она будет содержать значения True или False. Мы можем создать маску, указав условие, например, выбрав значения больше двух. Результирующий массив масок будет иметь ту же форму, что и исходный массив, со значениями True, указывающими позиции, где условие истинно, и значениями False, указывающими позиции, где условие ложно.

В Python существует удобная связь между логическими значениями и целыми числами: True эквивалентно 1, а False эквивалентно 0. Эта связь позволяет нам выполнять интересные операции. Например, мы можем использовать оператор if для проверки истинности условия, просто написав if condition:. Мы также можем использовать оператор not, чтобы проверить, является ли условие ложным, написав if not condition:. Эти подходы обеспечивают более читаемый код по сравнению с явным сравнением условия с True или False.

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

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

Бинаризация массива, т. е. преобразование его в двоичное представление, — еще одна распространенная операция. Мы можем добиться этого, присвоив определенное значение позициям, где условие истинно, и другое значение позициям, где условие ложно. Однако ввод всей операции может быть утомительным. К счастью, NumPy предоставляет функцию where, которая упрощает этот процесс. Функция where принимает условие и для позиций, где условие истинно, присваивает первое значение, а для позиций, где условие ложно, присваивает второе значение. Используя where, мы можем легко бинаризировать массив всего одной строкой кода.

В дополнение к операторам сравнения NumPy предлагает логические операторы, такие как и, или, исключающее или не. Эти операторы можно комбинировать с масками для создания более сложных условий. Например, мы можем выбрать значения, которые больше трех или меньше двух, используя оператор или. Комбинируя несколько условий с помощью логических операторов, мы можем создавать сложные маски выбора, соответствующие нашим потребностям.

Эти логические маски, логические операторы и операторы сравнения в NumPy невероятно полезны при работе с наборами данных и реализации правил дерева решений. Мы подробнее рассмотрим эти концепции в следующих видеороликах. В следующем видео мы углубимся в основные концепции линейной алгебры в NumPy. Следите за обновлениями!

 

4.9 Основы линейной алгебры NumPy (L04: Научные вычисления в Python)



4.9 Основы линейной алгебры NumPy (L04: Научные вычисления в Python)

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

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

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

Двигаясь дальше, мы сталкиваемся с основными обозначениями линейной алгебры для умножения матриц. В линейной алгебре умножение матриц эквивалентно вычислению множества скалярных произведений. Например, если у нас есть векторы [1, 2, 3] и [1, 2, 3], их скалярное произведение дает 14. Точно так же скалярное произведение [4, 5, 6] и [1, 2, 3] дает 32. В NumPy мы можем выполнять умножение матриц, используя функцию matmul. Кроме того, для удобства можно использовать оператор @. Однако важно отметить, что в линейной алгебре мы не можем напрямую перемножать матрицы и векторы. Тем не менее, мы можем рассматривать вектор-столбец как матрицу, в частности матрицу 3x1. Этот подход позволяет нам умножать матрицу на вектор, что невозможно в строгой линейной алгебре. Таким образом, NumPy предлагает большую гибкость по сравнению с традиционной линейной алгеброй.

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

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

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

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

На этом мы завершаем обсуждение NumPy и SciPy для научных вычислений в Python. В следующем видео мы продолжим наше путешествие по научным вычислениям, исследуя matplotlib, мощную библиотеку для построения графиков.

 

4.10 Matplotlib (L04: Научные вычисления в Python)



4.10 Matplotlib (L04: Научные вычисления в Python)

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

Переходя к последней теме четвертой лекции, мы рассмотрим matplotlib, популярную библиотеку для построения графиков для Python. Хотя в настоящее время доступно несколько библиотек для построения графиков, наиболее широко используемой остается matplotlib. Лично это также моя любимая библиотека для построения графиков, и ее название вдохновлено Metalab. Синтаксис matplotlib очень похож на MATLAB, что некоторым нравится, а другим нет. Мне, например, не нравилось использовать MATLAB во время учебы в аспирантуре, но я считаю, что matplotlib — отличный инструмент.

Даже если вы не являетесь поклонником MATLAB, я считаю, что matplotlib относительно прост в использовании. Кроме того, он легко интегрируется с NumPy, что является дополнительным преимуществом. Итак, давайте начнем с matplotlib. Я должен отметить, что лично я не запоминаю все специальные способы выполнения задач в matplotlib, потому что это низкоуровневая библиотека. Это означает, что он обеспечивает высокий уровень параметров настройки, но не все из них интуитивно понятны. Поэтому я часто ловлю себя на том, что ищу вещи. Когда мне нужно сделать что-то конкретное, я посещаю галерею matplotlib, где представлены различные примеры. Например, если я хочу создать базовый график, я просто ищу его в галерее, нахожу пример и адаптирую его к своим данным. Этого подхода обычно достаточно для моих нужд. Однако, если вы предпочитаете более подробные руководства, вы также можете изучить веб-сайт matplotlib.org, который предлагает пояснительные руководства по различным аспектам matplotlib.

Начнем с того, что при работе с matplotlib в Jupyter Lab или Jupyter Notebooks вы можете использовать встроенную функцию для отображения графиков внутри самой записной книжки. Это означает, что графики будут отображаться непосредственно в записной книжке, что позволяет избежать необходимости в отдельном окне. Хотя есть альтернативные способы добиться этого, я лично рекомендую использовать встроенный подход, поскольку он более надежен на разных компьютерах. Чтобы активировать встроенный режим, вы можете использовать следующую волшебную команду: %matplotlib inline. В качестве альтернативы вы можете добавить точку с запятой в конце операторов сюжета, что обычно приводит к тому же результату. Однако рекомендуется использовать plt.show() для отображения графиков, так как прием с точкой с запятой может не работать на некоторых компьютерах.

Теперь давайте погрузимся в создание простых графиков с помощью matplotlib. Например, мы можем начать с построения кривой синусоиды. Для этого мы можем использовать функцию np.linspace, чтобы сгенерировать 100 значений в диапазоне от нуля до десяти, а затем нанести эти значения на график относительно np.sin, функции синуса. Самый простой способ создать график — использовать функцию plt.plot, где plt — это сокращение от matplotlib.pyplot. Мы можем настроить диапазоны осей графика, используя функции plt.xlim и plt.ylim, чтобы установить пределы для осей x и y соответственно. Кроме того, мы можем добавить метки к оси x и оси y, используя функции plt.xlabel и plt.ylabel. Наконец, чтобы отобразить график, мы можем использовать функцию plt.show() или добавить точку с запятой в конце операторов графика, чтобы подавить нежелательный вывод.

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

Вот пример фрагмента кода, демонстрирующий создание нескольких подзаголовков:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace( 0 , 10 , 100 )
y1 = np.sin(x)
y2 = np.cos(x)

fig, axs = plt.subplots( 2 , 1 )  # Create a figure with 2 subplots arranged vertically

# Plot the sine curve in the first subplot
axs[ 0 ].plot(x, y1)
axs[ 0 ].set_title( 'Sine Curve' )  # Set a title for the subplot
axs[ 0 ].set_xlabel( 'X' )
axs[ 0 ].set_ylabel( 'Y' )

# Plot the cosine curve in the second subplot
axs[ 1 ].plot(x, y2)
axs[ 1 ].set_title( 'Cosine Curve' )
axs[ 1 ].set_xlabel( 'X' )
axs[ 1 ].set_ylabel( 'Y' )

plt.tight_layout()  # Adjust the spacing between subplots for better readability
plt.show()  # Display the figure
В этом примере мы используем функцию plt.subplots, чтобы создать фигуру с двумя подграфиками, расположенными вертикально (2, 1). Функция возвращает фигурный объект fig и массив объектов осей axs с размерами, соответствующими указанному макету подграфика. Мы можем получить доступ к каждому подграфику, проиндексировав массив axs.

Внутри блоков кода, специфичных для подграфика, мы используем функцию plot для построения соответствующих кривых, а затем настраиваем заголовок каждого подграфика, метку оси X и метку оси Y, используя функции set_title, set_xlabel и set_ylabel соответственно.

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

Вы можете попробовать запустить этот код в Jupyter Notebook или Jupyter Lab, чтобы увидеть результирующий рисунок с синусоидальными и косинусными кривыми, отображаемыми на отдельных подграфиках.

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

 

5.1 Чтение набора данных из табличного текстового файла (L05: Машинное обучение с помощью Scikit-Learn)



5.1 Чтение набора данных из табличного текстового файла (L05: Машинное обучение с помощью Scikit-Learn)

Всем привет! Я надеюсь, что у вас была отличная неделя и у вас была возможность поработать со всем материалом NumPy. На этой неделе мы сосредоточимся на обработке данных и машинном обучении с помощью scikit-learn, поэтому очень важно иметь хорошее представление о NumPy. Я считаю, что невероятно полезно практиковаться в кодировании и применять концепции, которые мы изучаем, на примерах из реальной жизни, поэтому в этой лекции мы будем заниматься программированием заранее. Это пригодится нам позже в классе, когда мы широко будем использовать эти инструменты. Говоря об этом, к этой лекции больше нечего добавить, за исключением того, что я загрузил первое большое домашнее задание, которое проверит вас в концепциях, которые мы рассмотрели в предыдущих лекциях, включая контролируемое обучение и примеры кода с использованием NumPy. Это отличная возможность получить практический опыт работы с алгоритмом K-ближайших соседей, а также изучить NumPy и изучить scikit-learn.

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

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

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

Двигаясь дальше, мы обсудим подготовку обучающих данных с использованием API преобразователя scikit-learn. Мы также рассмотрим определение конвейеров scikit-learn, которые помогают нам связывать различные операции, такие как подготовка набора данных, масштабирование, нормализация, уменьшение размерности и сам классификатор. Используя конвейеры, мы можем создавать эффективные рабочие процессы обучения, которые связывают различные аспекты процесса машинного обучения, делая его более удобным. Это одна из значительных сильных сторон scikit-learn.

Для этой лекции я снова решил использовать слайды. Хотя Jupiter Lab — фантастический инструмент, мне проще объяснять некоторые концепции, комментируя примеры кода ручкой или карандашом. Итак, на этих слайдах я захватил скриншоты из Jupiter Lab и Jupiter Notebook, которые буду аннотировать во время лекции. Тем не менее, я также загрузил весь блокнот с кодом на GitHub, где вы можете найти дополнительные пояснения. Рассматривайте этот документ как необязательный конспект курса или лекции для справки.

Давайте быстро вспомним, где мы находимся в этом курсе. Мы начали с введения в машинное обучение, рассмотрели основы и рассмотрели, как работает scikit-learn. Затем мы углубились в Python, изучая NumPy и научные вычисления. Теперь мы вступаем в фазу обработки данных и машинного обучения с помощью scikit-learn. В следующей лекции мы вернемся к основным концепциям машинного обучения, таким как деревья решений, ансамблевые методы и оценка моделей. Хотя это последняя часть лекций по основам вычислений, это не означает, что это конец курса. После завершения лекций по вычислительным основам мы перейдем к более сложным темам машинного обучения, включая глубокое обучение и нейронные сети.

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

Чтобы прочитать файл CSV в Python, мы можем использовать библиотеку Pandas. Pandas предоставляет мощные инструменты для обработки и анализа данных, что делает его популярным выбором для работы с табличными данными в Python. Давайте рассмотрим пример:

import pandas as pd

# Read the CSV file into a DataFrame
data = pd.read_csv( 'data.csv' )

# Display the first few rows of the DataFrame
print(data.head())

В этом примере мы сначала импортируем библиотеку pandas и называем ее псевдонимом pd для удобства. Затем мы используем функцию read_csv() для чтения CSV-файла data.csv в DataFrame, который представляет собой двумерную табличную структуру данных, предоставляемую Pandas. DataFrame хранится в переменной data.

После чтения данных мы можем использовать функцию head() для отображения первых нескольких строк DataFrame. Это позволяет нам быстро проверить данные и убедиться, что они были прочитаны правильно.

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

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

Одним из распространенных этапов предварительной обработки является обработка пропущенных значений. Отсутствующие значения часто представлены в данных как значения NaN (не число) или NULL. Эти отсутствующие значения могут вызвать проблемы при обучении моделей машинного обучения, поэтому нам нужно правильно с ними обращаться. Pandas предоставляет несколько функций для обработки отсутствующих значений, таких как isna() для проверки отсутствующих значений, fillna() для заполнения отсутствующих значений указанным значением и dropna() для удаления строк или столбцов с отсутствующими значениями.

Кодирование категориальных переменных — еще один важный шаг. Модели машинного обучения обычно работают с числовыми данными, поэтому нам нужно преобразовать категориальные переменные в числовое представление. Одним из распространенных методов кодирования является горячее кодирование, при котором мы создаем двоичные столбцы для каждой категории и указываем наличие или отсутствие категории с помощью 1 или 0 соответственно.

import pandas as pd

# Create a DataFrame with categorical variables
data = pd.DataFrame({ 'color' : [ 'red' , 'blue' , 'green' , 'red' , 'green' ]})

# Perform one-hot encoding
encoded_data = pd.get_dummies(data)

# Display the encoded data
print(encoded_data)
В этом примере мы создаем DataFrame со столбцом «цвет», содержащим категориальные переменные. Затем мы используем функцию get_dummies() из Pandas для выполнения одноразового кодирования. Результирующие закодированные данные содержат двоичные столбцы для каждой уникальной категории в исходном столбце «цвет».

Масштабирование числовых признаков — еще один распространенный этап предварительной обработки. Многие алгоритмы машинного обучения чувствительны к масштабу функций. Если функции имеют разные масштабы, это может повлиять на производительность модели. Чтобы решить эту проблему, мы можем масштабировать функции до стандартного диапазона, например, от 0 до 1 или от -1 до 1. Pandas предоставляет классы MinMaxScaler и StandardScaler в модуле sklearn.preprocessing для выполнения масштабирования функций.

import pandas as pd
from sklearn.preprocessing import MinMaxScaler

# Create a DataFrame with numerical features
data = pd.DataFrame({ 'age' : [ 25 , 30 , 35 , 40 ], 'income' : [ 50000 , 60000 , 70000 , 80000 ]})

# Perform feature scaling using MinMaxScaler
scaler = MinMaxScaler()
scaled_data = scaler.fit_transform(data)

# Convert the scaled data back to a DataFrame
scaled_df = pd.DataFrame(scaled_data, columns=data.columns)

# Display the scaled data
print(scaled_df)
В этом примере мы создаем DataFrame с двумя числовыми характеристиками: «возраст» и «доход». Затем мы используем класс MinMaxScaler из модуля sklearn.preprocessing для масштабирования функций. Метод fit_transform() масштабирует данные, и полученные масштабированные данные сохраняются в переменной scaled_data в виде массива NumPy. Наконец, мы конвертируем масштабированные данные обратно в DataFrame и отображаем их.

Наконец, разделение данных на наборы для обучения и тестирования имеет решающее значение для оценки производительности моделей машинного обучения. Обычно мы разделяем данные на два набора: обучающий набор, используемый для обучения модели, и тестовый набор, используемый для оценки ее производительности. Pandas предоставляет функцию train_test_split() в модуле sklearn.model_selection для разделения данных на наборы для обучения и тестирования.

import pandas as pd
from sklearn.model_selection import train_test_split

# Read the CSV file into a DataFrame
data = pd.read_csv( 'data.csv' )

# Split the data into features and labels
X = data.drop( 'label' , axis= 1 )
y = data[ 'label' ]

# Split the data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size= 0.2 , random_state= 42 )
В этом примере мы сначала читаем CSV-файл data.csv в DataFrame. Затем мы разделяем данные на функции X и метки y, где X содержит все столбцы, кроме столбца «метка», а y содержит только столбец «метка».

Затем мы используем функцию train_test_split(), чтобы разделить данные на наборы для обучения и тестирования. Мы передаем функции X и метки y, указываем желаемый размер теста (например, 0,2 для 20-процентного набора тестов) и устанавливаем случайное состояние для воспроизводимости.

После разделения данных мы можем использовать обучающий набор (X_train и y_train) для обучения нашей модели машинного обучения и оценки ее производительности на тестовом наборе (X_test и y_test).

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

 

5.2 Базовая обработка данных (L05: Машинное обучение с помощью Scikit-Learn)



5.2 Базовая обработка данных (L05: Машинное обучение с помощью Scikit-Learn)

В предыдущем видео мы обсуждали, как читать табличный текстовый файл как набор данных. В частности, мы сосредоточились на работе с CSV-файлом и, в частности, с набором данных Iris. Мы импортировали набор данных Iris из CSV-файла в Pandas DataFrame.

В этом видео мы углубимся в подготовку данных в соответствующем формате для машинного обучения с помощью scikit-learn. Мы изучим основные методы обработки данных, используя Pandas и NumPy, чтобы преобразовать данные в подходящий формат для машинного обучения. Но прежде чем мы продолжим, давайте кратко повторим концепцию функций Python, поскольку она пригодится, когда мы будем обсуждать преобразование значений в Pandas DataFrame.

Здесь у нас есть простая функция Python с именем «some_func». Он принимает один входной аргумент «x» и преобразует его в строку. Затем он объединяет преобразованное значение с фиксированной строкой «hello world». Если мы предоставим целое число, например 123, в качестве входных данных, оно будет преобразовано в строку («123») и объединено с «hello world», в результате чего получится окончательная строка. Это базовый обзор того, как работают функции Python, с двоеточием, обозначающим тело функции, и оператором возврата, указывающим результат. Хотя внутри функции может быть несколько строк кода, оператор return отмечает конец.

Еще одна концепция, о которой стоит упомянуть, — это лямбда-функции. Лямбда-функции — это сокращенный способ определения небольших функций без явного их именования. Они обычно используются, когда нужно сохранить строки кода и быстро написать функции. В контексте преобразования данных в столбцах Pandas часто используются лямбда-функции. Хотя лямбда-функции имеют более лаконичный синтаксис, по существу они выполняют те же операции, что и обычные функции. Они особенно полезны в сочетании с методом apply в столбце Pandas DataFrame.

В предыдущей лекции мы считывали набор данных Iris в Pandas DataFrame из CSV-файла. Набор данных Iris состоит из 150 строк, но для краткости мы показываем только первые пять строк. Набор данных включает столбец идентификатора, который не является обязательным, за которым следуют функции, представленные матрицей дизайна X. У нас также есть метки классов, обычно обозначаемые как y. Традиционно scikit-learn и другие библиотеки не обрабатывали строковые переменные как метки классов, поэтому было принято преобразовывать их в целые числа. Например, «Iris setosa» будет преобразовано в целое число 0, «Iris versicolor» — в 1, а «Iris virginica» — в 2. Это преобразование было необходимо, поскольку многие алгоритмы были разработаны для работы с метками целочисленных классов, а не строковыми метками.

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

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

Чтобы продемонстрировать преобразование, мы перезагружаем набор данных в исходное состояние. Затем, вместо применения, мы используем функцию карты для преобразования строковых меток в целые числа с помощью словаря сопоставления. Мы также демонстрируем использование атрибута values, который обращается к базовому массиву NumPy. Работа с массивами NumPy.

Работа с массивами NumPy может быть полезна по нескольким причинам. Массивы NumPy более эффективно используют память по сравнению с Pandas DataFrames, что делает их идеальными для больших наборов данных. Кроме того, многие алгоритмы машинного обучения в scikit-learn ожидают, что входные данные будут в виде массивов NumPy.

Чтобы преобразовать наш Pandas DataFrame в массивы NumPy, мы можем просто получить доступ к атрибуту values в DataFrame. Давайте посмотрим пример:

import pandas as pd
import numpy as np

# Reload the Iris dataset
iris_df = pd.read_csv( 'iris.csv' )

# Convert the features (X) into a NumPy array
X = iris_df.drop([ 'species' ], axis= 1 ).values

# Convert the class labels (y) into a NumPy array
y = iris_df[ 'species' ].values
В этом примере мы используем метод отбрасывания DataFrame, чтобы удалить столбец «виды» и получить функции в виде DataFrame. Затем, обратившись к атрибуту values, мы конвертируем функции в массив NumPy и присваиваем его переменной X.

Точно так же мы получаем доступ к столбцу «виды» DataFrame с помощью оператора индексации [] и преобразовываем его в массив NumPy, назначая его переменной y.

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

Допустим, мы хотим разделить наш набор данных на наборы для обучения и тестирования для оценки модели. Scikit-learn предоставляет вспомогательную функцию, называемую train_test_split, которая упрощает эту задачу. Вот пример:

 from sklearn.model_selection import train_test_split

# Split the data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size= 0.2 , random_state= 42 )
В этом примере мы импортируем функцию train_test_split из модуля sklearn.model_selection. Мы передаем массивы X и y в качестве аргументов функции вместе с параметром test_size, указывающим долю набора данных, выделяемую для тестирования (в данном случае 20%). Параметр random_state обеспечивает воспроизводимость разделения.

После вызова train_test_split мы получаем четыре массива: X_train и y_train содержат данные обучения, а X_test и y_test содержат данные тестирования.

Теперь вы можете использовать массивы X_train и y_train для обучения модели машинного обучения и оценки ее производительности с помощью массивов X_test и y_test.

Таким образом, преобразуя Pandas DataFrame в массивы NumPy, мы можем использовать преимущества NumPy, такие как эффективность использования памяти и совместимость с алгоритмами машинного обучения. Кроме того, scikit-learn предоставляет удобные функции, такие как train_test_split, для разделения данных на наборы для обучения и тестирования.

 

5.3 Объектно-ориентированное программирование и классы Python (L05: Машинное обучение с помощью Scikit-Learn)



5.3 Объектно-ориентированное программирование и классы Python (L05: Машинное обучение с помощью Scikit-Learn)

Прежде чем мы углубимся в тему машинного обучения с помощью scikit-learn в следующей лекции, давайте обсудим объектно-ориентированное программирование, в частности классы Python. Понимание классов будет очень важным, поскольку scikit-learn в значительной степени опирается на концепции объектно-ориентированного программирования. Ближе к концу этого видео я продемонстрирую реализацию K-ближайших соседей с использованием API scikit-learn, который является подходом, который scikit-learn использует для реализации оценщиков, таких как классификаторы.

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

В Python мы определяем класс, используя ключевое слово class, за которым следует имя класса. Внутри класса мы определяем различные методы класса. Методы класса похожи на функции, но у них есть обязательный первый аргумент с именем self, который относится к самому объекту. Этот аргумент self позволяет нам получить доступ к атрибутам и методам объекта. Другими словами, он позволяет нам взаимодействовать с данными и поведением объекта.

В контексте примера с транспортным средством рассмотрим простой наивный класс транспортного средства. Этот класс представляет различные типы транспортных средств, таких как автомобили, мотоциклы или грузовики. Класс имеет различные методы для определения своего поведения. Первый метод — это метод __init__, также известный как конструктор. Этот метод автоматически выполняется при создании нового объекта из класса. Он принимает аргумент self и любые дополнительные аргументы, необходимые для инициализации объекта.

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

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

Кроме того, мы можем определить методы, которые возвращают значения на основе атрибутов объекта. В этом примере метод horsepower_to_torque вычисляет значение крутящего момента на основе мощности объекта и предоставленного значения RPM. Этот метод демонстрирует, как можно использовать атрибуты объекта для выполнения вычислений и получения полезных результатов.

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

Кроме того, Python поддерживает наследование классов, что позволяет нам создавать дочерние классы, которые наследуют свойства и методы родительского класса. Эта концепция позволяет нам создавать специализированные классы с дополнительными атрибутами и поведением, используя существующие функции, определенные в родительском классе. Например, мы могли бы создать специализированный класс Car, который наследуется от класса Vehicle и добавляет атрибут number_of_wheels специально для автомобилей.

Чтобы проиллюстрировать обсуждаемые концепции, приведен пример классификатора K ближайших соседей. Эта реализация следует соглашениям API scikit-learn и демонстрирует использование класса оценщика в scikit-learn. Вот упрощенная реализация:

 class KNNClassifier:

    def __init__( self , k):
         self .k = k
         self .X_train = None
         self .y_train = None
    
    def fit( self , X_train, y_train):
         self .X_train = X_train
         self .y_train = y_train
    
    def predict( self , X_test):
        predictions = []
         for x in X_test:
            distances = []
             for i, x_train in enumerate( self .X_train):
                distance = self ._calculate_distance(x, x_train)
                distances.append((distance, self .y_train[i]))
            distances.sort()
            k_nearest = distances[: self .k]
            prediction = self ._majority_vote(k_nearest)
            predictions.append(prediction)
         return predictions
    
    def _calculate_distance( self , x1, x2):
         # Calculate the distance between two data points
         # (e.g., Euclidean distance)
        pass
    
    def _majority_vote( self , neighbors):
         # Determine the majority class among the nearest neighbors
        pass

В этом примере KNNClassifier — это класс, представляющий классификатор K ближайших соседей. Конструктор принимает параметр k, который указывает количество ближайших соседей для рассмотрения.

Метод подгонки используется для обучения классификатора. Он принимает два аргумента: X_train (данные для обучения) и y_train (соответствующие метки). Метод просто сохраняет обучающие данные и метки в атрибутах объекта для последующего использования.

Метод прогнозирования используется для прогнозирования новых данных. Он принимает X_test (тестовые данные) в качестве аргумента и возвращает предсказанные метки для тестовых данных. Для каждой точки данных в X_test метод вычисляет расстояния до всех точек данных в обучающем наборе, используя метод _calculate_distance. Затем он выбирает k ближайших соседей и определяет класс большинства, используя метод _majority_vote. Прогнозируемая метка добавляется к списку прогнозов.

Метод _calculate_distance — это закрытый метод (обозначается начальным подчеркиванием), который вычисляет расстояние между двумя точками данных. Это может быть евклидово расстояние или любая другая метрика расстояния, подходящая для задачи.

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

Этот пример демонстрирует базовую структуру класса оценщика в scikit-learn. Конечно, scikit-learn обеспечивает более сложную и оптимизированную реализацию K-ближайших соседей в классе KNeighborsClassifier, но эта упрощенная версия иллюстрирует основные принципы.

Причина обращения: