(Library) EOF with SSL2
EOFを計算します。 利用には ruby-ssl2 が必要です。
val,vec = Analysis.eof(x)
のように使います(val: 固有値、vec: 固有ベクトル)。
オプションで、
- 第2引数: 欠損値の設定
- 第3引数: 必要な主要モードの数
を指定できます。
ダウンロードはこちら -> eof_ssl2.rb
ソースを載せてみたら, と言うことで載せてみました.
require "narray"
require "numru/ssl2"
module Analysis
def covariance( x,y,rmiss=nil )
if x.length != y.length then
print "error\n"
exi
end
len = x.length
if rmiss.nil? then
sum = x.mul_add(y,0)
n = len
else
mask = x.ne(rmiss) & y.ne(rmiss)
sum = x.mask(mask).mul_add(y.mask(mask),0)
n = mask.count_true
end
if n>len/2 then
sum/(n-1)
else
rmiss
end
end
def covariance_matrix( x, rmiss=nil, lmean=false, ltotal=false)
if x.rank !=2
raise "covariance_matrix: x.rank must be 2"
end
dim, len = x.shape
rmiss = nil if !rmiss.nil? && x.ne(rmiss).all?
if lmean
if rmiss.nil?
x = x - x.mean(1)
else
for i in 0...dim
mask = x[i,true].ne(rmiss)
tmp = x[i,true].mask(mask)
if tmp.length >= len/2 then
x[i,mask] = tmp - tmp.mean
else
x[i,true] = rmiss
end
end
end
end
cov = NArray.new(x.typecode,dim*(dim+1)/2)
sind = 0
total = 0
if rmiss.nil?
for i in 0...dim
cov[sind..sind+i] = x[0..i,true].mul_add(x[i,true].reshape!(1,len),1)/(len-1)
total += cov[sind+i]
sind += i+1
end
else
for i in 0...dim
for j in 0...i
cov[sind] = covariance(x[i,true],x[j,true],rmiss)
sind += 1
end
cov[sind] = x[i,true].mask(x[i,true].ne(rmiss)).stddev**2
total += cov[sind]
sind += 1
end
end
if ltotal
return [cov,total]
else
return cov
end
end
def eof( x, rmiss=nil, ndim=nil )
if x.shape.length!=2 then
print "err\n"
exit
end
dim,nle = x.shape
rmiss = nil if !rmiss.nil? && x.ne(rmiss).all?
p "calc anomary"
if rmiss.nil? then
x = x - x.mean(1)
else
ary = NArray.byte(dim)
for i in 0..dim-1
mask = x[i,true].ne(rmiss)
tmp = x[i,true]
tmp2 = tmp.mask(mask)
if tmp2.length >= nle*3/4 then
tmp[mask] = tmp2 - tmp2.mean
x[i,true] = tmp
ary[i] = 1
else
ary[i] = 0
end
end
if !ary.all? then
tdim = ary.where.length
y = NArray.sfloat(tdim,nle)
k=0
for i in 0..dim-1
if ary[i]==1 then
y[k,true] = x[i,true]
k+=1
end
end
if k!=tdim then
p "BUG: eof of eof_ssl2 k!=tdim"
exit
end
x = y
tmp = dim
dim = tdim
tdim = tmp
end
end
p "make covariance matrix"
cova, total = covariance_matrix(x,rmiss,false,true)
p "calc eigen value"
if ndim.nil? then
ndim=dim
end
val, vec = SSL2.seig2(cova,ndim)
if !rmiss.nil? && !ary.all? then
vec2 = NArray.sfloat(tdim,val.length)
k=0
for i in 0..tdim-1
if ary[i]==1 then
vec2[i,true] = vec[k,true]
k+=1
else
vec2[i,true] = rmiss
end
end
if k!=dim then
p "BUG: eof of eof_ssl2 k!=dim"
exit
end
vec = vec2
end
[val/total,vec]
end
module_function :eof, :covariance_matrix, :covariance
end
編集者 西澤, 佐々木
キーワード:
参照: