sonoshouのまじめなブログ

情報系大学生からのウェブ見習い人生の記録

自己組織化写像をprocessingで実装する。 part.3

さて、前回のエントリーで自己組織化写像のアルゴリズムを紹介しました。
復習の意味も込めて、再掲致します。

1.全重みベクトルをランダマイズする
2.入力ベクトルを一つ用意する
3.各ノードを検査して、最も一致値が小さいノードを見つける。(BMU)
4.BMUの近傍のノードの重みベクトルを変更し、入力ベクトルに近付ける。
5.最大繰り返し回数に達していなければ2.に戻る。
Wikipedia:自己組織化写像の算法のステップを一部改変~

前回のエントリーでは、1.全重みベクトルをランダマイズするの実装まで完了致しました。
今日も張り切って続きを実装していきましょう!

各ユニットのデータを保存する

と、その前に前回のエントリーまでで、全重みベクトルをランダマイズすることまでは完了していたのですが、その全重みベクトルを保存するプログラムを書いていませんでした……。
(ぶっつけ本番でプログラムを書いて行っているので、このように内容が前後することがあるかもです。未熟者で申し訳ございません><;)
というわけで、今日ははランダマイズした各ユニットのデータを保存するプログラムを書くところから始めていきましょう。

プログラムの全体像は以下のようになります。

void setup()
{
  size(780, 810);

  int randR, randG, randB;
  int tempR, tempG, tempB;
  int[][][] unitArray = new int[28][23][3];  // <- add

  //1. set random vectors
  for (int i = 0; i < 28; i++)
  {
    for (int j = 0; j < 23; j++)
    {
      randR = int(random(256));
      randG = int(random(256));
      randB = int(random(256));

      unitArray[i][j][0] = randR;  // <- add
      unitArray[i][j][1] = randG;
      unitArray[i][j][2] = randB;

      if (i % 2 == 0)
      {
        hexagon(j * 34.64102, i * 30, 20, color(randR,randG,randB), color(0, 0, 0));
        } else {
        hexagon(j * 34.64102 + 17.32051 , i * 30, 20, color(randR,randG,randB), color(0, 0, 0));
      }      
    }      
  }
}

// hexagon
void hexagon(float centerX, float centerY, float size, color fillColor, color strokeColor)
{
  final float COS[] = {0, -0.8660254, -0.8660254, 0, 0.86602524, 0.86602524};
  final float SIN[] = {1, 0.5,  -0.5, -1, -0.5, 0.5};

  final float RADIUS = size;

  // color
  fill(fillColor);
  stroke(strokeColor);

  beginShape();
  for(int i = 0; i < 6; i++)
  {
    float tx = COS[i] * RADIUS + centerX;
    float ty = SIN[i] * RADIUS + centerY;
    vertex(tx, ty);
  }
  endShape(CLOSE);
}

前回のプログラムと比較して、

  • 各ユニットのRGBの値を格納する3次元配列unitArrayを定義した。
  • unitArrayにランダマイズしたRGBの値を格納した。

以上2点を書き加えました。
出力は変わりませんが、この変更により、
各ユニットのRGBの値が3次元配列unitArrayに格納され、いつでも参照できるようになりました。

2.入力ベクトルを一つ用意する

さて、気を取り直しまして、Wikipedia:自己組織化写像の算法のステップの続きを実装しましょう!
次は、2.入力ベクトルを一つ用意するですね。

しかし、これは簡単です。
以下の1文で用意することが可能です。

//2. set a known input vector  // <- add
int[] inputArray = {255,0,0}; 

これは赤の入力ベクトルを用意するためのプログラムです。
後々、ここのプログラムは、

//2. set a random input vector  // <- add
int[] inputArray = {int(random(256)),int(random(256)),int(random(256))}

と変更する予定です。
しかし、最初は本当に実装できているかを確認するために、
既知の入力ベクトルを用意することとします。

3.各ノードを検査して、最も一致値が小さいノードを見つける。(BMU)

さて、ここから少々面倒なプログラムとなります。
BMUはBest Maching Unitの略です。
すなわち、入力ベクトルとユニットベクトルの最も距離が近いユニットを指します。
今回はこのBMUを各ノードを検査することで見つけます。

