Прелюдия

Эта статья является дополнением к серии из трех статей (части I, II и III), которые я ранее публиковал здесь, в своем блоге на Medium, и подробно объясняет, как можно воспроизвести раздел сравнительного анализа в предстоящем выпуске. статья о новом алгоритме выбора переменных. Не читайте эту статью, не прочитав ее предварительно, она не будет иметь никакого смысла, более того, не должна без предварительного ознакомления с ней. Я пишу это дополнение, потому что, несмотря на то, что мои сценарии R, на которые ссылаются и которые объясняются в этих статьях, остались такими же, какими они были, когда я писал их в GitHub Repo, я решил запустить каждый алгоритм тестирования и вычислить результаты (модель классификации показатели производительности для него) в подмножествах размером 5 000, 10 000 или 15 000 за раз из 260 000 общих наборов синтетических выборок, как вы можете видеть на следующих двух снимках экрана:

Но оказалось, что главный автор и исследователь организовал результаты производительности своего алгоритма предполагаемой исчерпывающей регрессии, о котором на самом деле идет речь в статье и исследовании, в подмножествах размером по 500 за раз, с на порядок большей степенью детализации, чем у меня. Если бы я не был настолько параноиком, чтобы планировать смутную и отдаленную возможность чего-то подобного, мне пришлось бы потратить неделю или две на утомительный повторный запуск трех тестов, но я сохранил переменные, выбранные для каждого из них. 260 тысяч наборов данных по каждому тесту в книгах Excel и файлах CSV в качестве страхового полиса.

Средство

Путь вперед был ясен, раздражающе и утомителен, но ясен. Все, что мне нужно было сделать, это перезагрузить CSV-файлы, в которых было 5 000, 10 000 или 15 000 наборов выбранных переменных, истинных факторов, невыбранных переменных и нерелевантных факторов обратно в R (я говорю «ре», потому что изначально они были созданные с использованием функций write.csv() в R), напишите новый код, чтобы разделить их на 10, 20 или 30 подмножеств по 500 в каждом в том же порядке, а затем пересчитать производительность. снова метрики для всех этих меньших подмножеств. Вот пример того, как выглядят те CSV-файлы, в которых я сохранил переменные, выбранные для подмножества из 5 000, 10 000 или 15 000 выборочного набора данных для данного алгоритма Benchmark, в данном случае для BM1 - LASSO:

Синтаксис кода R, используемого для перезагрузки набора из 5 тыс., 10 тыс. или 15 тыс. выборок и структурных переменных, хранящихся в файлах csv, и разделения их на 10, 20 или 30 меньших подмножеств по 500 наборов данных каждый соответственно, можно найти в сценарий R под названием исходный сценарий дезагрегирования результатов в папке Сценарии этапа 2 в репозитории GitHub для этого проекта, вот код этого сценария:

library(readr)

selections_set <- readr::read_csv("LASSO's Selections via glmnet for the DSs from '0-12-1-1 to 0-12-10-500'.csv", col_names = TRUE)

# Number of rows per subset
rows_per_subset <- 500

# Number of subsets
n_subsets <- nrow(selections_set) %/% rows_per_subset

# Create a list to store the subsets
subsets <- list()


# Loop through and create the subsets
for(i in 1:n_subsets) {
  start_row <- (i - 1) * rows_per_subset + 1
  end_row <- i * rows_per_subset
  subsets[[i]] <- selections_set[start_row:end_row,] }

# If there are remaining rows that don't fit into a full 500-row subset
remaining_rows <- nrow(selections_set) %% rows_per_subset
if (remaining_rows > 0) {
  subsets[[n_subsets + 1]] <- selections_set[(n_subsets * rows_per_subset + 1):nrow(selections_set), ]}

Этот код создаст список подмножеств с помощью цикла for, каждое из которых будет содержать 500 наблюдений (или меньше для последнего подмножества, если количество строк не делится на 500). Доступ к этим подмножествам можно получить с помощью списка «подмножества».

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

