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

Введение

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

Ансамбли - это в основном модели прогнозирования, которые объединяют прогнозы «слабых учеников» для создания одного «сильного предиктора».

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

Работающий

Чтобы понять, как работает случайный лес, нам нужно понять значение «упаковки» или «агрегирования начальной загрузки».

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

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

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

Весь этот процесс можно изобразить с помощью следующего изображения:

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

Этот неизвестный фрукт имеет следующие атрибуты: диаметр = 3, он оранжевого цвета, растет летом, имеет круглую форму.

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

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

  • После их обучения мы «пропускаем» наш тестовый экземпляр через каждое из этих деревьев и видим на нем их предсказания.
  • Взяв первое дерево, мы видим, что сначала оно спрашивает, имеет ли диаметр ≥3? для тестового экземпляра это правда, так что он идет по правильному пути. Затем дерево спрашивает, оранжевый ли цвет. Опять же, это правда, поэтому мы идем по правильному пути, в результате чего предсказание оказывается апельсином.
  • Точно так же для дерева 2 и дерева 3 мы получаем прогнозируемую метку как «апельсин».
  • Таким образом, метка, которая появляется максимальное количество раз из всех трех прогнозов, будет «оранжевой».

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

Выполнение

Я реализовал этот алгоритм в наборе данных о раке груди, который вы можете найти здесь.

  • Импортируйте библиотеки numpy и pandas.
  • pandas.read_csv () используется для чтения файла csv и сохранения фрейма данных в переменном наборе данных.
  • Я проверил нулевые значения с помощью numpy.isnull (). Sum (). В этом наборе данных нет нулевых значений.
  • Я преобразовал свой фрейм данных в массив numpy, потому что мне лично легче использовать его операции нарезки (я также могу легко перетасовать строки с помощью np.random.shuffle (‹array›), и мне не нужно использовать dataframe.iloc каждый раз, когда я хочу получить доступ к столбцу или строке).
  • Я разделил свой набор данных в соотношении 75:25 на набор для обучения и тестирования. Я сделал это, сначала обнаружив индекс в 3/4 моего набора данных. Поскольку я использую Python 3.x, мне пришлось бы использовать целочисленное деление, которое использует «//» вместо «/» для нормального деления. Это деление дало бы мне интегральное значение, а не плавающее.
  • поезд = набор данных [: idx,:] и тест = набор данных [idx:,:]. Обратите внимание, я не разделил поезд на x_train и y_train. Аналогичный футляр для набора для тестирования. По мере того, как мы рассмотрим функции, вы поймете, почему.

Функции дерева решений

define count_label (‹раздел набора данных›): он создает словарь для разных типов значений в нашей переменной ответа. В нашем случае разные типы значений в «диагностике» - это либо 0, либо 1.

В словаре «cnt» для каждого типа в столбце ответа хранится количество его повторений.

определить энтропию (‹раздел набора данных›): он находит энтропию или случайность во всем наборе данных (в частности, в переменной ответа, которая в нашем случае «диагностика»).

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

энтропия = Σ (-n / всего) * log (n / total) где,

  • total = количество строк в этом разделе и,
  • n = количество вхождений для определенного типа.

define info_gain (left_split, right_split, parent_entropy): где left и right - левая и правая часть набора данных после разделения.

Он сообщает нам, сколько информации получается после разделения на:

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

узел класса:

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

Итак, для всех узлов, которые не являются листовыми, мы будем хранить все, кроме предсказанной метки.

Чтобы узнать, является ли узел листом, мы используем метод is_leaf (), который возвращает истину, если предсказанная метка не равна нулю.

определить раздел (‹строк раздела›, значение вопроса, характеристика):

Итак, значение вопроса соответствует функции или столбцу, на основе которого мы разделяем. Он создает левую и правую секции на основе этого «порогового значения» или значения вопроса.

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

Он возвращает разделы в виде массивов numpy.

определить best_split (строки, столбец):

здесь строка определяет раздел набора данных, который нужно разделить, а столбец - это список функций, которые уже используются при разделении.

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

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

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

Возвращает переменные ques и attr None, если нет разделения с приростом информации ›0.

определить build_tree (строки, max_depth, столбец):

  • Столбец - это список функций, которые уже используются при разбиении.
  • max_depth дает нам предел, до которого мы позволим нашему дереву расти.
  • rows - это набор данных.

Выполняемые им задачи:

  • Сначала он находит лучшее разбиение с помощью функции best_split.
  • Если возвращаемое значение атрибута не равно None, затем выполняется определение того, содержит ли наша переменная ответа только один тип значения или нет. Он также обновляет список столбцов.
  • Он возвращает листовой узел, если max_depth равен 0, или атрибут / функция имеет значение None или разделение является чистым (количество типов = 1).
  • В противном случае мы разделяем строки на левую и правую части и рекурсивно вызываем build_tree для обоих разделов, уменьшив max_depth на 1 и используя наш обновленный список столбцов.

define find_common_label (column): для данной функции он возвращает наиболее распространенный тип значения.

define_root (rows, max_depth): он вызывает функцию build_tree () и сохраняет корень нашего дерева решений.

define pred (test_set, root): он берет корень дерева решений, смоделированного с использованием наших обучающих данных, и для каждой тестовой строки в тестовом наборе дает прогнозы.

define traverse_tree (test_row, node): он сравнивает значение функции в тестовой строке со значением вопроса, хранящимся в нашем дереве решений.

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

Если он достигает конечного узла, он возвращает предсказанную метку.

Уф, что много функций для деревьев решений.

Случайные функции леса

define random_forest_classifier (): в качестве аргументов принимает количество деревьев, обучающий набор, тестовую строку (исключая столбец ответа), максимальную глубину дерева.

  • Каждому дереву присваиваются образцы из обучающей выборки.
  • Они обучаются с использованием наших функций дерева решений.
  • Мы добавляем каждый корень дерева в список «деревья», а предсказания дерева - в список «predictions_per_tree».

определить get_samples (обучающий набор):

Мы выбираем случайные индексы строк с помощью np.random.choice (). Я выбрал размер выборки, равный одной трети набора поездов.

Эти случайно выбранные строки затем добавляются в список выборки и затем возвращаются.

определить random_forest_predict (tree_predictions, actual_test_response_labels): Мы подсчитываем прогнозы для каждой строки каждого дерева и находим метку большинства, которая затем возвращается в качестве окончательного результата.

Я взял количество деревьев = 5 и max_depth = 100. Эти значения дали мне точность 92,3%.

****************************************************************

Преимущества:

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

Недостатки:

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

************************************************************

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

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

Итак, спасибо всем читателям, которые нашли время своего дня, чтобы прочитать этот блог. Удачного дня 😄 !!!