早速、見つけている部分のコードを見てみましょう。

//3. find Best Maching Unit  // <- add
int BMUi = 0, BMUj = 0;  
float tempDistance;
float minDistance = Float.MAX_VALUE;

for (int i = 0; i < 28; i++)
{
    for (int j = 0; j < 23; j++)
    {
      tempDistance = calculateDistance(unitArray[i][j], inputArray);

      if(minDistance > tempDistance)
      {
        minDistance = tempDistance;
        BMUi = i;
        BMUj = j;
      }
    }
}

// culcate distance
float calculateDistance(int[] unitArray1, int[] unitArray2)
{
  float distance;

  distance = sqrt(
             sq(unitArray1[0] - unitArray2[0]) + 
             sq(unitArray1[1] - unitArray2[1]) +
             sq(unitArray1[2] - unitArray2[2]));

  return distance;
}

少々ややこしいことをやっているように見えるかもしれませんね。
今回は、

  • setup関数の中に記述するプログラム
  • calculateDistance関数(2つの引数のベクトルの距離を返す関数)

と大きく分けて2つのブロックに分かれて記述されています。

setup関数の中に記述するプログラム

こちらは全ノードを検査する必要がありますので、
for文を2回まわしてすべてのユニットを探索しています。

各ユニットを回す際、そのユニットベクトルと入力ベクトルの距離を求めています。
そして、今まで発見していた入力ベクトルと最も近い距離minDistanceと、
そのユニットベクトルと入力ベクトルの距離tempDistanceを比較して、
tenpDistanceの方が近かった場合、tempDistanceはminDistanceとなります。
このときのiとjの値がBMUのiとjの値となります。
この処理をすべてのユニットに施すことで、BMUのiとjを探すことができます。

calculateDistance関数

calculateDistance関数は引数のベクトルを2つとり、両者間の距離をfloat型で返す関数です。
求め方はユークリッド距離を用いています。 ユークリッド距離は三平方の定理などにも登場するメジャーな距離の測定法です。
詳しくはこちらのホームページをご参照ください。
通信用語の基礎知識:ユークリッド距離

まとめると

はい!というわけで、1.2.3.の実装が終わりましたので、
全体のプログラムを動かしてみましょう!

void setup()
{
  size(780, 810);

  int randR, randG, randB;
  int tempR, tempG, tempB;
  int[][][] unitArray = new int[28][23][3];  // <- add

  //1. set random vectors
  for (int i = 0; i < 28; i++)
  {
    for (int j = 0; j < 23; j++)
    {
      randR = int(random(256));
      randG = int(random(256));
      randB = int(random(256));

      unitArray[i][j][0] = randR;  // <- add
      unitArray[i][j][1] = randG;
      unitArray[i][j][2] = randB;

      if (i % 2 == 0)
      {
        hexagon(j * 34.64102, i * 30, 20, color(randR,randG,randB), color(0, 0, 0));
        } else {
        hexagon(j * 34.64102 + 17.32051 , i * 30, 20, color(randR,randG,randB), color(0, 0, 0));
      }      
    }      
  }

  //2. set a random input vector  // <- add
  int[] inputArray = {255,0,0};   

  //3. find Best Maching Unit  // <- add
  int BMUi = 0, BMUj = 0;  
  float tempDistance;
  float minDistance = Float.MAX_VALUE;

  for (int i = 0; i < 28; i++)
  {
    for (int j = 0; j < 23; j++)
    {
      tempDistance = calculateDistance(unitArray[i][j], inputArray);

      if(minDistance > tempDistance)
      {
        minDistance = tempDistance;
        BMUi = i;
        BMUj = j;
      }
    }
  }

  print("BMU = (" + BMUi + "." + BMUj + ")");

}

void draw()
{

}

// hexagon
void hexagon(float centerX, float centerY, float size, color fillColor, color strokeColor)
{
  final float COS[] = {0, -0.8660254, -0.8660254, 0, 0.86602524, 0.86602524};
  final float SIN[] = {1, 0.5,  -0.5, -1, -0.5, 0.5};

  final float RADIUS = size;

  // color
  fill(fillColor);
  stroke(strokeColor);

  beginShape();
  for(int i = 0; i < 6; i++)
  {
    float tx = COS[i] * RADIUS + centerX;
    float ty = SIN[i] * RADIUS + centerY;
    vertex(tx, ty);
  }
  endShape(CLOSE);
}

// culcate distance
float calculateDistance(int[] unitArray1, int[] unitArray2)
{
  float distance;

  distance = sqrt(
             sq(unitArray1[0] - unitArray2[0]) + 
             sq(unitArray1[1] - unitArray2[1]) +
             sq(unitArray1[2] - unitArray2[2]));

  return distance;
}

実行結果は以下のようになります。

BMU = (4.1)

これは、すべてのユニットのうち最も赤いユニットが(4.1)であるということを意味しています。
それでは、色付きハニカム構造を見てみましょう。

f:id:sonoshou:20130621022206p:plain

配列は0番目から始めることに注意して数えていくと、
上から5番目、左から2番目のユニットが赤色であることがわかります。

入力ベクトルは{255,0,0}の赤色だったので、これに近い色を発見できていることが確認できました。

今回は以上です。

続きます。

自己組織化写像をprocessingで実装する。 part.4

自己組織化写像をprocessingで実装する。 part.2

3次元の色データを2次元にマッピングする自己組織化写像

さて、前回のエントリーでハニカム構造を作りました。
この後はどのようなデータを扱っていくかによって実装が変わってくるのですが、
今回は3次元の色データを2次元にマッピングする自己組織化写像のプログラムを書いてみようと思います。

早速プログラムに入っていっても良いのですが、
その前に少し、自己組織化写像について説明を加えようと思います。

前回、自己組織化写像は、
高次元のデータを(人間が見やすいように)2次元にビジュアライズする手法
と説明しましたが、少しわかりづらいですよね。
このことについて、今回の問題を例にとって説明します。

色データの次元

(パソコン画面などの液晶画面上の)色の次元は3次元で表されます。
光の三原色である赤、緑、青の色の強さの割合で様々な色を表現しているのです。
よく、この3種類の色の英語の頭文字をとってRGBと省略されます。

色の強さの段階は用途に応じて様々なのですが、ウェブ上では各々0~255の値で様々な色を表現するような仕組みになっています。
例えば、赤はR=255,G=0,B=0となり、黄はR=255,G=255,B=0となります。 黄は赤と緑の混色なので、R=255,G=255と2つの色の強さが最大になるのですね。

2次元データを2次元にマッピング

パソコンや携帯電話のディスプレイや新聞紙などの紙面は、
縦と横の2次元を持っています。
それでは、色のデータをマッピングしてみましょう。
ここでは、赤と緑の2次元をマッピングしてみました。

f:id:sonoshou:20130619191011p:plain

void setup()
{
  size(256, 256);

  for (int i = 0; i < 256; i++)
  {
    for (int j = 0; j < 256; j++)
    {
      rectColor(i, j, 1,color(i,j,0));     
    }      
  } 
}

void draw()
{
}

void rectColor(int x, int y, int size, color strokeColor)
{
  stroke(strokeColor);
  rect(x, y, size, size);
}

上の図は、横(X軸)に赤、縦(Y軸)に緑をとった図です。
右へ行けば行くほど赤が強く、下へ行けば行くほど緑が強く出ます。
従って、右下は赤と緑の両方共強くなったので黄が出力されています。
これが、2次元データのマッピングです。
とっても自然でとっても簡単だと思います。
このように、2次元のデータを2次元にマッピングすることは簡単なのです。

3次元データを2次元にマッピング

ところが、色は3次元です。
今回は赤と緑の2次元に話を限定しましたが、
ここに、青の要素を加えようとすると、とたんに話が難しくなります。

このような状況、高次元(今回の場合は3次元)データを2次元にビジュアライズしたいような状況のときに、
自己組織化写像が用いられます。

というわけで、本ブログでは、自己組織化写像を用いて、
3次元の色データを2次元に落としこむことを目標にしていきます。

自己組織化写像のアルゴリズム

早速、自己組織化写像の実装に入っていきますが、 その前に、自己組織化写像の全体像を見てみましょう。

