Crack Data Science Интервью
Статистическое моделирование в R с кодом - Часть 1
Интервью Ace Data Science
Это первая часть двойного сообщения о статистическом моделировании. Если у вас нет, ознакомьтесь со второй частью:
Вступление
За последние несколько месяцев я получил несколько собеседований по Data Science от ведущих технологических компаний. Почти все интервьюеры просили меня провести статистическое моделирование реального бизнес-сценария, на что я не произвел впечатления.
Знаете, это разумные вопросы, и на них не очень сложно ответить, если бы я уже сталкивался с этой темой раньше.
До сегодняшнего дня я потратил сотни часов на изучение симуляторов и подготовку к следующим техническим собеседованиям.
Статистическое моделирование - довольно обширная область, и невозможно охватить каждую деталь одним письмом. В качестве стартера я планирую изложить нюансы и приложения моделирования через последовательность сообщений.
Определение
В реальном мире все происходит случайно, и существует бесконечное количество возможностей. Мы можем наблюдать только часть, но не все возможности.
Моделирование очень удобно и предлагает быстрый обзор распределения возможностей, соответствующих реальным результатам. Изучая смоделированные результаты, мы получаем представление о реальном мире.
Генерация случайных чисел
Давайте начнем с самого простого кода и перейдем к более сложным сценариям.
Команда runif (x, min = a, max = b) генерирует x значений в диапазоне от a до b.
library(dplyr) set.seed(2) runif(25,min=0,max=10)
Функция set.seed () устанавливает начальное число для генератора случайных чисел R, чтобы мы получали одинаковые значения при каждом запуске кода. В противном случае мы получим другие результаты. Попробуйте сами.
Чтобы получить целые числа, мы используем функцию round следующим образом:
runif(25,min=0,max=10) %>% round(.,digits = 0)
Здесь канал % ›% происходит из пакета magrittr и позволяет писать более чистые и легко понятные код. На простой английский это слово можно перевести как «then».
На английском языке две приведенные выше строки кода означают:
- генерировать 25 чисел в диапазоне от 0 до 10
- затем (% ›%), округлите число до ближайшего целого.
Попробуйте, что произойдет, если вы настроите цифры = 1.
Другой способ создания случайного числа - с помощью функции sample:
> sample(x, size, replace=TRUE, prob=NULL)
- x: вектор или положительное целое число
- размер: неотрицательное целое число, дающее количество элементов на выбор
- replace: образец с заменой или нет?
- проблема: вектор вероятностных весов для получения элементов выбираемого вектора
(Пожалуйста, обратитесь к документации R для получения дополнительной информации, ссылка)
Быстрый пример.
set.seed(24) sample(seq(1,10),8)
Функция set.seed () делает результат воспроизводимым.
Приведенный выше код генерирует случайную выборку из 8 чисел из последовательности [1,10]. Как видите, мы не устанавливаем правила замены и вероятности выбора.
По умолчанию R устанавливает для замены значение FALSE и принимает равные вероятности выбора.
x = 1:10 sample(x,replace=TRUE)
Процесс передискретизации с заменой называется начальной загрузкой, более сложная тема, которая будет рассмотрена в следующей главе.
Помимо чисел, мы можем выбирать слова следующим образом:
set.seed(1) sample(letters,18)
Равная и неравная вероятность выбора
# Сценарий 1: равная вероятность
Мы генерируем случайную выборку размером 10 из последовательности [1,5] с равными вероятностями.
equal_prob_dist = sample(5,10000,prob=rep(0.1,5),replace=T) hist(equal_prob_dist)
Если мы установим prob = rep (0.1,5), то числа от 1 до 5 будут одинаковыми, как показано на гистограмме выше.
# Сценарий 2 Неравная вероятность
Как выглядит распределение, если вероятности выбора не равны (например, загруженная игральная кость)?
Мы генерируем случайную выборку размером 10 из последовательности [1,5] с неравными вероятностями.
unequal_prob_dist = sample(5,10000,prob =c(0.1,0.25,0.4,0.25,0.1), replace=T) hist(unequal_prob_dist)
Мы устанавливаем следующие правила вероятности выбора для последовательности:
1 & 5: 0.1 2 & 4: 0.25 3: 0.4
Оказывается, номер 3 выбирается чаще всего, а номер 1 и 5 выбирают меньше всего.
Эти равные / неравные сценарии могут быть чрезвычайно полезны, если интересующий вопрос требует дифференцированного подхода к вероятности выбора.
Примеры наблюдений из фрейма данных
Для выборки наблюдений (строк) из фрейма данных или списка мы выбираем не строки напрямую, а индексы в объект.
head(mtcars)
# step 1: create an index vector for the elements/rows index <- seq_len(nrow(mtcars)) # step 2: sample the index vector set.seed(12) #to obtain a random sample of 10 sample_index <- sample(index,10) # step 3: to show the sampled elements/rows mtcars[sample_index,]
Приложения
В этом разделе давайте немного попрактикуемся и решим реальные бизнес-сценарии.
Вопрос 1: Есть два шестигранных кубика. Если вы бросите их вместе, какова вероятность выпадения 7?
set.seed(1) die = 1:6 # sample 10000 times with replacements for dice 1 die1 = sample(die,10000,replace = TRUE,prob=NULL) # sample 10000 times with replacements for dice 2 die2= sample(die,10000,replace=TRUE,prob = NULL) # the combined value of die_1 and die_2 outcomes = die1+die2 # the probability of getting a 7 mean(outcomes == 7)
Точно так же мы можем использовать цикл for для той же цели.
set.seed(1) for (i in 10000){ die_1 = sample(die,prob=NULL,replace=TRUE) die_2 = sample(die,prob=NULL,replace=TRUE) die_sum = die_1+die_2 print(mean(die_sum==7)) }
Эти два результата почти одинаковы.
Вопрос 2: у вас есть два кубика. Какова вероятность выпадения 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 и 13?
Вместо моделирования каждого результата есть более простой способ получить то, что нам нужно, с помощью sapply.
sapply(2:13,function(x) mean(outcomes==x))
Согласно документации R, функция sapply
() является «удобной для пользователя версией и оболочкой lapply
, по умолчанию возвращающей вектор, матрицу или, если simplify = "array"
, массив, если необходимо, путем применения simplify2array()
. sapply(x, f, simplify = FALSE, USE.NAMES = FALSE)
то же самое, что и lapply(x, f)
».
Вкратце, функция применяет функцию mean (results) к последовательности [2,13].
Вопрос к вам: какова вероятность выпадения 7, если у вас 3 кубика?
Вопрос 3. Создайте случайную выборку из 10000 значений, и сколько уникальных наблюдений будет включено? Сколько не включено?
set.seed(1) n=10000 included_obs = length(unique(sample(1:n, replace = TRUE))) included_obs missing_obs = n-included_obs missing_obs
После выборки мы используем unique () для нахождения отличительных наблюдений и length () для подсчета. В выборке из 10 тыс. Выбираются 6316 уникальных случаев, а из 3684 (10 тыс. - 6316) - нет.
В качестве дальнейшего примечания, причина, по которой мы получаем только 6316 из 10k, заключается в том, что мы производим выборку с заменами, и поэтому некоторые числа выбираются повторно. Другими словами, некоторые числа отбираются несколько раз.
Вопрос 4. Создайте матрицу размера m * n со случайными значениями 0 и 1.
(кредиты дискуссиям на R-bloggers, здесь)
В исходном посте авторы представляют несколько методов, и здесь я сосредоточусь на первых подходах.
Во-первых, мы можем использовать цикл for.
m <- 10 n <- 10 # create an empty matrix m00 <- matrix(0,m,n) for (i in 1:m) { for (j in 1:n) { m00[i,j] <- sample(c(0,1),1) } } m00
Здесь matrix (0, m, n) создает пустую матрицу размером m * n, а два цикла for определяют значения каждой ячейки.
В большинстве случаев цикл for в R может быть не самым эффективным решением, и мы будем использовать другие варианты, если размер выборки достаточно велик.
Имея это в виду, авторы используют второй метод, используя функцию apply ().
m <-10 n<-10 m0 <- matrix(0,m,n) apply(m0,c(1,2),function(x) sample(c(0,1),1))
Пока все должно быть хорошо знакомо, кроме функции apply (). Он возвращает вектор / массив / список значений, полученных путем применения функции к полям массива или матрицы (исходное определение, ссылка).
Он имеет следующий вид:
> apply(x, margin, fun,…)
- x: массив или матрица
- margin: вектор, дающий индексы, в которых будет применяться функция. Для матрицы 1 обозначает строки, а 2 обозначает столбцы. c (1,2) указывает строки и столбцы, где x имеет именованные dimnames, это может быть вектор символов, выбирающий имена измерений
- веселье: функция, которую нужно применить
Вопрос 5: Подбросьте монетку 10 раз и смоделируйте процесс 10 000 раз. Покажите распределение количества появившихся голов.
# create an empty list total_heads = c() # use a for loop to simulate coin-flipping 10 times # repeat it for 10,000 times for (i in 1:10000){ sum_heads = sum(round(runif(10,0,1))) total_heads = c(total_heads, sum_heads) } hist(total_heads)
Здесь я объясню три строчки кода, а остальные не требуют пояснений.
- для (1 из 1: 1000). В отличие от других языков программирования, вы должны указать диапазон как 1: 10000.
- сумма (round (runif (10,0,1))). Это структурированный способ кодирования, который имеет три отдельные функции: runif () → round () → sum (). Сначала он запускает функцию runif (), а в последнюю - sum (). По сути, строки кода генерируют 10 случайных чисел от 0 до 1, округляют их до ближайшего целого числа (0 или 1) и, наконец, суммируют.
- total_heads = c (total_heads, sum_heads). Поскольку вначале total_heads является пустым списком, мы используем строку кода для присвоения значения sum_heads total_heads.
Спасибо за чтение!
Это вводная статья о статистическом моделировании, и мы рассмотрим более сложные темы в следующих публикациях.
Будьте на связи!
Medium недавно разработал свою Партнерскую программу писателей, которая поддерживает обычных писателей, таких как я. Если вы еще не являетесь подписчиком и зарегистрируетесь по следующей ссылке, я получу часть членских взносов.
Нравится читать это?
Также ознакомьтесь с другими моими сообщениями об искусственном интеллекте и машинном обучении.