とある事情で,文字認識実験をしていました.その実験は,平仮名46文字を認識するというもので,認識手法の中に重み付きユークリッド距離というものがありました.重み付きユークリッド距離とは,
D(x, u) = √(∑(x[i]-u[i])^2/v[i])
x : 未知の文字の特徴ベクトル
u : ある字種の平均特徴ベクトル
v : uの分散ベクトル
というもので,適当にJavaで組んであるものを動かしていました.ところが,ある文字に対しては,非常に良い認識率が得られるが,ある文字は全く認識できない(認識率0%),という事態になってしまいました.
ファイルの読み込みや,計算式を入念にチェックしましたが,原因が見つかりませんでした.
よくよく考え,D(x, u)を出力してみました.
結果
NaN
ここでやっと原因が分かりました.単に0.0f/0.0fという演算が発生していたというだけのことです(上の式の場合x[i]-u[i]=0.0fかつ,v[i]=0.0fとなっていた).
そんなわけで,この問題は解決しましたが,浮動小数点における特殊な数について少しばかり調べてみました.上の実験では,Java,float型を使用してましたので,それに限りますが.
ちなみに,JDKのバージョンは1.6.0_06です.
Float.POSITIVE_INFINITY
正の無限大です.Floatクラスでの定義は,
public static final float POSITIVE_INFINITY = 1.0f / 0.0f;
でした.
Float.NEGATIVE_INFINITY
正の無限大です.Floatクラスでの定義は,
public static final float NEGATIVE_INFINITY = -1.0f / 0.0f;
でした.
Float.NaN
Not a Number(=非数)です.Floatクラスでの定義は,
public static final float NaN = 0.0f / 0.0f;
NaNの発生条件には以下のようなものがあります.
異符号の無限大同士の加算
同符号の無限大同士の減算
0と無限大の乗算
0同士の除算
無限大同士の除算
被除数が無限大の剰余
除数が0の剰余
負数の平方根
値が未定義となる逆三角関数,対数関数
また,この定数は特殊であり,
NaN op something (op -> "==", "<", ">", "<=", ">=")
は必ずfalseであり,
NaN != something
は必ずtrueとなります.
実際,あるfloat値がNaNかどうかを返すメソッドboolean isNaN(float)は以下のように定義されていました.
static public boolean isNaN(float v) {
return (v != v);
}
vがNaNの時にだけ,v != vはtrueとなります.
今日はこんなところで.
0 件のコメント:
コメントを投稿