Подтвердить что ты не робот

Как вычислить евклидову норму вектора в R?

Я пробовал norm, но я думаю, что он дает неверный результат. (норма c(1, 2, 3) равна sqrt(1*1+2*2+3*3), но возвращает 6..

x1 <- 1:3
norm(x1)
# Error in norm(x1) : 'A' must be a numeric matrix
norm(as.matrix(x1))
# [1] 6
as.matrix(x1)
#      [,1]
# [1,]    1
# [2,]    2
# [3,]    3
norm(as.matrix(x1))
# [1] 6

Кто-нибудь знает, что функция для вычисления нормы вектора в R?

4b9b3361

Ответ 1

Это тривиальная функция для написания себя:

norm_vec <- function(x) sqrt(sum(x^2))

Ответ 2

norm(c(1,1), type="2")     # 1.414214
norm(c(1, 1, 1), type="2")  # 1.732051

Ответ 3

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

> uut <- lapply(1:100000, function(x) {runif(1000, min=-10^10, max=10^10)})
> norm_vec <- function(x) sqrt(sum(x^2))
> norm_vec2 <- function(x){sqrt(crossprod(x))}
> 
> system.time(lapply(uut, norm_vec))
   user  system elapsed 
   0.58    0.00    0.58 
> system.time(lapply(uut, norm_vec2))
   user  system elapsed 
   0.35    0.00    0.34 
> system.time(lapply(uut, norm, type="2"))
   user  system elapsed 
   6.75    0.00    6.78 
> system.time(lapply(lapply(uut, as.matrix), norm))
   user  system elapsed 
   2.70    0.00    2.73 

Похоже, что взятие питания, а затем sqrt вручную выполняется быстрее, чем встроенный norm для векторов реальных значений, по крайней мере. Вероятно, это связано с тем, что внутренне норма делает SVD:

> norm
function (x, type = c("O", "I", "F", "M", "2")) 
{
    if (identical("2", type)) {
        svd(x, nu = 0L, nv = 0L)$d[1L]
    }
    else .Internal(La_dlange(x, type))
}

и функция SVD внутренне преобразует вектор в матрицу и выполняет более сложные операции:

> svd
function (x, nu = min(n, p), nv = min(n, p), LINPACK = FALSE) 
{
    x <- as.matrix(x)
    ...

ОБНОВЛЕНИЕ (20 октября 2019 г.):

Там были некоторые комментарии, чтобы указать на проблему правильности, которую вышеупомянутый контрольный пример не выявил:

> norm_vec(c(10^155))
[1] Inf
> norm(c(10^155), type="2")
[1] 1e+155

Это происходит потому, что большие числа считаются бесконечностью в R:

> 10^309
[1] Inf

Итак, это выглядит так:

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

Как маленький? Так что сумма квадратов не переполняется.

Ответ 4

norm(x, type = c("O", "I", "F", "M", "2"))

По умолчанию используется "O".

"O", "O" или "1" указывает одну норму (максимальную абсолютную сумму столбца);

"F" или "f" задает норму Фробениуса (евклидова норма x рассматривается так, как если бы она была вектором);

norm(as.matrix(x1),"o")

Результат равен 6, так же как norm(as.matrix(x1))

norm(as.matrix(x1),"f")

Результат sqrt(1*1+2*2+3*3)

Итак, norm(as.matrix(x1),"f") - это ответ.

Ответ 5

Мы также можем найти норму как:

Result<-sum(abs(x)^2)^(1/2)

ИЛИ Даже вы также можете попробовать:

Result<-sqrt(t(x)%*%x)

Оба получат тот же ответ

Ответ 7

Если у вас есть data.frame или data.table 'DT', и вы хотите вычислить евклидову норму (норма 2) для каждой строки, можно использовать функцию apply.

apply(X = DT, MARGIN = 1, FUN = norm, '2')

Пример:

>DT 

        accx       accy       accz
 1: 9.576807 -0.1629486 -0.2587167
 2: 9.576807 -0.1722938 -0.2681506
 3: 9.576807 -0.1634264 -0.2681506
 4: 9.576807 -0.1545590 -0.2681506
 5: 9.576807 -0.1621254 -0.2681506
 6: 9.576807 -0.1723825 -0.2682434
 7: 9.576807 -0.1723825 -0.2728810
 8: 9.576807 -0.1723825 -0.2775187

> apply(X = DT, MARGIN = 1, FUN = norm, '2')
 [1] 9.581687 9.582109 9.581954 9.581807 9.581932 9.582114 9.582245 9.582378

Ответ 8

Создайте свою матрицу в качестве тика столбца с помощью cbind, тогда нормальная функция хорошо работает с нормой Фробениуса (евклидовой нормой) в качестве аргумента.

х1 < -cbind (1: 3)

норма (x1, "е" )

[1] 3.741657

SQRT (1 * 1 + 2 * 2 + 3 * 3)

[1] 3.741657

Ответ 9

После ответа AbdealiJK,

Я экспериментировал дальше, чтобы получить некоторое представление.

Здесь один.

x = c(-8e+299, -6e+299, 5e+299, -8e+298, -5e+299)
sqrt(sum(x^2))
norm(x, type='2')

Первый результат - Inf, а второй - 1.227355e+300, что совершенно правильно, как я покажу вам в приведенном ниже коде.

library(Rmpfr)
y <- mpfr(x, 120)
sqrt(sum(y*y))    

Результат - 1227354879.... Я не посчитал количество конечных чисел, но все выглядит хорошо. Я знаю другой способ решения этой проблемы OVERFLOW, который сначала применяет функцию log ко всем числам и суммирует, что у меня нет времени на реализацию!