自己組織化写像のアルゴリズムは、Wikipediaが詳しいです。
Wikipedia:自己組織化写像
上のリンク先の算法のステップから引用します。

1.全重みベクトルをランダマイズする
2.入力ベクトルを一つ用意する
3.各ノードを検査して、最も一致値が小さいノードを見つける。(BMU)
4.BMUの近傍のノードの重みベクトルを変更し、入力ベクトルに近付ける。
5.最大繰り返し回数に達していなければ2.に戻る。
Wikipedia:自己組織化写像 を一部改変~

ではでは、まずは1.全重みベクトルをランダマイズするですね!

1.全重みベクトルをランダマイズする

重みベクトルとは、色データのことです。
すなわち、前回のエントリーでハニカム構造を作成しましたが、
このハニカム構造のひとつひとつの六角形の色をランダムにすることが今回の1.に対応します。

文章ではわかりづらいので、まず結果を御覧ください。
その後、プログラムの説明を行いたいと思います。

f:id:sonoshou:20130619191014p:plain

void setup()
{
  size(797, 810);

  int randR, randG, randB;

  for (int i = 0; i < 28; i++)
  {
    for (int j = 0; j < 25; j++)
    {
      randR = int(random(256));
      randG = int(random(256));
      randB = int(random(256));

      if (i % 2 == 0)
      {
        hexagon(j * 34.64102, i * 30, 20, color(randR,randG,randB), color(0, 0, 0));
      } else {
        hexagon(j * 34.64102 - 17.32051 , i * 30, 20, color(randR,randG,randB), color(0, 0, 0));
      }      
    }      
  }
}

void draw()
{

}

// hexagon
void hexagon(float centerX, float centerY, float size, color fillColor, color strokeColor)
{
  final float COS[] = {0, -0.8660254, -0.8660254, 0, 0.86602524, 0.86602524};
  final float SIN[] = {1, 0.5,  -0.5, -1, -0.5, 0.5};

  final float RADIUS = size;

  // color
  fill(fillColor);
  stroke(strokeColor);

  beginShape();
  for(int i = 0; i < 6; i++)
  {
    float tx = COS[i] * RADIUS + centerX;
    float ty = SIN[i] * RADIUS + centerY;
    vertex(tx, ty);
  }
  endShape(CLOSE);
}

プログラムの説明

プログラムの以下の部分

randR = int(random(256));
randG = int(random(256));
randB = int(random(256));

この部分で各六角形の赤と緑と青の強さを決定しています。
色の強さは各々0~255で表されるので、
0~255の整数値がランダムで得られれば良いのです。
従って、2つの関数をうまく使って、目標の値を得ます。

(random(256));

は0以上256未満の値をランダムに返す変数です。
しかし、この関数の返り値はfloatであり、
返り値に小数点を含みます。
そこで、

int();

上のint関数を用いて、引数の値の小数点を切り捨てて整数とします。

このように、random関数とint関数をうまく使って、
0~255のランダムの整数値を得ています。

あとはここで得られたランダムの整数値を、
前回作成したhexagon関数の引数に加えるだけです。

まだ簡単ですかね? これにてプログラムの説明を終わります。

続きます。
続き書きましたよー><b
自己組織化写像をprocessingで実装する。 part.3

自己組織化写像をprocessingで実装する。 part.1

はじめに

研究室の勉強会でこのたび自己組織化写像を実装することになった。
というわけで、自己組織化写像の実装過程をブログに書こうかなーっと。
久しぶりの更新で気合が入りますね!

自己組織化写像とprocessing

今回は実装にprocessingを選ぶことにしました。
自己組織化写像は教師なし学習の機械学習の一種です。
自己組織化写像は、自己組織化マップSOMと呼ばれることも多いですので、
こちらも合わせて覚えておきましょう。
機械学習は普段ならRかpythonで実装するのだけど、今回はビジュアル重視ということで、グラフィック機能に特化した言語であるprocessingを採用してみました。
wikipedia:自己組織化写像
wikipedia:processing
自己組織化写像ここでの限定的な意味として簡単に申し上げますと、
高次元のデータを(人間が見やすいように)2次元にビジュアライズする手法です。
……と言ってもイメージしづらいと思いますので、以下のページをご参照下さい。
次回以降のエントリーでも同様の問題を扱い実装していく予定です。
勝手に整理整頓:http://gaya.jp/spiking_neuron/som.htm