# Inside the loop
for(i in 1:n_subsets) {
  start_row <- (i - 1) * rows_per_subset + 1
  end_row <- i * rows_per_subset
  subset <- selections_set[start_row:end_row,]
  subsets[[i]] <- subset
  write.csv(subset, paste0("subset_", i, ".csv"), row.names = FALSE) }

По правде говоря, еще до того, как попытаться написать это самому, я спросил Chat GPT 4, используя подсказку для однократного обучения, и код в полученном ответе сработал достаточно хорошо, и я не стал задавать его снова, и это факт. приведенный выше код без каких-либо изменений. Надеюсь, не отвлекаясь здесь слишком сильно, я поделюсь подсказкой, которую я использовал, чтобы получить именно то, что я хотел в первый раз, потому что я также очень заинтересован в том, чтобы научиться использовать LLM (честно говоря, просто Chat GPT 3.5). , 4 и Bing AI) ну не оптимально, но хорошо. Подсказка, которую я использовал, следующая:

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

› data_subset ‹- readr::read_csv («Выбор LASSO через glmnet для DS от '0–3–1–1 до 0–4–10–500'.csv», col_names = TRUE) Строки: 10000 Столбцы: 5 ─ ─ Спецификация столбца ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ . ──────────── Разделитель: «», chr (5): DS_name, Variables.Selected.by.glmnet, Structural_Variables, Variables…

ℹ Используйте `spec()`, чтобы получить полную спецификацию столбца для этих данных. ℹ Укажите типы столбцов или установите `show_col_types = FALSE`, чтобы скрыть это сообщение. › View(data_subset) › str(data_subset) spc_tbl_ [10 000 × 5] (S3: spec_tbl_df/tbl_df/tbl/data.frame) $ DS_name : chr [1:10000] «0–3–1–1» «0– 3–1–2» «0–3–1–3» «0–3–1–4» … $ Variables.Selected.by.glmnet : chr [1:10000] «X8, X10, X23» «X12, X18, X23» «X8, X11, X13, X16» «X17, X19, X24» …
$ Structural_Variables : chr [1:10000] «X8, X10, X23» «X12, X18, X23» «X11 , X13, X16» «X17, X19, X24» …
$ Variables.Not.Selected.by.glmnet: chr [1:10000] «X1, X2, X3, X4, X5, X6, X7, X9 , Х11, Х12, Х13, Х14, Х15, Х16, Х17, Х18, Х19, Х20, Х21, Х22, Х24, Х25, Х26, Х27, Х28, Х29, Х30» «Х1, Х2, Х3, Х4, Х5, Х6, Х7, Х8, Х9, Х10, Х11, Х13, Х14, Х15, Х16, Х17, Х19, Х20, Х21, Х22, Х24, Х25, Х26, Х27, Х28, Х29, Х30» «Х1, Х2, Х3 , X4, X5, X6, X7, X9, X10, X12, X14, X15, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30» «X1, Х2, Х3, Х4, Х5, Х6, Х7, Х8, Х9, Х10, Х11, Х12, Х13, Х14, Х15, Х16, Х18, Х20, Х21, Х22, Х23, Х25, Х26, Х27, Х28, Х29, X30» …
$ Nonstructural_Variables : chr [1:10000] «X1, X2, X3, X4, X5, X6, X7, X9, X11, X12, X13, X14, X15, X16, X17, X18, X19 , X20, X21, X22, X24, X25, X26, X27, X28, X29, X30» «X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X13, X14, X15, Х16, Х17, Х19, Х20, Х21, Х22, Х24, Х25, Х26, Х27, Х28, Х29, Х30» «Х1, Х2, Х3, Х4, Х5, Х6, Х7, Х8, Х9, Х10, Х12, Х14 , X15, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30» «X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X18, X20, X21, X22, X23, X25, X26, X27, X28, X29, X30» …
— attr(*, «спецификация») =
.. cols(
.. DS_name = col_character(),
.. Variables.Selected.by.glmnet = col_character(),
.. Structural_Variables = col_character() ,
.. Variables.Not.Selected.by.glmnet = col_character(),
.. Неструктурные_переменные = col_character()
.. ) — attr(*, «проблемы»)=‹ внешнийptr›

