在 Xcode 中使用 MLModel 时如何重写更少的代码

Posted

技术标签:

【中文标题】在 Xcode 中使用 MLModel 时如何重写更少的代码【英文标题】:How to rewrite less code when using MLModels in Xcode 【发布时间】:2020-11-19 19:47:21 【问题描述】:

摘要:当我将.mlModel 拖入Xcode 时,Xcode 会为模型生成一个类接口。

我使用的所有模型输入都接受 common 初始化参数, 返回唯一输入类,这些类被传递给模型的predict(input:UniqueInput)方法和 那些返回一个唯一ModelOutput实例 它有一个common lazy var dependent: String 属性。

问题:每次我拖入一个新的.mlModel 时生成的唯一类要求我每次都重写代码。

目标:利用公共参数和依赖属性,以尽可能减少我在拖入新的.mlModels 时需要重写的代码量。

当前失败的尝试 我试图让自动生成的模型输入符合ModelVersion1 协议,以便新生成的模型输入具有共同的类型。但是,带有初始化程序的协议要求初始化程序实现具有 required 关键字,用于在自动生成的类中我无法控制的类。

func createRunningDataFrame() 
    var transactions: [Transaction] = []
    let model = try? MITO_1(configuration: MLModelConfiguration())
    URLRequest.streamFor(ticker: "MITO")  (runningFrame: DataFrame, price, ticker) in

      // ----------------------------> key line ----------------------
        guard let dependent: Double = try? model?.prediction(input: runningFrame.modelInput()!).dependent.double,
      // <-------------------------------------------------------------

        let direction = Direction(dependent: dependent) else  return 
        URLRequest.transact(direction, price, ticker)  transaction in
            transactions.append(transaction)
        
    

使用的代码

(自动生成)

class MITO_1 
    func prediction(input: MITO_1Input) throws -> MITO_1Output 
        return try self.prediction(input: input, options: MLPredictionOptions())
    



class MITO_1Input  
    init(daysOfWeek: String, tradingsHours: String, quarters: String) 
        self.daysOfWeek = daysOfWeek
        self.tradingsHours = tradingsHours
        self.quarters = quarters
    


class MITO_1Output : MLFeatureProvider 
    lazy var dependent: String =  [unowned self] in 
        return self.provider.featureValue(for: "dependent")!.stringValue
    ()

数据帧

extension DataFrame 
    
    func modelInput<T: ModelVersion1>() -> T? 
        guard let daysOfWeek = self.cell(for: "daysOfWeek"),
        let tradingsHours = self.cell(for: "tradingsHours"),
        let quarters = self.cell(for: "quarters") else  return nil 
        return T(
            daysOfWeek: daysOfWeek,
            tradingsHours: tradingsHours,
            quarters: quarters
        )
        

一致性 ERROR: Initializer requirement 'init(daysOfWeek:tradingsHours:quarters:)' can only be satisfied by a 'required' initializer in non-final class 'MITO_1Input'

extension MITO_1Input: ModelVersion1 

protocol ModelVersion1: AnyObject 
    init(daysOfWeek: String, tradingsHours: String, quarters: String)

字符串

extension String  
    var double: Double? 
        Double(self)
    

【问题讨论】:

【参考方案1】:

将自动生成的类复制到您自己的 Swift 文件中。禁用自动生成。修改 Swift 文件以满足您的需要。

请注意,自动生成的文件只是为了方便。它包装了MLModel API。您可以直接使用此 API,因此您不必使用自动生成的东西。

【讨论】:

如何禁用自动生成? 在应用程序的设置中,只需搜索“CoreML Compiler”,它可以让您在 Swift、Objective-C 或不生成任何代码之间进行选择。 我没有在项目的构建设置中找到它,我也没有在应用程序的目标构建设置中找到它。 确保选择“所有”设置(不仅仅是“基本”)。 耶。在我的项目构建设置中-所有我都找到了。谢谢!

以上是关于在 Xcode 中使用 MLModel 时如何重写更少的代码的主要内容,如果未能解决你的问题,请参考以下文章

Xcode 12 更新后快速运行 MLModel 的新错误

在 CreateML 中重新导入 mlmodel

CreateML App - 导出经过训练的 mlmodel 以在应用程序开发中使用

快速选择多个 .mlModel

预热 CoreML MLModel

动态加载 mlmodel