46

試し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のベクトルのノルムを計算する関数を知っている人はいますか?

4

10 に答える 10

75
norm(c(1,1), type="2")     # 1.414214
norm(c(1, 1, 1), type="2")  # 1.732051
于 2014-12-10T16:16:18.320 に答える
57

これは、自分で書くための簡単な関数です。

norm_vec <- function(x) sqrt(sum(x^2))
于 2012-06-07T14:43:27.350 に答える
25

上記の提案された方法の結果をプロファイリングしようとした人が誰もいないことに驚いたので、それを行いました。私はランダムな均一関数を使用してリストを生成し、それを繰り返しに使用しました(エンベロープタイプのベンチマークの単純な裏側):

> 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)
    ...

編集(2019年10月20日):

上記のテストケースでは明らかにならない正確性の問題を指摘するコメントがいくつかあります。

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

これは、Rで大きな数が無限大と見なされるために発生します。

> 10^309
[1] Inf

したがって、次のようになります。

パワーを取得してから手動でsqrtを取得する方が、小さい数の実数ベクトルの組み込みの標準よりも高速であるようです。

どれくらい小さいですか?二乗和がオーバーフローしないように。

于 2016-09-06T04:27:37.273 に答える
15
norm(x, type = c("O", "I", "F", "M", "2"))

デフォルトはです"O"

"O""o"または"1"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")答えです。

于 2014-06-12T19:12:17.423 に答える
4

また、次のように標準を見つけることができます:

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

または、次のように試すこともできます。

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

どちらも同じ答えになります

于 2013-02-15T09:32:38.700 に答える
3

私もこれを同等のR式として投げます

norm_vec(x) <- function(x){sqrt(crossprod(x))}

Rの外積を同様の名前のベクトル/外積と混同しないでください。その命名は、特に物理学/力学のバックグラウンドを持つ人々にとって混乱を引き起こすことが知られています。

于 2014-12-12T22:31:43.073 に答える
2

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
于 2016-08-16T04:58:12.857 に答える
2

破壊的なアンダーフローとオーバーフローを回避するためのスケーリングを使用したベクトルのユークリッド長(k-norm)に対する回答は次のとおりです。

norm <- function(x, k) { max(abs(x))*(sum((abs(x)/max(abs(x)))^k))^(1/k) }

説明については、以下を参照してください。

1.スケーリングなしのベクトルのユークリッド距離:


norm()ベクトルの長さを計算するベクトル値関数です。xクラスのベクトルとクラスmatrixのノルムkのタイプなど、2つの引数を取りますinteger

norm <- function(x, k) {
  # x = matrix with column vector and with dimensions mx1 or mxn
  # k = type of norm with integer from 1 to +Inf
  stopifnot(k >= 1) # check for the integer value of k greater than 0
  stopifnot(length(k) == 1) # check for length of k to be 1. The variable k is not vectorized.
  if(k == Inf) {
    # infinity norm
    return(apply(x, 2, function(vec) max(abs(vec)) ))
  } else {
    # k-norm
    return(apply(x, 2, function(vec) (sum((abs(vec))^k))^(1/k) ))
  }
}

x <- matrix(c(1,-2,3,-4)) # column matrix
sapply(c(1:4, Inf), function(k) norm(x = x, k = k))
# [1] 10.000000  5.477226  4.641589  4.337613  4.000000
  • 1ノルム(10.0)は無限ノルム(4.0)に収束します。
  • kノルムは、「ユークリッドn次元空間におけるユークリッドノルム」とも呼ばれます。

注:関数定義で はnorm()、実数成分を含むベクトルの場合、絶対値をnorm-2kまたはインデックス付きノルムにドロップできます。ここでk >= 1

norm関数の定義と混同している場合は、以下のようにそれぞれを個別に読むことができます。

norm_1 <- function(x) sum(abs(x))
norm_2 <- function(x) (sum((abs(x))^2))^(1/2)
norm_3 <- function(x) (sum((abs(x))^3))^(1/3)
norm_4 <- function(x) (sum((abs(x))^4))^(1/4)
norm_k <- function(x) (sum((abs(x))^k))^(1/k)
norm_inf <- max(abs(x))

2.破壊的なオーバーフローとアンダーフローの問題を回避するためのスケーリングを使用したベクトルのユークリッド距離:


注-2: このソリューションの唯一の問題は、ここここでnorm()ほのめかされているように、オーバーフローまたはアンダーフローの問題を防ぐことができないことです。

幸いなことに、誰かがすでにこの問題をblas(基本線形代数サブルーチン)fortranライブラリの2ノルム(ユークリッド長)で解決していました。この問題の説明は、「Kahaner、Moler、およびNashによる数値的方法とソフトウェア」の教科書-第1章、セクション1.3、ページ-7-9に記載されています。

fortranサブルーチンの名前は、です。これは、ベクトル成分の最大値でスケーリングすることによりdnrm2.f、破壊的なオーバーフローとアンダーフローの問題を処理します。norm()破壊的なオーバーフローとアンダーフローの問題は、norm()関数の根本的な操作が原因で発生します。

