От 0 до машинного обучения с R

Экскурсия по R-кодированию, фреймам данных, применению модели.

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

Однако в Интернете есть фантастические ресурсы:

  • RDocumentation - это сайт, который я использую чаще всего. Если вы знакомы с синтаксисом и поисковой системой, это настоящая золотая жила.
  • Datacamp - отличное место для начала с R (или даже с Python). С новым содержанием каждую неделю и приятными функциями, такими как проекты и задачи.

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

Давайте начнем с R, выберем набор данных и начнем работать с фрагментами кода.

Начиная

Установите R language на свой компьютер.
Установите бесплатную полную IDE: RStudio.

Библиотеки

Базовая установка R не поставляется со всеми библиотеками, как и в случае с pip в Python, новые библиотеки устанавливаются с помощью этой команды в терминале R:

install.packages(tidyverse) # For installing tidyverse

После установки пакета для библиотек можно выполнить несколько операций:

library(readr) # Load library
# Load multiple libraries
p.names <- c(‘xgboost’, ‘caret’, ‘dplyr’, ‘e1071’)
lapply(p.names, library, character.only = TRUE)

installed.packages()                # List available packages
remove.packages("tidyverse")   # Uninstall a package
# Getting help and documentation
?functionName
help(functionName)
example(functionName)

Написание кода

Переменные

Определение переменных довольно просто, мы одинаково используем операторы «=» или «‹ - ». Одна необычная вещь, если вы пришли из Python, заключается в том, что имена переменных могут содержать точки «.» и вы получите такие переменные, как «my.data.vector». На самом деле это очень часто встречается во фрагментах кода, которые можно найти в Интернете.

# Create new variables
my_var <- 54
my.data.vector = c(34, 54, 65)
# Clean a variable
my_var <- NULL

Функции

Функции в R похожи на функции Python:

  • Назначьте функцию, как если бы вы назначали переменную.
  • Используйте ключевое слово function с параметрами внутри скобок.
  • Используйте возврат в качестве точек выхода

Следующая небольшая функция с именем prod_age, принимает в качестве аргумента дату создания. С помощью оператора if мы обрабатываем случаи NULL, в противном случае мы приводим значение как date.

prod_age <- function(creation_date) {
 if (is.na(creation_date)) {return(as.numeric(-1))}
 else {return(as.Date(creation_date))}
}

Работа с фреймами данных

Загружать данные, читать файлы

Функция read_delim из библиотеки readr предлагает множество инструментов для чтения большинства типов файлов.

В приведенном ниже примере мы указываем тип данных каждого столбца. В файле 56 столбцов, и мы хотим, чтобы все они читались как символы, поэтому мы используем аргумент col_types с «c… c», каждый символ соответствует столбцу.

# Load the library
library(readr)
# Create dataframe from CSV file
my_dataframe <- read_delim(“C:/path/to/file.csv”,
   delim = “|”,
   escape_double = FALSE,
   col_types = paste(rep(“c”, 56), collapse = ‘’))

Подмножество фрейма данных

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

  • Для доступа к определенному столбцу используйте оператор $, что очень удобно.
y_train <- my.dataframe$label
  • Для доступа к определенным строкам мы используем оператор []. Возможно, вам знаком этот синтаксис: [строки, столбцы]
# Works with numeric indices
y_train <- my.dataframe[c(0:100), 8]
# Works with negative indices to exclude
y_test <- my.dataframe[-c(0:100), 8]
  • Вот еще один метод, по-прежнему использующий синтаксис скобок. Операторы which и names используются для подмножества строк и столбцов.
filtered.dataframe <- my.dataframe[
   which(my.dataframe$col1 == 2),     # Filter rows on condition
   names(my.dataframe) %in% c("col1","col2","col3")] # Subset cols
  • Функция подмножества: первый аргумент - это фрейм данных, затем условие фильтрации для строк, затем столбцы для выбора.
filtered.dataframe <- subset(
   my.dataframe, 
   col1 == 2, 
   select = c("col1","col2","col3"))

Библиотека dplyr

plyr - популярная библиотека для работы с данными. На его основе появился пакет dplyr, который вводит грамматику для наиболее распространенных проблем манипулирования данными.

Если вы пришли из Python, возможно, вы знакомы с цепочкой команд с точкой. Здесь с dplyr вы можете сделать то же самое с помощью специальной трубы: % ›%. Вот несколько примеров из документа:

starwars %>% 
  filter(species == "Droid")
starwars %>% 
  select(name, ends_with("color"))
starwars %>% 
  mutate(name, bmi = mass / ((height / 100)  ^ 2)) %>%
  select(name:mass, bmi)
starwars %>% 
  arrange(desc(mass))
starwars %>%
  group_by(species) %>%
  summarise(
    n = n(),
    mass = mean(mass, na.rm = TRUE)
  ) %>%
  filter(n > 1)

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

Изменить значения столбца

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

Изменить значения столбца

Когда создается объект фрейма данных, мы получаем доступ к определенным столбцам с помощью оператора $.

# Filtering rows based on a specific column value
my_datarame <- subset(my_dataframe, COLNAME != ‘str_value’)
# Assign 0 where column values match condition
non_conformites$REGUL_DAYS[non_conformites$REGUL_DAYS_NUM < 0] <- 0
# Create new column from existing columns
table$AMOUNT <- table$Q_LITIG * table$PRICE
# Delete a column
my_dataframe$COLNAME <- NULL

Применить функцию к столбцу

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

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

