/** * An adaptation of the Zhang-Oles 2001 CLG algorithm by Genkin et al. to * use the Laplace prior for parameter regularization. On completion, * optimizes the beta vector to maximize the likelihood of the data set. * * @param object $X SparseMatrix representing the training dataset * @param array $y array of known labels corresponding to the rows of $X */ function train($X, $y) { $invX = new InvertedData($X); $this->lambda = $this->estimateLambdaNorm($invX); $m = $invX->rows(); $n = $invX->columns(); $this->beta = array_fill(0, $n, 0.0); $beta =& $this->beta; $lambda = $this->lambda; $d = array_fill(0, $n, 1.0); $r = array_fill(0, $m, 0.0); $converged = false; $drSum = 0.0; $rSum = 0.0; $change = 0.0; $score = 0.0; $minDrj = $this->epsilon; $prevDrj = $this->epsilon; $schedule = new SplMaxHeap(); $nextSchedule = new SplMaxHeap(); for ($j = 0; $j < $n; $j++) { $schedule->insert(array($this->epsilon, $j)); } for ($k = 0; !$converged; $k++) { $prevR = $r; $var = 1; while (!$schedule->isEmpty()) { list($drj, $j) = $schedule->top(); if ($drj < $minDrj) { break; } else { $schedule->extract(); $prevDrj = $drj; } $Xj = $invX->iterateColumn($j); list($numer, $denom) = $this->computeApproxLikelihood($Xj, $y, $r, $d[$j]); // Compute tentative step $dvj if ($beta[$j] == 0) { $dvj = ($numer - $lambda) / $denom; if ($dvj <= 0) { $dvj = ($numer + $lambda) / $denom; if ($dvj >= 0) { $dvj = 0; } } } else { $s = $beta[$j] > 0 ? 1 : -1; $dvj = ($numer - $s * $lambda) / $denom; if ($s * ($beta[$j] + $dvj) < 0) { $dvj = -$beta[$j]; } } if ($dvj == 0) { $d[$j] /= 2; $nextSchedule->insert(array($this->epsilon, $j, $k)); } else { // Compute delta for beta[j], constrained to trust region. $dbetaj = min(max($dvj, -$d[$j]), $d[$j]); // Update our cached dot product by the delta. $drj = 0.0; foreach ($Xj as $cell) { list($_, $i, $Xij) = $cell; $dr = $dbetaj * $Xij; $drj += $dr; $r[$i] += $dr; } $drj = abs($drj); $nextSchedule->insert(array($drj, $j, $k)); $beta[$j] += $dbetaj; // Update the trust region. $d[$j] = max(2 * abs($dbetaj), $d[$j] / 2); } if ($this->debug > 1) { $score = $this->score($r, $y, $beta); } $this->log(sprintf("itr = %3d, j = %4d (#%d), score = %6.2f, change = %6.4f", $k + 1, $j, $var, $score, $change)); $var++; } // Update $converged $drSum = 0.0; $rSum = 0.0; for ($i = 0; $i < $m; $i++) { $drSum += abs($r[$i] - $prevR[$i]); $rSum += abs($r[$i]); } $change = $drSum / (1 + $rSum); $converged = $change <= $this->epsilon; while (!$schedule->isEmpty()) { list($drj, $j) = $schedule->extract(); $nextSchedule->insert(array($drj * 4, $j)); } $tmp = $schedule; $schedule = $nextSchedule; $nextSchedule = $tmp; $minDrj *= 2; } }
$heap->insert('3'); $heap->insert('1'); $heap->insert('2'); $heap->insert('5'); $heap->insert('4'); // $heap = new SplPriorityQueue(); // insert($value, $priority) // 优先队列插入新值 //$heap->insert('A', '3'); //$heap->insert('B', '1'); //$heap->insert('C', '2'); //$heap->insert('D', '5'); //$heap->insert('E', '4'); // isEmpty() // 判断该堆是否为空 $heap->isEmpty(); // count() // 获得堆值的数量 $heap->count(); // key() // 返回当前节点的索引值 $heap->key(); // valid() // 判断堆中还是否有其他节点 $heap->valid(); // rewind() // 返回首节点,在堆中是空操作。因为堆是二叉树,rewind始终会在当前位置而不移动 $heap->rewind(); // current() // 获得当前节点 $heap->current();
<?php $h = new SplMaxHeap(); var_dump($h->isEmpty());
<?php $data_provider = array(new stdClass(), array(), true, "string", 12345, 1.2345, NULL); foreach ($data_provider as $input) { $h = new SplMaxHeap(); var_dump($h->isEmpty($input)); }
<?php $h = new SplMaxHeap(); echo "Checking a new heap is empty: "; var_dump($h->isEmpty()) . "\n"; $h->insert(2); echo "Checking after insert: "; var_dump($h->isEmpty()) . "\n"; $h->extract(); echo "Checking after extract: "; var_dump($h->isEmpty()) . "\n";