バッチ型学習SOM

自己組織化写像にはたくさんのバリエーションがあります。
これについては上述の自己組織化写像Wikipediaページが詳しいです。
自己組織化写像ののバリエーションを大きく分けると、
1. 逐次型学習SOM
2. バッチ型学習SOM
の2種類があります。
本来ならば、データのビジュアライズを目的とする場合、
バッチ型学習SOMを採用すべきなのですが、
今回は簡単のため、逐次型の自己組織化写像を実装することにします。

その他、自己組織化写像については以下のページが詳しいです。
“データマイニング用SOM”,マインドウエア総研:
http://www.mindware-jp.com/basic/faq2.html

processing

processingについてはあまり触れませんが、簡単さだけはお伝えしたいなと思いまして。 processingはグラフィックに特化された言語だと上述しましたが、
どの程度楽なのか、一つ例を出そうと思います。

int i = 0;

void setup()
{
  size(200,200);
}

void draw()
{
  rect(0,0,100+i,100+i);
  i++;
}

f:id:sonoshou:20130618195021p:plain

これは200✕200のウィンドウの中に、
左上から右下へ四角形を(重ねながら)大きくしていくアニメーションプログラムです。

setup()はプログラムが始まって1回だけ実行され、
その後はdraw()が絶え間なく実行されます。

これにより、左上から少しずつ大きくなる四角形を描写することが可能です。
ただし、前の四角形を消すプログラムを書いていないので、
どんどん四角形を重ねていることになります。

このように、processingは簡単にグラフィック、アニメーション処理のプログラムを書くことが可能です。

さっそく書いてみる

processingのインストールは簡単なので省略っと……。
今回は1マスが六角形の自己組織化写像を実装する予定です。

まずは、ハニカム構造を書いてみることにしました。

void setup()
{
size(800, 800);

  for (int i = 0; i < 28; i++)
  {
    for (int j = 0; j < 25; j++)
    {
      if (i % 2 == 0)
      {
        hexagon(j * 34.64102, i * 30, 20, color(255,255,255), color(0, 0, 0));
      } else {
        hexagon(j * 34.64102 - 17.32051 , i * 30, 20, color(255,255,255), color(0, 0, 0));
      }

    }      
  } 
}

void draw()
{

}

// hexagon
void hexagon(float centerX, float centerY, float size, color fillColor, color strokeColor)
{
  final float COS[] = {0, -0.8660254, -0.8660254, 0, 0.86602524, 0.86602524};
  final float SIN[] = {1, 0.5,  -0.5, -1, -0.5, 0.5};

  final float RADIUS = size;

  // color
  fill(fillColor);
  stroke(strokeColor);

  beginShape();
  for(int i = 0; i < 6; i++)
  {
    float tx = COS[i] * RADIUS + centerX;
    float ty = SIN[i] * RADIUS + centerY;
    vertex(tx, ty);
  }
endShape(CLOSE);
}

以上がプログラムの全貌です。
実行結果は以下の通りになります。

f:id:sonoshou:20130618195151p:plain

draw()関数の中身について簡単に補足します。
……といっても特に特殊なことはしていませんね。

if (i % 2 == 0)

実行結果をご覧頂けると理解が早いのですが、
ハニカム構造は奇数行と偶数行(縦)で互い違いになっていることがわかります。
従って、偶数回目のループかどうかを判定して、処理を分けています。

hexagon(j * 34.64102, i * 30, 40);
hexagon(j * 34.64102 - 17.32051 , i * 30, 40);

以上が六角形を書くプログラムです。
hexagon()は、X座標とY座標と一辺の長さ、塗りつぶす色、枠線の色を与えると、
任意の場所に指定した六角形を書くことができる関数です。
こちらのページを参考にしました。
Processingで五角形・六角形・ハート形を描く:http://blog.p5info.com/?p=28

34.64102は20ルート3、17.32056は10ルート3にあたります。
二重ループを使ってうまーく六角形を書く場所を調整すると、このようになります。