# Product age function
prod_age <- function(creation_date) {
 if (xxx) {return(as.numeric(-1))}
 else { return(as.Date(creation_date))}
}
# Apply function on column
mytable$PRODUCT_AGE <-
 apply(mytable[,c(‘DATE_CREA’), drop=F], 1, function(x) prod_age(x))

Работа с датами

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

# Convert a column into date format
sales$date_f <- as.Date(sales$date, format = ‘%d/%m/%Y’)
# Create column from time difference
mytable$REGUL_DAYS = as.numeric(difftime(
 strptime(mytable$closing, “%Y-%m-%d”),
 strptime(mytable$opening, “%Y-%m-%d”),
 unit=”days”))

Экспорт фрейма данных

Несколько встроенных функций позволяют записывать фреймы данных в виде файлов. Очень распространенный формат - CSV. Однако формат RDS оптимизирован (сериализация + сжатие Gzip) для хранения любых объектов R.

# Write to CSV
write.csv(non_conformites,
 ‘C:\\Users\\path\\export.csv’,
 row.names = FALSE)
# Write to RDS
saveRDS(
 feature_importance_values,
 file=”c:/path/folder/feature_importance.RDS”)

Сюжет

Как и Python, R поставляется с несколькими библиотеками для построения графиков данных. Функция plot фактически аналогична функции plt.plot с python.

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

Графики

plot(
 ref_sales$Date, ref_sales$Sales,
 type = ‘l’,
 xlab = “Date”, ylab = “Sales”,
 main = paste(‘Sales evolution over time for : ‘, article_ref)
)

Различные графики

На языке статистиков R поставляется с различными диаграммами для построения графиков распределения данных.

values <- c(1, 4, 8, 2, 4)
barplot(values)
hist(values)
pie(values)
boxplot(values)

Машинное обучение: библиотека XGBoost

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

Для этой части нам понадобятся эти конкретные библиотеки:
- xgboost: давайте обойдем знаменитый алгоритм XGB.
- каретка: обучение классификации и регрессии, включает множество функций обработки данных
- dplyr: быстрый и последовательный инструмент для работы с объектами, подобными фреймам данных, как в памяти, так и вне ее.

Сплит-тест

Как только фрейм данных подготовлен, мы разделяем его на обучающий и тестовый наборы, используя индекс (inTrain):

set.seed(1337)
inTrain <- createDataPartition(y = my.dataframe$label, p = 0.85, list = FALSE)
X_train = xgb.DMatrix(as.matrix(my.dataframe[inTrain, ] %>% select(-label)))
y_train = my.dataframe[inTrain, ]$label
X_test = xgb.DMatrix(as.matrix(my.dataframe[-inTrain, ] %>% select(-label)))
y_test = my.dataframe[-inTrain, ]$label

Поиск параметров для XGBoost

Что делает следующая функция:
- Принимает в качестве входных данных наши наборы поездов / тестов.
- Определение trainControl для перекрестной проверки.
- Определение сетки для параметров.
- Настройка Модель XGB, включая поиск параметров.
- Оценить точность модели.
- Вернуть набор лучших параметров.

param_search <- function(xtrain, ytrain, xtest, ytest) {
# Cross validation init
 xgb_trcontrol = trainControl(method = “cv”, number = 5, allowParallel = TRUE,
 verboseIter = T, returnData = FALSE)
# Param grid
 xgbGrid <- expand.grid(nrounds = 60, #nrounds = c(10,20,30,40),
 max_depth = 20, #max_depth = c(3, 5, 10, 15, 20, 30),
 colsample_bytree = 0.6,#colsample_bytree = seq(0.5, 0.9, length.out = 5),
 eta = 0.005, #eta = c(0.001, 0.0015, 0.005, 0.1),
 gamma=0, min_child_weight = 1, subsample = 1
 )
# Model and parameter search
 xgb_model = train(xtrain, ytrain, trControl = xgb_trcontrol,
 tuneGrid = xgbGrid, method = “xgbTree”,
 verbose=2,
 #objective=”multi:softprob”,
 eval_metric=”mlogloss”)
 #num_class=3)
# Evaluate du model
 xgb.pred = predict(xgb_model, xtest, reshape=T)
 xgb.pred = as.data.frame(xgb.pred, col.names=c(“pred”))
 result = sum(xgb.pred$xgb.pred==ytest) / nrow(xgb.pred)
 print(paste(“Final Accuracy =”,sprintf(“%1.2f%%”, 100*result)))
return(xgb_model)
}

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

best.model <- xgboost(
 data = as.matrix(my.dataframe[inTrain, ] %>% select(-IMPORTANCE)),
 label = as.matrix(as.numeric(my.dataframe[inTrain,]$IMPORTANCE)-1),
 nrounds = xgb_model$bestTune$nrounds,
 max_depth = xgb_model$bestTune$max_depth,
 eta = xgb_model$bestTune$eta,
 gamma = xgb_model$bestTune$gamma,
 colsample_bytree = xgb_model$bestTune$colsample_bytree,
 min_child_weight = xgb_model$bestTune$min_child_weight,
 subsample = xgb_model$bestTune$subsample,
 objective = “multi:softprob”, num_class=3)

Вычислить и построить график важности характеристик

И снова в пакете xgboost доступно множество функций. В документации представлено большинство из них.

xgb_feature_imp <- xgb.importance(
   colnames(donnees[inTrain, ] %>% select(-label)), 
   model = best.model
)
gg <- xgb.ggplot.importance(xgb_feature_imp, 40); gg

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

дальнейшее чтение

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

Спасибо за внимание, любые отзывы приветствуются, летайте безопасно!