<?php /****************************/ /* 競合学習 */ /* coded by Y.Suganuma */ /****************************/ /***************************/ /* Competitionクラスの定義 */ /***************************/ class Competition { private $max; // 最大学習回数 private $n; // 訓練例の数 private $o; // 出力セルの数 private $p; // 入力セルの数 private $E; // 訓練例 private $W; // 重み private $sig; // 重み修正係数 /******************/ /* コンストラクタ */ /******************/ function Competition($max_i, $n_i, $o_i, $p_i, $sig_i) { /* 設定 */ $this->sig = $sig_i; $this->max = $max_i; $this->n = $n_i; $this->o = $o_i; $this->p = $p_i; mt_srand(); /* 領域の確保 */ $this->E = array($this->n); for ($i1 = 0; $i1 < $this->n; $i1++) $this->E[$i1] = array($this->p); $this->W = array($this->o); for ($i1 = 0; $i1 < $this->o; $i1++) $this->W[$i1] = array($this->p); } /**************************/ /* 学習データの読み込み */ /* name : ファイル名 */ /**************************/ function Input($name) { $st = fopen($name, "rb"); for ($i1 = 0; $i1 < $this->n; $i1++) { $str = trim(fgets($st)); $this->E[$i1][0] = intval(strtok($str, " ")); for ($i2 = 1; $i2 < $this->p; $i2++) $this->E[$i1][$i2] = intval(strtok(" ")); } fclose($st); } /*********************************/ /* 学習と結果の出力 */ /* pr : =0 : 画面に出力 */ /* =1 : ファイルに出力 */ /* name : 出力ファイル名 */ /*********************************/ function Learn($pr, $name = "STDOUT") { $mx = 0; $mx_v = 0.0; /* 初期設定 */ for ($i1 = 0; $i1 < $this->o; $i1++) { $sum = 0.0; for ($i2 = 0; $i2 < $this->p; $i2++) { $this->W[$i1][$i2] = mt_rand() / mt_getrandmax(); $sum += $this->W[$i1][$i2]; } $sum = 1.0 / $sum; for ($i2 = 0; $i2 < $this->p; $i2++) $this->W[$i1][$i2] *= $sum; } /* 学習 */ for ($count = 0; $count < $this->max; $count++) { // 訓練例の選択 $k = intval(mt_rand() / mt_getrandmax() * $this->n); if ($k >= $this->n) $k = $this->n - 1; // 出力の計算 for ($i1 = 0; $i1 < $this->o; $i1++) { $s = 0.0; for ($i2 = 0; $i2 < $this->p; $i2++) $s += $this->W[$i1][$i2] * $this->E[$k][$i2]; if ($i1 == 0 || $s > $mx_v) { $mx = $i1; $mx_v = $s; } } // 重みの修正 $sum = 0.0; for ($i1 = 0; $i1 < $this->p; $i1++) $sum += $this->E[$k][$i1]; for ($i1 = 0; $i1 < $this->p; $i1++) $this->W[$mx][$i1] += $this->sig * ($this->E[$k][$i1] / $sum - $this->W[$mx][$i1]); } /* 出力 */ if ($pr == 0) $out = STDOUT; else $out = fopen($name, "w"); fwrite($out, "分類結果\n"); for ($i1 = 0; $i1 < $this->n; $i1++) { $str = ""; for ($i2 = 0; $i2 < $this->p; $i2++) $str = $str." ".$this->E[$i1][$i2]; $str = $str." Res "; for ($i2 = 0; $i2 < $this->o; $i2++) { $s = 0.0; for ($i3 = 0; $i3 < $this->p; $i3++) $s += $this->W[$i2][$i3] * $this->E[$i1][$i3]; if ($i2 == 0 || $s > $mx_v) { $mx = $i2; $mx_v = $s; } } fwrite($out, $str.($mx+1)."\n"); } } } /****************/ /* main program */ /****************/ if (count($argv) > 1) { // 基本データの入力 $st = fopen($argv[1], "r"); fscanf($st, "%*s %ld %*s %ld %*s %ld %*s %ld %*s %lf", $max, $p, $o, $n, $sig); fscanf($st, "%*s %s", $name); fclose($st); // ネットワークの定義 $net = new Competition($max, $n, $o, $p, $sig); $net->Input($name); // 学習と結果の出力 if (count($argv) == 2) $net->Learn(0); else $net->Learn(1, $argv[2]); } else exit("***error 入力データファイル名を指定して下さい\n"); /* ------------------------入力ファイル-------------- 最大試行回数 1000 入力セルの数 9 出力セルの数 3 訓練例の数 9 係数(0~1) 0.1 入力データファイル pat.dat ------------------------pat.dat------------------- 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 */ ?>