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

如何关闭Turi Create生成的Core ML图像分类器的Softmax层?

如何用Turi Create生成不带Softmax层的Core ML图像分类器

没问题,这事儿完全能搞定,不用费劲深度修改Turi Create源码,给你两种实用方法,按需选择:

方法1:导出后修改Core ML模型(最简单快捷)

Turi Create默认导出的图像分类模型带Softmax层,但我们可以用Core ML Tools轻松移除它,步骤如下:

  1. 先按常规流程训练并导出模型:
    import turicreate as tc
    
    # 加载你的图像数据集
    data = tc.image_analysis.load_images("你的数据集文件夹路径", with_path=True)
    # 从路径提取标签(根据你的文件夹结构调整逻辑)
    data["label"] = data["path"].apply(lambda path: path.split("/")[-2])
    
    # 训练图像分类器
    model = tc.image_classifier.create(data, target="label")
    # 导出默认带Softmax的Core ML模型
    model.export_coreml("OriginalWithSoftmax.mlmodel")
    
  2. 用Core ML Tools加载模型并移除Softmax层:
    import coremltools as ct
    
    # 加载刚导出的模型
    mlmodel = ct.models.MLModel("OriginalWithSoftmax.mlmodel")
    # 获取模型的神经网络结构规范
    nn_spec = mlmodel.get_spec()
    
    # 遍历所有层,找到Softmax层并标记删除
    softmax_layer_indices = []
    for idx, layer in enumerate(nn_spec.neuralNetwork.layers):
        if layer.WhichOneof("layer") == "softmax":
            softmax_layer_indices.append(idx)
    # 倒序删除,避免索引错乱
    for idx in reversed(softmax_layer_indices):
        del nn_spec.neuralNetwork.layers[idx]
    
    # 保存修改后的无Softmax模型
    modified_model = ct.models.MLModel(nn_spec)
    modified_model.save("ClassifierWithoutSoftmax.mlmodel")
    
    这样得到的模型输出就是预Softmax的logits值,你可以在App里自行计算Softmax。

方法2:训练阶段自定义模型结构(更灵活)

如果你想从源头就避免添加Softmax层,可以用Turi Create的NeuralNetClassifier搭建自定义网络,手动控制最后一层:

  1. 准备数据集并构建自定义网络:
    import turicreate as tc
    
    # 加载数据集并处理标签
    data = tc.image_analysis.load_images("你的数据集文件夹路径", with_path=True)
    data["label"] = data["path"].apply(lambda path: path.split("/")[-2])
    # 将标签映射为数值ID(分类任务需要)
    data = data.add_row_number()
    label_id_map = data.groupby("label", {"class_id": tc.aggregate.MIN("row_number")})
    data["class_id"] = data["label"].apply(lambda x: label_id_map[label_id_map["label"] == x]["class_id"][0])
    
    # 构建自定义神经网络
    net = tc.neural_networks.Sequential()
    # 添加预训练特征提取器(比如ResNet50,也可以用其他或自定义卷积层)
    net.add(tc.image_analysis.resnet_v2_50_feature_extractor())
    # 添加全局平均池化层,压缩特征维度
    net.add(tc.layers.GlobalAveragePooling2D())
    # 添加线性输出层,维度等于类别数,**不要设置激活函数**
    num_classes = len(data["label"].unique())
    net.add(tc.layers.Dense(num_classes, activation=None))
    
    # 训练模型,注意损失用softmax_cross_entropy(内部会自动处理logits)
    model = tc.neural_net_classifier.create(
        data,
        target="class_id",
        network=net,
        loss="softmax_cross_entropy",
        metric="accuracy"
    )
    
  2. 导出模型即可:
    model.export_coreml("CustomNoSoftmaxClassifier.mlmodel")
    
    这个模型的输出直接就是logits,完全符合你的需求。

小提示

  • 训练时用softmax_cross_entropy损失完全没问题,哪怕最后一层没有Softmax,Turi Create会在计算损失时自动处理logits,不影响模型训练效果。
  • 修改完模型后,记得在Xcode里查看模型的输出类型,确认是对应每个类别的向量(logits),而不是概率值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:58:29