Ответ 1
Это тривиальная функция для написания себя:
norm_vec <- function(x) sqrt(sum(x^2))
Я пробовал 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?
Это тривиальная функция для написания себя:
norm_vec <- function(x) sqrt(sum(x^2))
norm(c(1,1), type="2") # 1.414214
norm(c(1, 1, 1), type="2") # 1.732051
Я был удивлен, что никто не пытался профилировать результаты для предложенных выше методов, поэтому я сделал это. Я использовал случайную равномерную функцию для генерации списка и использовал ее для повторения (просто простая задняя часть эталонного теста типа 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 вручную выполняется быстрее, чем встроенная норма для векторов действительных значений для небольших чисел.
Как маленький? Так что сумма квадратов не переполняется.
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")
- это ответ.
Мы также можем найти норму как:
Result<-sum(abs(x)^2)^(1/2)
ИЛИ Даже вы также можете попробовать:
Result<-sqrt(t(x)%*%x)
Оба получат тот же ответ
Я тоже выброшу это как эквивалентное выражение R
norm_vec(x) <- function(x){sqrt(crossprod(x))}
Не путайте R crossprod с аналогичным именем vector/cross product. Известно, что это название вызывает беспорядок особенно для тех, у кого есть физика/механика.
Если у вас есть 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
Создайте свою матрицу в качестве тика столбца с помощью cbind, тогда нормальная функция хорошо работает с нормой Фробениуса (евклидовой нормой) в качестве аргумента.
х1 < -cbind (1: 3)
норма (x1, "е" )
[1] 3.741657
SQRT (1 * 1 + 2 * 2 + 3 * 3)
[1] 3.741657
После ответа 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 ко всем числам и суммирует, что у меня нет времени на реализацию!