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

package MiniST

import std.fs.*

// 1. 数据加载类(保持高效解析)
class MiniSTLoader {
    var imagePath: String = ""
    var labelPath: String = ""

    public init(imgPath: String, labelPath: String) {
        this.imagePath = imgPath
        this.labelPath = labelPath
    }

    // 解析大端格式32位整数
    public func unpackI32(buffer: Array<UInt8>, offset: Int32): Int32 {
        return (Int32(buffer[Int64(offset)])) << 24 | (Int32(buffer[Int64(offset + 1)])) << 16 |
            (Int32(buffer[Int64(offset + 2)])) << 8 | (Int32(buffer[Int64(offset + 3)]))
    }

    // 加载图像数据(归一化到0-1)
    func loadImages(): Matrix<Float32> {
        let file = File(this.imagePath, OpenOption.Open(true, false)) // 只读模式
        let buffers = file.readToEnd()
        file.close()

        let imgNum = unpackI32(buffers, 4)
        let width = unpackI32(buffers, 8)
        let height = unpackI32(buffers, 12)
        let pixelCount = Int64(width * height)

        // 预分配内存避免动态扩容
        let images = Matrix<Float32>(Int64(imgNum), item: Array<Float32>())
        for (i in 0..=Int64(imgNum - 1)) {
            let row = Array<Float32>(Int64(pixelCount), item: 0.0)
            let baseIdx = 16 + i * pixelCount
            for (j in 0..=Int64(pixelCount - 1)) {
                row[j] = Float32(buffers[baseIdx + j]) / 255.0
            }
            images[Int64(i)] = row
        }
        return images
    }

    // 加载标签数据(转为one-hot编码)
    func loadLabels(): Matrix<Float32> {
        let file = File(this.labelPath, OpenOption.Open(true, false)) // 只读模式
        let buffers = file.readToEnd()
        file.close()

        let labelNum = unpackI32(buffers, 4)

        // 预分配内存
        let labels = Matrix<Float32>(Int64(labelNum)) {
            i => Array<Float32>(10) {
                j => if (j == Int64(buffers[8 + i])) {
                    1.0
                } else {
                    0.0
                }
            }
        }
        return labels
    }

    // 加载完整数据集
    func loadData(): (Matrix<Float32>, Matrix<Float32>) {
        let images = this.loadImages()
        let labels = this.loadLabels()
        return (images, labels)
    }
}