Abstract: When I drag in an .mlModel
into Xcode
, Xcode
generates a class interface for the model.
- All the model Inputs I use accept common initializer arguments,
- return unique Input classes, which are passed to the model's
predict(input:UniqueInput)
method and - those return a unique
ModelOutput
instance - which has a common
lazy var dependent: String
property.
Problem: The unique classes generated every time I drag in a new .mlModel
requires me to rewrite code every time.
Goal: to take advantage of the common arguments and dependent property in order to minimize as much as possible the amount of code I need to rewrite when I drag in new .mlModels
.
Current Failing Attempt
I tried to have the autogenerated model input conform to a ModelVersion1
protocol so that newly generated model inputs would have a Type in common. However protocols with initializers require that the initializer implementation has the required
keyword for classes which I don't have control over in autoGenerated classes.
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)
}
}
}
Used Code
(Auto generated)
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
}()
}
DataFrame
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
)
}
}
Conformance
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)
}
String
extension String {
var double: Double? {
Double(self)
}
}