ぐぐると「オートコンプリートOFF」で対応できるという話が出てくるけど、
オプションの詳細設定にある「マルチスレッド」をOFFにする事でも効果があるようです。
ただし、マルチスレッドの設定は「計算」のマルチスレッドと「全般」のマルチスレッドの2つがあるので要注意。多分「全般」のほうが効いてくるけれども。念のため両方OFFのほうが安心かも?
マルチスレッドは、複数のCPUを使って高速化する機能なので、
処理速度がちょっと落ちるけれども、機能面では全く差はないです。
ぐぐると「オートコンプリートOFF」で対応できるという話が出てくるけど、
オプションの詳細設定にある「マルチスレッド」をOFFにする事でも効果があるようです。
ただし、マルチスレッドの設定は「計算」のマルチスレッドと「全般」のマルチスレッドの2つがあるので要注意。多分「全般」のほうが効いてくるけれども。念のため両方OFFのほうが安心かも?
マルチスレッドは、複数のCPUを使って高速化する機能なので、
処理速度がちょっと落ちるけれども、機能面では全く差はないです。
ガウス関数(exp(-x^2))の最小二乗フィッティングの際に、「対数取ってから2次関数近似すればよい」とか嘘だから。
ノイズというのも貴重な情報です。ノイズの分布を考慮せずに空間を安易に変換してはいけません。最小二乗法ではノイズの分布が時刻によって変動しない事を前提としています。
例えば有る時間で信号が1でノイズ幅が1だったとします。べつの時刻で信号が100でノイズ幅が1だとします。これは最小二乗法でフィッティングしてOKです。
ここで対数を取るとざっくりlog(2)-log(1)=0.69とlog(101)-log(100)=0.0099となって小さい信号の上にのったノイズにひっぱられて、大きな信号の上のノイズを見逃します。
同様に、多くの場合で最尤推定!=最小二乗です。
あーーー、すっきりした。
ということでガウス関数の最小二乗をやろうと思ってググってたんですが、なんか良いサンプルが見つからないんですね。で、頑張って自分で微分して、解を求めようとしたんですが、どーも計算できない。(微分・積分苦手)
最尤推定のときは解析解が求まるけど、最小二乗だと解析解がもとまらないのかな?という事で普通はニュートン法に逃げる訳だけれども、微分式を見るとなんか既視感。
g(t)をガウスモデル関数とする(なお、Σ時間tでの積算)
振幅aで微分: Σa*g(t)*g(t) =Σg(t)*i(t)
平均uで微分: Σa*g(t)*g(t)*t =Σg(t)*i(t)*t
標準偏差sで微分:Σa*g(t)*g(t)*t*t =Σg(t)*i(t)*t*t
モーメントの形に成っちゃってるけれども、ざっくりと言うと。
入力信号にモデル関数を掛けた平均値が、
モデル関数にモデル関数をかけたものの平均値になるようにパラメータを決めなさい。
ってこったね。
ん?ここではガウス窓で見てるけれども、矩形窓だと考えて平均値のみを考えるとミーンシフトそのものだよね?
1.適当な矩形範囲で重心を求める
2.上で求めた重心を中心にした矩形範囲で重心を求め直す
3.落ち着くまで2を繰り返す
ということで、ミーンシフトとして解釈して実装してみた。ただし、全体を最小二乗マッチングする必要あるので窓範囲=入力信号範囲。そのため、窓関数の重心が中心にくるとは限らない状況。
なんでモデルの重心も意識しながらコーディングする必要があるのがオリジナルのミーンシフトと違うという解釈。
結局は原始的な山登り法なんじゃね?という疑惑がふつふつと自分の中でわき上がるけれども、今後非対称重みのミーンシフトを実装する自信がついたのでよしとする。
以下rubyのサンプルコード(標準偏差もうごいてるけど真面目に考えてない)
#!/usr/bin/ruby
# -*- coding: utf-8 -*-
include Math
#テスト用入力信号
input=Array.new
100.times do |i|
signal = exp(-((i.to_f-75)/30.0)**2/2.0)*4.0;
signal += 0.1 * rand #-0.5;
input.push(signal)
end
#ガウス関数
##t=time u= center s=stddev
def gauss(t,u,s)
return exp(-((t-u)/s)**2/2)
end
#初期値を適当に設定(対数とって最小二乗でもいいよ)
m0=0.0
m1=0.0
m2=0.0
input.size.times do |t|
m0+=input[t]
m1+=input[t] * t
m2+=input[t] * t**2
end
u= m1/m0;
s= sqrt(m2/m0 - u**2);
#振幅を求める
def detectA(input,u,s)
gg=0.0
gi=0.0
input.size.times do |t|
g=gauss(t,u,s);
gg += g**2;
gi += g*input[t]
end
return gi/gg;
end
#平均と標準偏差更新(ついでに振幅)
def detectUS(input,a,u,s)
mg0=mg1=mg2=mi0=mi1=mi2=0.0
input.size.times do |t|
g=a*gauss(t,u,s);
gi=g * input[t]
gg= g* g
mi0+=gi
mi1+=gi * t
mi2+=gi * t**2
mg0+=gg
mg1+=gg * t
mg2+=gg * t**2
end
ui=mi1/mi0 #実際の重心候補
ug=mg1/mg0 #理論上の重心 (データ打ち切りの影響で中心!=重心)
vi=mi2/mi0 - ui**2 #実際の分散候補
vg=mg2/mg0 - ug**2 #理論上の分散
a=detectA(input,u,s)
return [a,u+ui-ug,sqrt(s**2 + vi-vg) ]
end
a=detectA(input,u,s)
#更新処理
100.times do |i|
d=detectUS(input,a,u,s)
a=d[0]
u=d[1]
s=d[2]
puts "#{a}\t#{u}\t#{s}";
end
#結果出力
open("o","w")do |f|
input.size.times do |t|
f.puts "#{input[t]}\t#{ a * gauss(t,u,s)}"
end
end
理想的な計測装置はノイズのない回路と、無限段階のADコンバータだけれども、現実にはADコンバータは有限段階です(例えば256段階とか)。
Q:ノイズはゼロが望ましいんでしょうか?
A:違います。
測定対象の信号の変動具合と、ADコンバータのサンプリングレート・分解能によって最適なノイズ量ってのがあります。例えば、測定対象が時間によって変動しないと見なせる場合で。かつ、測定値がADコンバータの換算値で0.5の場合。ノイズなしでは測定値は0です。ここでノイズが乗っている場合測定値のヒストグラムは0.5を中心とした正規分布になります。
ヒストグラムの幅がある程度あるほうが、正確に中心が求まるのである程度ノイズが大きい方が嬉しいですが。算出される計算結果には ノイズ幅xsqrt(測定回数)の誤差が含まれます。
そんな感じでノイズを活用すると、計測時間と精度をトレードオフではあるけれども、性能向上ができるんですね。なんで、ノイズを0と見なした信号処理はもったいない上に、上の対数変換で説明したあような誤りを誘う邪教なんです。
知りたい領域を選んで「エフェクト→増幅」で表示されるデシベルが現在クリップなしで増幅可能なデシベル数。
なんで4.2とか書いてあったらその領域の最大dBは-4.2
知らないと「解析」とか探して。なんでこんな基本機能ないんだ?って焦るよね。
用途「 遠隔地のFreeBSDマシンが HDD障害などで起動しなくなった時に、USBメモリから起動して、遠隔からSSHで入る」
USB起動ディスクを作るのは前回示した通り。
あとは、 なんのNICが刺さってるかわからないマシンで、いわゆる「BBルータ」の後ろにいるマシンに繋ぎたい。
結論から書くとこれをrc.localにつっこむ
ifconfig -l | tr " " "\n"|grep -v lo0 |xargs -n 1 dhclient
ifconfig |grep "inet 192"|awk '{print $2}' |sort |uniq |cat -n|awk '{print "/usr/local/bin/upnpc -a "$2" 22 8"$1"22 tcp"}' | sh
miniupnpcがインストールしてあることが前提なので注意。
これで適当に、 8122 ,8222,8322番のポートにSSHが公開されるようになるはず。
やっていることは、1行目で、 NICの一覧を取得してそれぞれにDHCPクライアントを実行しています。
2行目は、192.から始まるアドレスの22(SSH)ポートをUPnP を使ってルータの外に公開しています。
現実的な運用としては更に、自分のサイトにpingを打ち続けるなどの対処をしておいてIPアドレスを自分の端末から調べられるようにしておいたほうが無難ですね。
以下を参考にちょっとしたノウハウの追加
http://d.hatena.ne.jp/konbunori/20110328/1301250660
NAT設定の説明は-eオプションで足せます
upnpc -u ${ROOT_RUL} -e "my main server ssh " -a 192.168.1.3 22 8022
ルータを探すのに2秒ほど待つので遅いです。
upnpc -l
とやってdesc:で始まる行がルータのURLなのでソレをメモしておけば高速に実行できます。
シェルスクリプトなんかではこんな風にするといいんじゃないでしょうか?
ROOT_URL=`upnpc -l | grep "desc:" | head -n 1 | sed -E 's/ +desc: +//'`
upnpc -u ${ROOT_URL} -e "my main server ssh " -a 192.168.1.3 22 8022
同じ設定を何度やっても特段弊害はなさそうです(試したルータはPR-400KI)。
なんで単純にこんなスクリプトをcronで回しまくれば大丈夫です(多分)
#!/bin/sh
ROOT_URL=`upnpc -l | grep "desc:" | head -n 1 | sed -E 's/ +desc: +//'`
upnpc -u ${ROOT_URL} -e "my main server ssh " -a 192.168.1.3 22 8022 tcp >/dev/null
upnpc -u ${ROOT_URL} -e "my main server ssh " -a 192.168.1.3 22 8023 tcp >/dev/null
多くのFreeBSD使いは、実家だとか知り合いのマシンのリモートメンテしてたりする事が多いかと思うんです。そんなとき「ルータの設定飛んじゃった」とか困りますよね。
ルータ故障に関しては、インターネットが繋がるって所までは電話屋呼びつけて修理させればOK。ただ、田舎のNTT系列会社にNATが理解できるとは思えない。最近はUPnPデフォルトONみたいなんで、これで設定しとけばとりあえず安心だよね~という事で。。。
変なソフトに先に取られちゃうリスクはあるので、静的に設定しとくのも大切っちゃ大切なんですが。
ドライブがgeneric-mmc-rawドライバに対応していれば問題ないけど、
generic-mmcを使う場合はデフォルトではCD-TEXT(曲タイトル等)を無視する。
ドライバのオプションとして0x50を指定するのが吉。
gcdmasterでは0x00と書いてある欄を0x50に書き換え、コマンドラインなら「--driver generic-mmc:0x50」と指定