You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CoreML输入数组归一化:sklearn转换报错及iOS使用疑问

解决Sklearn Normalizer转CoreML及iOS中使用CoreML原生Normalizer的问题

一、解决Sklearn转CoreML时的num_dimensions报错问题

你遇到的这个报错是因为Sklearn的Normalizer是无状态的(调用fit()不会改变任何参数),CoreML转换器没办法自动推断输入特征的维度,所以必须显式指定num_dimensions参数,同时还要搭配feature_names一起传递。

修改后的代码如下:

from sklearn.preprocessing import Normalizer
import coremltools

# 初始化Sklearn的Normalizer,可指定归一化类型,默认是l2
normalized = Normalizer(norm='l2')

# 转换时显式指定特征名和维度
# num_dimensions=1表示输入是一维数组;如果是二维特征矩阵(样本x特征),就设为2
coreml_model = coremltools.converters.sklearn.convert(
    normalized,
    feature_names=["input_features"],
    num_dimensions=1
)

# 保存CoreML模型
coreml_model.save("SklearnNormalizer.mlmodel")

简单说明参数:

  • feature_names:给输入特征命名,方便iOS端调用时识别输入输出
  • num_dimensions:根据实际输入数据维度设置,1对应一维数组,2对应二维特征矩阵

二、iOS中使用CoreML原生Normalizer处理浮点数组

如果不想转Sklearn模型,直接用CoreML原生的Normalizer,步骤分为创建CoreML模型和iOS端调用两部分:

1. 用coremltools构建原生Normalizer模型

先通过Python代码生成符合要求的CoreML模型:

import coremltools as ct

# 配置Normalizer的归一化类型,可选L1/L2/MAX,对应Sklearn的norm参数
normalizer_spec = ct.proto.FeatureEngineering_pb2.Normalizer()
normalizer_spec.norm_type = normalizer_spec.L2
normalizer_spec.input_dimension = 1  # 输入维度,1表示一维数组

# 构建模型基础配置
model_spec = ct.proto.Model_pb2.Model()
model_spec.specificationVersion = ct.utils.SPECIFICATION_VERSION
model_desc = model_spec.description

# 添加输入特征:这里假设输入是10个元素的一维浮点数组
input_feat = model_desc.input.add()
input_feat.name = "input_array"
input_feat.type.multiArrayType.dataType = ct.proto.FeatureTypes_pb2.ArrayFeatureType.FLOAT32
input_feat.type.multiArrayType.shape.append(10)  # 设置数组长度

# 添加输出特征
output_feat = model_desc.output.add()
output_feat.name = "normalized_array"
output_feat.type.multiArrayType.dataType = ct.proto.FeatureTypes_pb2.ArrayFeatureType.FLOAT32
output_feat.type.multiArrayType.shape.append(10)

# 将Normalizer配置绑定到模型
model_spec.normalizer.CopyFrom(normalizer_spec)

# 保存模型
ct.models.MLModel(model_spec).save("CoreMLNativeNormalizer.mlmodel")

2. iOS Swift代码中调用模型处理浮点数组

把生成的.mlmodel文件拖进Xcode项目,Xcode会自动生成对应的模型类(比如这里是CoreMLNativeNormalizer),然后用下面的代码处理浮点数组:

import CoreML

func normalizeFloatArray(_ inputArray: [Double]) -> [Double]? {
    // 加载CoreML模型
    guard let model = try? CoreMLNativeNormalizer(configuration: .init()) else {
        print("模型加载失败")
        return nil
    }
    
    // 验证输入数组长度是否和模型定义一致(这里是10)
    guard inputArray.count == 10 else {
        print("输入数组长度不匹配模型要求")
        return nil
    }
    
    // 将Swift数组转换成MLMultiArray(CoreML要求的输入格式)
    guard let inputMultiArray = try? MLMultiArray(shape: [10], dataType: .float32) else {
        print("无法创建MLMultiArray")
        return nil
    }
    
    // 赋值给MLMultiArray
    for (index, value) in inputArray.enumerated() {
        inputMultiArray[index] = NSNumber(value: value)
    }
    
    // 创建模型输入并执行预测
    let modelInput = CoreMLNativeNormalizerInput(input_array: inputMultiArray)
    guard let modelOutput = try? model.prediction(input: modelInput) else {
        print("归一化处理失败")
        return nil
    }
    
    // 将输出的MLMultiArray转换成Swift数组
    let normalizedArray = (0..<modelOutput.normalized_array.count).map {
        modelOutput.normalized_array[$0].doubleValue
    }
    
    return normalizedArray
}

// 调用示例
let rawArray = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
if let result = normalizeFloatArray(rawArray) {
    print("归一化结果:\(result)")
}

这段代码的核心是把Swift的浮点数组转换成CoreML支持的MLMultiArray类型,传入模型得到归一化结果后,再转换回Swift数组供后续使用。

内容的提问来源于stack exchange,提问作者Spring

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:24:02