Linear Transformations
Scale Transformation
In PHP it can be written as a class LinearTransformation
with implementation of linear transformation operations.
Example of class LinearTransformation
:
<?php
declare(strict_types=1);
class LinearTransformation {
private $matrix;
private $rows;
private $cols;
/**
* Constructor to initialize the transformation matrix
* @param array $matrix The transformation matrix
* @throws InvalidArgumentException If matrix is invalid
*/
public function __construct(array $matrix) {
if (!$this->isValidMatrix($matrix)) {
throw new InvalidArgumentException("Invalid matrix: all rows must have same length");
}
$this->matrix = $matrix;
$this->rows = count($matrix);
$this->cols = count($matrix[0]);
}
/**
* Apply the linear transformation to a vector
* @param array $vector The input vector
* @return array The transformed vector
* @throws InvalidArgumentException If vector dimension doesn't match matrix columns
*/
public function transform(array $vector): array {
if (count($vector) !== $this->cols) {
throw new InvalidArgumentException(
"Vector dimension ({$this->cols}) must match matrix columns ({$this->cols})"
);
}
$result = [];
for ($i = 0; $i < $this->rows; $i++) {
$sum = 0;
for ($j = 0; $j < $this->cols; $j++) {
$sum += $this->matrix[$i][$j] * $vector[$j];
}
$result[] = $sum;
}
return $result;
}
/**
* Apply linear transformation with weights and bias: y = Wx + b
* @param array $input The input vector
* @param array $bias The bias vector
* @return array The transformed vector with bias added
* @throws InvalidArgumentException If dimensions don't match
*/
public function linearLayer(array $input, array $bias): array {
// First validate that bias vector length matches number of rows
if (count($bias) !== $this->rows) {
throw new InvalidArgumentException(
"Bias dimension must match matrix rows"
);
}
// Use existing transform method to compute Wx
$transformed = $this->transform($input);
// Add bias to each element: Wx + b
$result = [];
for ($i = 0; $i < $this->rows; $i++) {
$result[] = $transformed[$i] + $bias[$i];
}
return $result;
}
/**
* Apply ReLU activation function to a vector
* @param array $vector Input vector
* @return array Vector with ReLU activation applied
*/
public function relu(array $vector): array {
return array_map(function($v) {
return max(0, $v);
}, $vector);
}
/**
* Static method to perform linear transformation with weights and bias: y = Wx + b
* @param array $weights The weight matrix W
* @param array $bias The bias vector b
* @param array $input The input vector x
* @return array The transformed vector
* @throws InvalidArgumentException If dimensions don't match
*/
public function linearTransform(array $weights, array $bias, array $input): array {
// Use existing linearLayer method
return $this->linearLayer($input, $bias);
}
/**
* Get the transformation matrix
* @return array The transformation matrix
*/
public function getMatrix(): array {
return $this->matrix;
}
/**
* Get matrix dimensions
* @return array [rows, columns]
*/
public function getDimensions(): array {
return [$this->rows, $this->cols];
}
/**
* Validate if the matrix has consistent dimensions
* @param array $matrix Matrix to validate
* @return bool True if valid, false otherwise
*/
private function isValidMatrix(array $matrix): bool {
if (empty($matrix) || !is_array($matrix[0])) return false;
$columnCount = count($matrix[0]);
foreach ($matrix as $row) {
if (!is_array($row) || count($row) !== $columnCount) {
return false;
}
}
return true;
}
}