2013年6月29日土曜日

VirtualBoxのBiosRomファイル



VirtualBoxはBiosを入れ替える機能を持ってるんだけれども、BIOSファイルのフォーマットってなんやねん。で止まってた。


結論から言うと、アドレス 0xf0000から始まる64KbyteがBIOSってことらしい。


なんでFreeBSDでBIOSを取得するには以下のコマンドをrootで実行すればいい。



dd if=/dev/mem bs=64k of=bios.bin iseek=15 count=1



基本的にはVirtualBox上でBIOSをダンプして、それを書き換えて起動できないBIOSを作って泣くのが主な使い方みたいだね。





LAN DISK HDL2-Aでリモートシャットダウン



CSRF対策でruby使わないと簡単にはリモートシャットダウンできないようになってるのね。ということで書きました。


urlとpassの行を適宜自分の環境に書き換えれば動くはずです。


ただしruby mechanizeを使っているのでFreeBSDな人はwww/rubygem-mechanize をあらかじめインストールしておいてください。






#!/usr/local/bin/ruby
# -*- coding: utf-8 -*-
####### 設定内容
url="http://10.0.0.1"
pass="your password"

####### 以下処理内容
require 'rubygems'
require 'mechanize'
agent=Mechanize.new
page=agent.get(url);
# ログイン
page.form_with(:name => 'form') { |f|
f.field_with(:type => 'password').value=pass}.submit
#シャットダウンページ取得
page=agent.get(url+"/system/detail/system/shutdown.php");
#デフォルトで再起動ではなく、シャットダウンに選択されてるはず、そのままsubmit
page=page.form_with(:name => 'form').submit
#確認画面(本当はjavascriptで確認画面処理してるので、飛ばして最後のシャットダウン実行
page=page.form_with(:name => 'form'){|f| f.default_event="shutdown" }.submit






2013年6月27日木曜日

GPTパーティションのUSBメモリをwindowsで使おうとしてはまる。。。。



MacやFreeBSDなどUSBメモリからのOS起動のときって旧来のMBR形式じゃなくて今風のGPTでディスクを初期化することになる。


それはそれでいいんだけど、問題は市販のNASだとかは特許のからみでイニシエのフォーマットであるFATフォーマットが必要とされている。


windowsのFATは実はGPTパーティションに対応していない。


なのでGPTをMBRに変更する必要があるんだけど、、、こんな方法普通に思いつくかよ!なんで管理ツールからいけへんねん。





http://www.atmarkit.co.jp/fwin2k/win2ktips/1378clngpt/clngpt.html





LAN DISK HDL2-Aでフォルダ間バックアップ



バックアップ用フォルダにどんどん上書き追記するという原始的なバックアップをとりたい場合あるよね。


そんな機能ないな~と思ったけれども、「ネットワークバックアップ」でバックアップ元のIPアドレスを127.0.0.1に設定できる事に気がつく。


それだけなんだけど、気がつかないと悩む事になる。





2013年6月25日火曜日

エクセル2013が落ちまくる時はマルチスレッドOFF



ぐぐると「オートコンプリートOFF」で対応できるという話が出てくるけど、


オプションの詳細設定にある「マルチスレッド」をOFFにする事でも効果があるようです。


ただし、マルチスレッドの設定は「計算」のマルチスレッドと「全般」のマルチスレッドの2つがあるので要注意。多分「全般」のほうが効いてくるけれども。念のため両方OFFのほうが安心かも?


マルチスレッドは、複数のCPUを使って高速化する機能なので、


処理速度がちょっと落ちるけれども、機能面では全く差はないです。





2013年6月14日金曜日

ガウス関数の最小二乗(最小自乗)フィッティング と ガウス窓ミーンシフト



最初に一言



ガウス関数(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と見なした信号処理はもったいない上に、上の対数変換で説明したあような誤りを誘う邪教なんです。





2013年6月12日水曜日

Audacityで現在の録音レベルを知りたいとき。



知りたい領域を選んで「エフェクト→増幅」で表示されるデシベルが現在クリップなしで増幅可能なデシベル数。


なんで4.2とか書いてあったらその領域の最大dBは-4.2


知らないと「解析」とか探して。なんでこんな基本機能ないんだ?って焦るよね。





2013年6月9日日曜日

FreeBSDで起動時に我武者羅に SSHを公開する。



用途「 遠隔地の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アドレスを自分の端末から調べられるようにしておいたほうが無難ですね。





2013年6月2日日曜日

FreeBSDからUPnP IGDのポートマッピングを設定する(with miniupnpc)



以下を参考にちょっとしたノウハウの追加


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みたいなんで、これで設定しとけばとりあえず安心だよね~という事で。。。


変なソフトに先に取られちゃうリスクはあるので、静的に設定しとくのも大切っちゃ大切なんですが。





メモ:cdrdao(gcdmaster)で音楽CDを焼くときのドライバの設定(CD-TEXT有効化)



ドライブがgeneric-mmc-rawドライバに対応していれば問題ないけど、


generic-mmcを使う場合はデフォルトではCD-TEXT(曲タイトル等)を無視する。


ドライバのオプションとして0x50を指定するのが吉。


gcdmasterでは0x00と書いてある欄を0x50に書き換え、コマンドラインなら「--driver generic-mmc:0x50」と指定