次回に続きます。
続き書きました!
自己組織化写像をprocessingで実装する。 part.2

データの歩き方

この記事は、オライリー・ジャパン社の
入門 機会学習
の内容を元にしております。

「入門 機会学習」という本を研究室で買ってもらいました。
実践的な内容で興味深い本です。
全編に渡って、例題を出題し、その問題を機会学習で解くことで、
学習が進んでいくという具合です。
問題を解く際、Rを用います。

以下、2章の個人的なまとめです。
(個人メモなので、読んでもわからないと思います。是非お求めを。)

データ分析

  • 見つけたと考えている形式モデルを、パターン発見に用いたのとは
    別の新しいデータセットでテストする。
  • 確率論を用いて元々のデータセットの中で発見したパターンが
    偶然に生成されたもんかどうかをテストする。

データの探索

データの数値による要約標準的な可視化の手法は重要である。
基礎的な可視化の手法を使うだけでも、データからたくさんのことを
知り得ることができる。

データを探索するには、大きく分けて2つのアプローチがある。

  1. 要約統計量
  2. 次元削減

数値による要約

  1. 最小値
  2. 第1四分位(データ全体の下から25%の値。)
  3. 中央値(データ全体の真ん中の値。第2四分位とも。)
  4. 平均値
  5. 第3四分位(データ全体の上から25%の値。)
  6. 最大値
  7. 標準偏差

データの広がり

  • 広がりはデータのすべてではなく、ほぼ全てを含むべきである。
  • 広がりはデータ中の最大値と最小値の2つの値によって
    完全に決められるものではない。
    それらの値は外れ値である場合が多く、
    データセット全体を表すには適切な値ではない。

Rメモ

#最小値
min(data)

#最大値
max(data)

#中央値
mean(data)

#分散
var(data)

#標準偏差
#sd(data)

#データ範囲
range(data)

#4分位
quantile(data)

#N分位
#seq巻数を使い、0から1の間で0.20ずつ増やしている。
quantile(data, probs = seq(0, 1, 0.20))

#データの95%を含む範囲を調査
c(quantile(data, probs = 0.025),)quantile(data,probs=0.975))

#グラフ
library('ggplot2')
ggplot(data) #引数略
#ggplot2についてはこちらが詳しい。
#http://d.hatena.ne.jp/triadsou/20100528/1275042816

検定のお話 Rによる実践

検定のお話 A君 VS B君
前回、後輩の卒論を見ていて検定していないことが気になったわけだけど、うっかり
検定を行わないと教授に指摘される。
なんて書いたもんだから、本当に指摘されてしまった。

検定については去年勉強したはずだったのだけれど、 今回検定して忘れかけてきていることがわかったので、再度まとめ直します。

検定手法

検定には、複数の検定手法があり、
どの検定手法を使うか検討する必要があります。

ノンパラメトリックテストには
1)独立2群の比較      Mann-Whitney U-test
2)独立3群以上の比較    Kruskal-Wallis test
3)対応のある2群の比較   Wilcoxon signed rank test
4)対応のある3群以上の比較 Friedman test

パラメトリックテストには
1)母集団の平均値との比較      One Sample t-test
2)対応のない2群の比較       Unpaired t-test
3)対応のある2群の比較       Paired t-test
4)一元配置分散分析(対応なし)   One-way Factorial ANOVA
5)一元配置分散分析(対応あり)   One-Way Repeated-Measures ANOVA
6)二元配置分散分析(対応のない因子と対応のない因子)Two-way Factorial ANOVA
7)二元配置分散分析(対応のある因子と対応のない因子)Two-way Repeated-Measures ANOVA
引用元:「分散分析」http://www.ibaraki-kodomo.com/toukei/anova.html

パラメトリック検定は、等分散性や正規性が過程されます。
従って、以下の場合はノンパラメトリック検定が推奨されます。

  • 標本数に極端な差がある
  • 等分散を仮定しない
  • 標本数が少ない

詳しくはwikipediaをご参照して下さい。

Rで検定メモ

Rとは、統計解析向けのソフトウェアです。
Wikipedia:R言語
研究室の先輩がRによる検定方法をまとめてくれたので、
そちらをご紹介します。
(お、俺も少し加筆したよ><;)