Я действительно думал, что после этого все будет гладко, потому что все, что мне нужно было сделать, это импортировать эти наборы переменных из CSV-файлов правильного размера обратно в RStudio, а затем скопировать + вставить код, который я уже написал, чтобы вычислить все показатели производительности модели классификации ранее, но я подумал неправильно! Продолжая использовать LASSO через glmnet, то есть в качестве примера 1-го теста, я попытался просто добавить этот небольшой фрагмент кода в начало пустого скрипта:

data_subset <- readr::read_csv("subset_1.csv", col_names = TRUE)
Structural_Variables <- data_subset$Structural_Variables
class(Structural_Variables)
Variables.Selected.by.glmnet <- data_subset$Variables.Selected.by.glmnet
Nonstructural_Variables <- data_subset$Nonstructural_Variables
Variables.Not.Selected.by.glmnet <- data_subset$Variables.Not.Selected.by.glmnet

Затем просто скопируйте и вставьте код из раздела расчета показателей производительности моего сценария «cv.glmnet LASSO с s = «lambda.lse» (только регрессии).R», и он действительно запустился, когда я нажал Ctrl+Alt. +R после этого, но итоговые агрегированные показатели для всех 500 не имели смысла. Некоторые из них были больше 1, а другие были NaN. Это означает, что где-то в процессе импорта наборов переменных обратно в R из файлов csv, в которые я их распечатал с помощью read_csv, произошло некоторое изменение в форматировании одного из четырех списков наборов переменных по сравнению с тем, когда они были был только что создан во время того же сеанса путем запуска LASSO.

Поэтому я попросил Chat GPT, и он согласился, использовать случай кода, который подсчитывает количество истинных положительных результатов, выбранных для каждого набора данных, и сохраняет их в списке под названием BM1_TPs, а именно:

BM1_TPs <- lapply(seq_along(Structural_Variables), \(i) {
  sum(Variables.Selected.by.glmnet[[i]] %in% Structural_Variables[[i]])
})

GPT 4 сказал:

Проблема может возникнуть, если переменные в столбце «Variables.Selected.by.glmnet» и столбце «Structural_Variables» не отформатированы одинаково или если имеются начальные/конечные пробелы или другие символы, препятствующие точному совпадению. Например, если в элементах этих столбцов есть пробелы, сравнение с использованием %in% может дать неправильные результаты.

Далее он рекомендовал мне попробовать использовать функцию trimws() для решения этой проблемы следующим образом, чтобы удалить любые начальные/конечные пробелы или нежелательные символы:

BM1_TPs <- lapply(seq_along(Structural_Variables), function(i) {
  selected_vars <- trimws(strsplit(Variables.Selected.by.glmnet[[i]], ",")[[1]])
  structural_vars <- trimws(strsplit(Structural_Variables[[i]], ",")[[1]])
  sum(selected_vars %in% structural_vars)
})

Это предложение действительно устранило проблему, так что агрегированные показатели производительности для каждого подмножества наборов данных из 500 теперь снова были действительными и надежными, что я смог проверить несколькими способами, но самым простым было просто сложить и/или усреднить (в зависимости от того, какой метрика производительности) их всех для 10, 20 или 30 подмножеств, полученных из каждого из 5 000, 10 000 или 15 000 подмножеств, и сравнивают эти повторно агрегированные показатели производительности первого с показателями второго, откуда они пришли. И мне пришлось сделать это всего 260 000/500 = 520 раз для каждого из трех алгоритмов выбора эталонной переменной… Это заняло у меня некоторое время.