Векторизация цикла for для одновременного обновления вектора

avatar
Liondancer
8 апреля 2018 в 05:55
77
1
0

Как можно векторизовать этот фрагмент кода для одновременного обновления theta?

for (j in 1:length(theta)) {
  val = exp(y * sum(theta * random_data_vector)) * y * random_data_vector[j]
  val = val / (1 + exp(y * sum(theta * random_data_vector)))
  theta[j] = theta[j] - (alpha * val)
}

theta — вектор, random_data_vector — вектор, y — число

> dput(head(theta))
c(0.772925310069695, 0.853900654707104, 0.291106897871941, 0.114210048923269, 
0.257764941081405, 0.0881731726694852)
> dput(head(random_data_vector))
c(0, 0, 0, 0, 0, 0)
Источник
F. Privé
8 апреля 2018 в 07:03
0

Не уверен, что вы можете так векторизовать, так как итерации зависят от предыдущих. Вы в порядке, используя Rcpp? Предоставьте несколько примеров данных для random_data_vector, theta, alpha и y.

Liondancer
8 апреля 2018 в 07:10
0

@ F.Privé, не могли бы вы рассказать, почему я не могу векторизовать? Все является действительным числовым вектором, за исключением y и alpha, которые также являются действительными числами. Мой код, кажется, работает, но я могу пропустить вариант использования

F. Privé
8 апреля 2018 в 07:13
0

Когда вы вычисляете sum(theta * random_data_vector), вы используете theta из предыдущей итерации, что не позволяет вам просто векторизовать свой код.

Liondancer
8 апреля 2018 в 07:18
0

@ F.Privé немного сбит с толку. Я изменяю theta только в последней строке, предложенной r2evans. Разве theta не остается прежним в других строках?

r2evans
8 апреля 2018 в 07:20
0

@F.Privé, theta никогда не ссылается на [j-1], поэтому значение theta после этого цикла такое же, как и раньше, но оно не зависит (например) от значения theta[j-1]. Но я вижу твою точку зрения...

r2evans
8 апреля 2018 в 07:21
0

Liondancer, я предлагаю вам использовать dput(head(...)) вместо просто head(...), это значительно упрощает нам использование.

Liondancer
8 апреля 2018 в 07:23
0

@r2evans ГОТОВО. Спасибо!

r2evans
8 апреля 2018 в 07:29
0

Ах, кажется, я вижу проблему... theta находится внутри sum, поэтому в этот момент он не векторизован, а изменяется на основе предыдущего изменения на theta. @Liondancer, , вот почему вам нужны образцы данных и ожидаемый результат , аналогично тому, почему программистам часто требуются модульные тесты для кода.

r2evans
8 апреля 2018 в 07:35
0

@Liondancer, вы можете подтвердить предполагаемое поведение? Есть ли у вас «истинные» значения, чтобы знать, что ваш цикл правильный? (Я просто спрашиваю на всякий случай ...) Если вы это сделаете, и мой ответ правильный, то все в порядке, в противном случае я предлагаю вам «не принять» мой ответ ниже и найти/подтвердить данные проверки.

Liondancer
8 апреля 2018 в 07:37
1

@ r2evans Я проверил ваш ответ на нескольких очень простых примерах, и они вели себя так, как я хотел. У меня нет источника правды, но я думаю, что ты хорош! Спасибо!!

Ответы (1)

avatar
r2evans
8 апреля 2018 в 06:06
1

Не требуется цикл for или индексация, поскольку математические операции в R по умолчанию векторизованы, при условии, что все векторы имеют одинаковую длину или длину 1. (Например, 1:10 + 1 векторизован по умолчанию, циклы не требуются .)

val = exp(y * sum(theta * random_data_vector)) * y * random_data_vector
val = val / (1 + exp(y * sum(theta * random_data_vector)))
theta = theta - (alpha * val)
user9589138
8 апреля 2018 в 06:21
0

Не могли бы вы объяснить, почему здесь нет необходимости в цикле for?

r2evans
8 апреля 2018 в 06:23
0

По умолчанию он векторизован, при условии, что все переменные здесь имеют либо длину 1, либо ту же длину, что и другие переменные, отличные от длины 1. Точно так же 1:10 + 1 векторизован по умолчанию, нет необходимости в цикле for.

user9589138
8 апреля 2018 в 06:24
1

Идеально. Хорошо добавить его к вашему идеальному ответу, так как это будет очень полезно.

F. Privé
8 апреля 2018 в 06:57
1

Не уверен, что вы можете так векторизовать, так как итерации зависят от предыдущих.

r2evans
8 апреля 2018 в 07:00
0

Вы можете быть правы... хотя это зависит от данных. Если @Liondancer предоставит образцы, возможно, мы сможем проверить эту проблему.

F. Privé
8 апреля 2018 в 07:01
0

Попробуйте с random_data_vector <- rnorm(5); theta <- rep(0, 5); alpha <- 1; y <- 0.5.

Liondancer
8 апреля 2018 в 07:21
0

@r2evans предоставил некоторые образцы данных. Дайте мне знать, если я пропущу что-то еще

r2evans
8 апреля 2018 в 07:40
0

@ F.Privé, хорошая проверка, спасибо за контроль качества. Я предполагаю, что цикл Liondancer for может быть неправильной реализацией предполагаемого вычисления, если этот код подтвердится как правильный. Вы правы в том, что они не эквивалентны, больше поддерживая полезность (юнит-) тестов.

F. Privé
8 апреля 2018 в 08:48
0

@ r2evans Я думаю, что реализация OP может быть правильной. Похоже на координатный спуск.

r2evans
8 апреля 2018 в 14:31
0

Возможно. Если да, то (1) это нельзя делать параллельно, один из явных недостатков; (2) этот процесс продолжается до тех пор, пока он больше не будет сокращен, а не до определенного количества итераций, как здесь; и (3) для чего нужен случайный вектор? Я вижу там ссылку на постоянно дифференцируемый F(x). Хм.