CSVファイルの読み込み 
data <- read.csv("C:\\Users\\test\\Desktop\\test.csv", header=FALSE)

・T検定 
パラメトリック検定.2群の標本に対して,有意差があるか検定する. 
t.test(data$V1, data$V2) 

・F検定 
-パラメトリック検定.2群の標本に対して,等分散性があるか検定する. 
(等分散検定.T検定の前提である等分散性を検定するためによく用いられる.) 
-パラメトリック検定.3群以上の標本に対して,有意差があるか検定する.(分散分析) 
var.test(data$V1, data$V2)

・マンホイットニーのU検定 
ノンパラメトリック検定.2群の標本に対して,有意差があるか検定する. 
wilcox.test(data$V1, data$V2) 

・Bartlett検定 
各群の分散が均一であるかどうか検定する. 
p < Alpha: 分散が均一でない 
分散が均一:ANOVA 
分散が均一でない:Kruskal-Wallis 
bartlett.test(data) 

・Kruskal-Wallis検定(kruskal.test) + 多重比較 
ノンパラメトリック検定.3群以上の標本に対して,それぞれ有意差があるか検定する. 
source("http://aoki2.si.gunma-u.ac.jp/R/src/kruskal_wallis.R", encoding="euc-jp") 
kruskal.wallis(data, group=NULL) 

以上です。
もっと詳しく説明したかったのですが、今日は時間がないのでこのへんで。
それでは良い検定ライフを。

検定のお話 A君 VS B君

後輩の卒業論文を見ていて、検定の大事さを思い出した。
ちょうど1年前検定について学んでいたのだが、
すっかり忘れてきたので、少し復習しようと思い立った。

今回は復習した中で、自分が興味深かった話を紹介する。

A君とB君、どちらが強い?

A君とB君は共にライバル同士。
ある日、A君とB君はゲームの3本勝負をすることにした。
結果は、A君の2勝1敗、B君の1勝2敗だった。
以下はその時のA君とB君の会話である。

A君「へっへー、俺の方が強いだろー!」
B君「くそー、あとちょっとだったな……。でもなぁ……。」
A君「どうしたー?何か言い訳あるのかー?」
B君「まぁ、今回はたまたまだ。100本勝負したら俺の方が勝ってたなー。」
A君「何がたまたまだよ。」
B君「だって、3本勝負は少なすぎて実力差が出る前に終わっちまうもん。」
A君「お前そういう言い訳ばっかりじゃん。」
B君「いやいや。100本勝負で例えば、10回ぐらいしか勝てなかったら俺も素直に負けを認めるよ?
   でも、今回は2勝1敗じゃん。たまたま勝っただけなのに、そんな嬉しいのか?」
A君「はー!?お前負けたからって変な言い訳するなよ!じゃあどういう結果だったら満足すんだよ!」
B君「それは知らねーけど、何かたまたま勝っただけのお前が偉そうなのがムカつくんだよ!」
A君「キーッ!!かかってこいよ、オラァァァ!!!」
B君「うおおおお!!!!」

有意差とは

統計ではデータに差があることを有意差があると呼ぶ。
今回の場合は、A君とB君の実力に有意差があるかどうかを検定し、
A君とB君の間に統計的な有意差がある時だけ、実力差があると言って良い。

論文では、この検定を行うことが重要である。
複数のデータを取った時、
「平均が○○異なるので、こちらの方が優れている。」
なんて無根拠な主張は許されないのだ。
検定を行わないと教授に指摘される。

A君とB君はどちらが強いのか。

A君とB君に必要なのは、統計の知識である。
よくありそうな問題なのに、必要な数学の知識は大学数学というなんともまぁ滑稽である。

このような、2項分布の問題に対する検定と信頼区間を求めるには、
Rbinom.test()関数を使えば良い。

B君はA君が勝ったのは実力差ではなく、たまたまであると主張していたので、 A君とB君の勝つ確率は0.5であると仮定して検定してみましょう。

binom.test(c(1,2))

        Exact binomial test

data:  c(1, 2) 
number of successes = 1, number of trials = 3, p-value = 1
alternative hypothesis: true probability of success is not equal to 0.5 
95 percent confidence interval:
 0.008403759 0.905700676 
