Creating .mlmodel with Create ML Components

I have rewatched WWDC22 a few times , but still not getting full understanding how to get .mlmodel model file type from components .

Example with banana ripeness is cool , but what need to be added to actually have output of .mlmodel , is somewhere full sample code for this type of modular project ?

Code is from [https://developer.apple.com/videos/play/wwdc2022/10019)

import CoreImage
import CreateMLComponents

struct ImageRegressor {
    static let trainingDataURL = URL(fileURLWithPath: "~/Desktop/bananas")
    static let parametersURL = URL(fileURLWithPath: "~/Desktop/parameters")

    static func train() async throws -> some Transformer<CIImage, Float> {
        let estimator = ImageFeaturePrint()
            .appending(LinearRegressor())

        // File name example: banana-5.jpg
        let data = try AnnotatedFiles(labeledByNamesAt: trainingDataURL, separator: "-", index: 1, type: .image)
            .mapFeatures(ImageReader.read)
            .mapAnnotations({ Float($0)! })

        let (training, validation) = data.randomSplit(by: 0.8)
        let transformer = try await estimator.fitted(to: training, validateOn: validation)
        try estimator.write(transformer, to: parametersURL)

        return transformer
    }
}

I have tried to run it in Mac OS command line type app, Swift-UI but most what I had as output was .pkg with

"pipeline.json, parameters, optimizer.json, optimizer"

Answered by Frameworks Engineer in 827476022

can you try the following

try transformer.export(to: modelURL)

Accepted Answer

can you try the following

try transformer.export(to: modelURL)

import CoreImage
import CreateMLComponents
import Foundation

struct ImageRegressor {
    static let trainingDataURL = URL(fileURLWithPath: ("~/Desktop/bananas" as NSString).expandingTildeInPath)
    static let parametersURL = URL(fileURLWithPath: ("~/Desktop/parameters" as NSString).expandingTildeInPath)
    static let modelURL = URL(fileURLWithPath: ("~/Desktop/model.mlmodel" as NSString).expandingTildeInPath)

    static func train() async throws -> some Transformer<CIImage, Float> {
        // 1. Verify paths
        print("🛠️ Training data path:", trainingDataURL.path)
        print("🛠️ Parameters path:", parametersURL.path)
        print("🛠️ Model path:", modelURL.path)
        
        // 2. Create directories
        try FileManager.default.createDirectory(at: parametersURL, withIntermediateDirectories: true)
        try FileManager.default.createDirectory(at: modelURL.deletingLastPathComponent(), withIntermediateDirectories: true)
        
        // 3. Training setup
        print("🔍 Loading training data...")
        let data = try AnnotatedFiles(labeledByNamesAt: trainingDataURL, separator: "-", index: 1, type: .image)
            .mapFeatures(ImageReader.read)
            .mapAnnotations { Float($0)! }
        
        print("📊 Dataset size:", data.count)
        guard data.count > 0 else { throw NSError(domain: "No training data", code: -1) }
        
        let (training, validation) = data.randomSplit(by: 0.8)
        print("✂️ Split: \(training.count) training, \(validation.count) validation")
        
        // 4. Model training
        print("🏋️ Training model...")
        let estimator = ImageFeaturePrint().appending(LinearRegressor())
        let transformer = try await estimator.fitted(to: training, validateOn: validation)
        
        // 5. Save outputs
        print("💾 Saving parameters...")
        try estimator.write(transformer, to: parametersURL.appendingPathComponent("params.bin"))
        
        print("💾 Saving model...")
        try transformer.export(to: modelURL)
        
        print("✅ Done! Model saved to:", modelURL.path)
        return transformer
    }
}

// 6. Execution wrapper
func main() {
    let semaphore = DispatchSemaphore(value: 0)
    
    Task {
        do {
            _ = try await ImageRegressor.train()
        } catch {
            print("❌ Error:", error)
        }
        semaphore.signal()
    }
    
    semaphore.wait()
}

// 7. Start execution
main()

Updated to full code , thank you .

Some recommendations for evolution , do I need to do separate folder like in Create ML to evaluate or increase number of iterations?

Debug Console 🛠️ Training data path: /Users/xcode/Desktop/bananas 🛠️ Parameters path: /Users/xcode/Desktop/parameters 🛠️ Model path: /Users/xcode/Desktop/model.mlmodel 🔍 Loading training data... 📊 Dataset size: 273 ✂️ Split: 217 training, 56 validation 🏋️ Training model... The optimizer failed to converge after 21 iterations. 💾 Saving parameters... 💾 Saving model... ✅ Done! Model saved to: /Users/xcode/Desktop/model.mlmodel Program ended with exit code: 0

The optimizer failed to converge after 21 iterations.
Type: Error | Timestamp: 2025-03-03 18:00:50.224932Z | Process: Train Banana | Library: CreateMLComponents | Subsystem: com.apple.createml | Category: optimization | TID: 0x3efb9
Creating .mlmodel with Create ML Components
 
 
Q