以下に実装方法を示しdnrm2.fますR

#1. find the maximum among components of vector-x
max_x <- max(x)
#2. scale or divide the components of vector by max_x
scaled_x <- x/max_x
#3. take square of the scaled vector-x
sq_scaled_x <- (scaled_x)^2
#4. sum the square of scaled vector-x
sum_sq_scaled_x <- sum(sq_scaled_x)
#5. take square root of sum_sq_scaled_x
rt_sum_sq_scaled_x  <- sqrt(sum_sq_scaled_x)
#6. multiply the maximum of vector x with rt_sum_sq_scaled_x
max_x*rt_sum_sq_scaled_x

dnrm2.f上記の6ステップのinのワンライナーは次のとおりRです。

# Euclidean length of vector - 2norm
max(x)*sqrt(sum((x/max(x))^2))

この問題の2ノルム(このスレッドの他の解決策を参照)を計算するためのベクトルの例を試してみましょう。

x = c(-8e+299, -6e+299, 5e+299, -8e+298, -5e+299)
max(x)*sqrt(sum((x/max(x))^2))
# [1] 1.227355e+300

x <- (c(1,-2,3,-4))
max(x)*sqrt(sum((x/max(x))^2))
# [1] 5.477226

したがって、Rでk-normの一般化されたソリューションを実装するための推奨される方法は、破壊的なオーバーフローまたはアンダーフローの問題を防ぐ単一のラインです。このワンライナーを改善するためnorm()に、小さすぎないまたは大きすぎないコンポーネントを含むベクトルのスケーリングなしと、小さすぎるknorm()または大きすぎるコンポーネントを含むベクトルのスケーリングの組み合わせを使用できます。すべてのベクトルにスケーリングを実装すると、計算が多すぎます。knorm()以下に示すように、この改善は実装しませんでした。

# one-liner for k-norm - generalized form for all norms including infinity-norm:
max(abs(x))*(sum((abs(x)/max(abs(x)))^k))^(1/k)

# knorm() function using the above one-liner.
knorm <- function(x, k) { 
  # x = matrix with column vector and with dimensions mx1 or mxn
  # k = type of norm with integer from 1 to +Inf
  stopifnot(k >= 1) # check for the integer value of k greater than 0
  stopifnot(length(k) == 1) # check for length of k to be 1. The variable k is not vectorized.
  # covert elements of matrix to its absolute values
  x <- abs(x)
  if(k == Inf) { # infinity-norm
    return(apply(x, 2, function(vec) max(vec)))
  } else { # k-norm
    return(apply(x, 2, function(vec) {
      max_vec <- max(vec)
      return(max_vec*(sum((vec/max_vec)^k))^(1/k))
    }))
  }
}

# 2-norm
x <- matrix(c(-8e+299, -6e+299, 5e+299, -8e+298, -5e+299))
sapply(2, function(k) knorm(x = x, k = k))
# [1] 1.227355e+300

# 1-norm, 2-norm, 3-norm, 4-norm, and infinity-norm
sapply(c(1:4, Inf), function(k) knorm(x = x, k = k))
# [1] 2.480000e+300 1.227355e+300 9.927854e+299 9.027789e+299 8.000000e+299

x <- matrix(c(1,-2,3,-4))
sapply(c(1:4, Inf), function(k) knorm(x = x, k = k))
# [1] 10.000000  5.477226  4.641589  4.337613  4.000000

x <- matrix(c(1,-2,3,-4, 0, -8e+299, -6e+299, 5e+299, -8e+298, -5e+299), nc = 2)
sapply(c(1:4, Inf), function(k) knorm(x = x, k = k))
#           [,1]          [,2]          [,3]          [,4]   [,5]
# [1,]  1.00e+01  5.477226e+00  4.641589e+00  4.337613e+00  4e+00
# [2,] 2.48e+300 1.227355e+300 9.927854e+299 9.027789e+299 8e+299
于 2020-09-06T11:49:36.023 に答える
1

AbdealiJKの答えに続いて、

私はいくつかの洞察を得るためにさらに実験しました。

これが1つです。

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

最初の結果はInfであり、2番目の結果は、1.227355e+300以下のコードで示すように非常に正しいものです。

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

結果は1227354879...です。末尾の数字は数えませんでしたが、大丈夫そうです。この問題を回避する別の方法があることを私は知っていOVERFLOWます。それは、最初にすべての数値に対数関数を適用して合計することですが、実装する時間がありません。

于 2018-06-14T21:15:14.937 に答える
0

cbindを使用して列バイスとして行列を作成すると、norm関数は引数としてFrobeniusノルム(ユークリッドノルム)とうまく機能します。

x1 <-cbind(1:3)

norm(x1、 "f")

[1] 3.741657

sqrt(1 * 1 + 2 * 2 + 3 * 3)

[1] 3.741657

于 2014-11-18T20:22:45.930 に答える