sample estimates:
probability of success 
             0.3333333 

p値は1。 p値とは、帰無仮説の下で実際にデータから計算された統計量よりも極端な統計量が観測される確率である。Wikipedia:有意

95%信頼区間は0.008403759~0.905700676 つまり、95%の確率で0.008403759~0.905700676が勝つ(もしくは負ける)確率であるという 意味である。
信頼区間が幅広いですね。
B君はA君が勝ったのはたまたまだと言っていましたが、
統計的にもたまたまであることが証明されました。

じゃあどうすればいいのか?

A 君「へっへー、俺の5連勝だぜ!」
B'君「くそー……。次こそは勝つぞー!」
A 君「いやいや、俺の5勝0敗だぜ?いい加減諦めろよ。」
B'君「ちょっと待って。検定するから。
   僕達の勝つ確率は0.5と仮定しよう。信頼区間は95%で異論はない?」
A 君「……。」

binom.test(c(0,5))

        Exact binomial test

data:  c(0, 5) 
number of successes = 0, number of trials = 5, p-value = 0.0625
alternative hypothesis: true probability of success is not equal to 0.5 
95 percent confidence interval:
 0.0000000 0.5218238 
sample estimates:
probability of success 
                     0 

B'君「あ、p値は0.0625ですね。有意水準0.05よりも大きいのでまだ実力差があるとは言えません。」
A 君「あ……、そう……。」

~次のゲーム&終了~

A 君「よ、よし。勝ったぞ……。」
B'君「ふむ、ちょっと待って下さい。」

> binom.test(c(0,6))

        Exact binomial test

data:  c(0, 6) 
number of successes = 0, number of trials = 6, p-value = 0.03125
alternative hypothesis: true probability of success is not equal to 0.5 
95 percent confidence interval:
 0.0000000 0.4592581 
sample estimates:
probability of success 
                     0 

B'君「p値は0.03125。有意水準0.05よりも小さいので実力差があると言えますね。」
A 君「……。」
B'君「どうしました?あなたの勝ちは統計的に証明されましたよ?」

A 君「しゃらくせえええ!!!!!」

Eclipseのテーマ

Dark Blackでおしゃれに決める!

パソコンの画面を長く見れば見るほど目が疲れてくる。
いわずもがなですが、仕方ないことではありますよね。
かくいう私も1日10時間ぐらいは平気でディスプレイを見続けているのですが、
流石に目への負担がひどくなってきました。
そこで現在主力で使っているIDEのEclipseのテーマを変更して、
少しでも目への負担を減らそうと思いました。

以下が本エントリー設定完了の参考の画像です。

f:id:sonoshou:20121203170028p:plain

テーマ変更の仕方

下のホームページを参考にしました。
http://d.hatena.ne.jp/cypher256/20120926/p1

1. カラーテーマをインストールする

  1. Eclipseを起動する。

  2. ヘルプ - 新規ソフトウェアのインストール

  3. 「追加」

  4. 名前に「color theme」、アドレスに
    http://eclipse-color-theme.github.com/update」を入力

  5. 「全て選択」

  6. 「次へ」

あとは流れで。
詳しくは http://eclipsecolorthemes.org/ をご参照下さい。

2. Dark Junoをダウンロードする

  1. 作者のホームページから「Eclipse-Juno-Dark.zip」をダウンロードする。
    https://github.com/Prototik/Eclipse-Juno-Dark/downloads

  2. 解凍する。

  3. 解凍して出てきたpluginフォルダの中の「Eclipse_Juno_Dark.jar」ファイルを
    eclipseが展開されているフォルダの「plugin」フォルダ内にコピー。

3. Eclipseからテーマを設定する。

  1. Eclipseを起動する。

  2. ウィンドウ - 設定
    (Macの場合 Eclipse - 環境設定)

  3. 一般 - 外観 - 色テーマ

  4. 「Pastel」を選択 (ここはお好みで。)

  5. 一般 - 外観

  6. テーマから「Eclipse Juno Dark」を選択

以上です。

これであなたも目に優しい環境で思い切ったプレーができるでしょう。