5431f9d6创建于 2025年9月18日历史提交
/**
 * Created on
 *      2025/9/17
 *      2025/9/4
 *      2025/8/29
 * ----------------
 * package MiniST
 *      module MatrixUtils
 */

package MiniST

import std.math.*
import std.runtime.*
import std.random.*

// 2. 优化的矩阵工具类(批次级向量化运算)
class MatrixUtils {
    public static let chunkSize: Int64 = BPNetwork.chunkSize
    // 批次向量×矩阵(batch: m×n, mat: n×p → result: m×p)
    public static func batchVecMatMul(batch: Matrix<Float32>, mat: Matrix<Float32>): Matrix<Float32> {
        let m = batch.size
        let n = mat.size
        let p = mat[0].size
        let result = Matrix<Float32>(Int64(m)) {i => Array<Float32>(Int64(p), item: 0.0)}

        AsyncTask(n / chunkSize) {
            s => spawn {
                for (k in s * chunkSize..min(s * chunkSize + chunkSize, n)) {
                    let kIndex = Int64(k)
                    for (iIndex in 0..=m - 1) {
                        let val = batch[iIndex][kIndex]
                        if (val == 0.0) {
                            continue
                        } // 稀疏优化
                        for (jIndex in 0..=p - 1) {
                            result[iIndex][jIndex] += val * mat[kIndex][jIndex]
                        }
                    }
                }
            }
        }
        return result
    }

    // 批次矩阵+偏置(广播)
    public static func batchAddBias(batch: Matrix<Float32>, bias: Array<Float32>): Matrix<Float32> {
        let m = batch.size
        let n = batch[0].size
        let result = Matrix<Float32>(Int64(m), item: Array<Float32>())

        AsyncTask((m + chunkSize - 1) / chunkSize) {
            chunkIndex =>
            let start = chunkIndex * chunkSize
            let end = min(start + chunkSize, m)
            spawn {
                for (iIndex in start..end) {
                    let row = Array<Float32>(n, item: 0.0)
                    for (j in 0..=n - 1) {
                        row[j] = batch[iIndex][j] + bias[j]
                    }
                    result[iIndex] = row
                }
            }
        }
        return result
    }

    // 批次ReLU激活
    public static func batchRelu(batch: Matrix<Float32>): Matrix<Float32> {
        let m = batch.size
        let n = batch[0].size
        let result = Matrix<Float32>(Int64(m), item: Array<Float32>())

        AsyncTask((m + chunkSize - 1) / chunkSize) {
            s =>
            let start = s * chunkSize
            let end = min(start + chunkSize, m)
            spawn {
                for (iIndex in start..end) {
                    let row = Array<Float32>(n, item: 0.0)
                    for (j in 0..=n - 1) {
                        let val = batch[iIndex][j]
                        row[j] = if (val > 0.0) {
                            val
                        } else {
                            0.0
                        }
                    }
                    result[iIndex] = row
                }
            }
        }
        return result
    }

    // 批次Softmax(数值稳定版)
    public static func batchSoftmax(batch: Matrix<Float32>): Matrix<Float32> {
        let m = batch.size
        let n = batch[0].size
        let result = Matrix<Float32>(Int64(m), item: Array<Float32>())

        AsyncTask((m + chunkSize - 1) / chunkSize) {
            s =>
            let start = s * chunkSize
            let end = min(start + chunkSize, m)
            spawn {
                for (iIndex in start..end) {
                    let row = batch[iIndex]
                    // 找每行最大值(数值稳定)
                    var maxVal = row[0]
                    for (j in 1..=n - 1) {
                        if (row[j] > maxVal) {
                            maxVal = row[j]
                        }
                    }

                    // 计算指数和
                    var expSum = Float32(0.0)
                    let expVals = Array<Float32>(n, item: 0.0)
                    for (j in 0..=n - 1) {
                        expVals[j] = exp(row[j] - maxVal)
                        expSum += expVals[j]
                    }

                    // 归一化
                    let softmaxRow = Array<Float32>(Int64(n), item: 0.0)
                    for (j in 0..=n - 1) {
                        softmaxRow[j] = expVals[j] / expSum
                    }
                    result[iIndex] = softmaxRow
                }
            }
        }
        return result
    }

    // 向量×矩阵(单样本辅助函数)
    public static func vecMatMul(vec: Array<Float32>, mat: Matrix<Float32>): Array<Float32> {
        let n = vec.size
        let p = mat[0].size
        let result = Array<Float32>(Int64(p), item: 0.0)

        for (kIndex in 0..=n - 1) {
            let val = vec[kIndex]
            if (val == 0.0) {
                continue
            }
            for (j in 0..=p - 1) {
                result[j] += val * mat[kIndex][j]
            }
        }
        return result
    }

    // 向量+偏置(单样本辅助函数)
    public static func vecAdd(vec: Array<Float32>, bias: Array<Float32>): Array<Float32> {
        let n = vec.size
        let result = Array<Float32>(Int64(n), item: 0.0)
        for (i in 0..=n - 1) {
            result[i] = vec[i] + bias[i]
        }
        return result
    }

    // 单样本ReLU(辅助函数)
    public static func relu(vec: Array<Float32>): Array<Float32> {
        let n = vec.size
        let result = Array<Float32>(Int64(n), item: 0.0)
        for (i in 0..=n - 1) {
            let val = vec[i]
            result[i] = if (val > 0.0) {
                val
            } else {
                0.0
            }
        }
        return result
    }

    // 单样本Softmax(辅助函数)
    public static func softmax(vec: Array<Float32>): Array<Float32> {
        let n = vec.size
        var maxVal = vec[0]
        for (i in 1..=n - 1) {
            if (vec[i] > maxVal) {
                maxVal = vec[i]
            }
        }

        var expSum = Float32(0.0)
        let expVals = Array<Float32>(n, item: 0.0)
        for (i in 0..=n - 1) {
            expVals[i] = exp(vec[i] - maxVal)
            expSum += expVals[i]
        }

        let result = Array<Float32>(n, item: 0.0)
        for (i in 0..=n - 1) {
            result[i] = expVals[i] / expSum
        }
        return result
    }

    public static func randomInit(row: Int32, col: Int32): Matrix<Float32> {
        let result = Matrix<Float32>(Int64(row), item: Array<Float32>())
        let stddev = sqrt(2.0 / (Float32(row) + Float32(col))) // 正确的sigma
        let r = Random()

        for (i in 0..=Int64(row - 1)) {
            let rowArr = Array<Float32>(Int64(col), item: 0.0)
            for (j in 0..=Int64(col - 1)) {
                // 正确的正态分布参数
                var val = r.nextGaussianFloat32(mean: 0.0, sigma: stddev)
                // 截断到[-2σ, 2σ]
                if (val < -2.0 * stddev) {
                    val = -2.0 * stddev
                }
                if (val > 2.0 * stddev) {
                    val = 2.0 * stddev
                }
                rowArr[j] = val
            }
            result[i] = rowArr
        }
        return result
    }
}