Machine Learning in Objective-C Has Never Been Easier

Posted by

Taking the opportunity provided by our recent Spring release, BigML is pleased to announce our new SDK for Objective-C, bigml-objc, which provides a modern, block-based Objective-C API, and a new more maintainable and coherent design. Additionally, bigml-objc includes support for WhizzML, our exciting new DSL for the automation of ML workflows. bigml-objc evolves and supersedes the old ML4iOS library, which has been kindly supported by BigML’s friend Felix Garcia Lainez.

logo

bigml-objc‘s API design follows along the lines of our Swift SDK. Its main aim is to allow iOS, OS X, watchOS, and tvOS developers to easily integrate BigML services into their apps while also benefitting from modern Objective-C features (first and foremost Objective-C blocks), which allow for a simple handling of asynchronous operations.

The main features BigML SDK for Objective-C provides can be divided into two areas:

  • Remote resource processing: BigML SDK exposes BigML’s REST API through a higher-level Objective-C API that will make is easier for you to create, retrieve, update, and delete remote resources. Supported resources are:

    source Sources source Datasets
    source Models source Clusters
    source Anomalies source Ensembles
    source Predictions source WhizzML
  • Local resource processing: BigML SDK allows you to mix local and remote distributed processing in a seamless and transparent way. You will be able to download your remote resources (e.g. a cluster) and then apply supported algorithms to them (e.g. calculate its nearest centroid based on your input data). This is one definite advantage that BigML offers in comparison to competing services, which mostly bind you into either using their remote services or do everything locally. BigML’s SDK for Objective-C combines the benefits of both approaches by making it possible to use the power of a cloud solution and to enjoy the flexibility/transparency of local processing right when you need it. The following is a list of currently supported algorithms that BigML’s SDK for Objective-C provides:

    • Model predictions
    • Ensemble predictions
    • Clustering
    • Anomaly detections.

    A dive into BigML’s Objective-C API

    The BMLAPIConnector class is the workhorse of all remote processing: it allows you to create, delete, and get remote resource of any supported type. When instantiating it, you should provide your BigML’s account credentials and specify whether you want to work in development or production mode:

    BMLAppAPIConnector* connector =
      [[BMLAppAPIConnector alloc]
         initWithUsername:@"your BigML username here"
                   apiKey:@"your BigML API Key here"
                     mode:BMLModeProduction
                   server:nil
                  version:nil]
    

    You can safely pass nil for the version argument, since there is actually only one API version supported by BigML.

    Once you connector is instantiated, you can use it to create a data source from a local CSV file:

    
    NSString* filePath = ...;
    BMLMinimalResource* file =
    [[BMLMinimalResource alloc]
       initWithName:@"My Data Source"
               type:BMLResourceTypeFile
               uuid:filePath
         definition:nil];
    
    [connector createResource:BMLResourceTypeSource
                         name:@"My frist data source"
                      options:nil
                         from:file
                   completion:^(id resource, NSError* error) {
    
          if (error == nil) {
                 //-- use resource
          } else {
                 //-- handle error
          }
    }];
    
    

    As you can see, BMLAPIConnector’s createResource allows you to specify the type of resource you want to create, its name, a set of options, and the resource that should be used to create it, in this case a local file.

    BigML SDK for Objective-C’s API is entirely asynchronous and relies on completion blocks, where you will get the resource that has been created, if any, or the error that aborted the operation as applicable. The resource you will receive in the completion block is an instance of the BMLMinimalResource type, which conforms to the BMLResource protocol.

    typedef NSString BMLResourceUuid;
    typedef NSString BMLResourceFullUuid;
    
    @class BMLResourceTypeIdentifier;
    
    /**
     * This protocol represents a generic BigML resource.
     */
    @protocol BMLResource <NSObject>
    
    /// the json body of the resource. See BigML REST API doc (https://tropo.dev.bigml.com/developers/)
    @property (nonatomic, strong) NSDictionary* jsonDefinition;
    
    /// the current status of the resource
    @property (nonatomic) BMLResourceStatus status;
    
    /// the resource progress, a float between 0 and 1
    @property (nonatomic) float progress;
    
    /// the resource name
    - (NSString*)name;
    
    /// the resource type
    - (BMLResourceTypeIdentifier*)type;
    
    /// the resource UUID
    - (BMLResourceUuid*)uuid;
    
    /// the resource full UUID
    - (BMLResourceFullUuid*)fullUuid;
    
    @end
    

    The BMLResource protocol encodes the most basic information that all resources share: a name, a type, a UUID, the resource’s current status, and a JSON object that describes all of its properties. You are supposed to create your own custom class that conforms to the BMLResource protocol and that best suits your needs e.g., it might be a Core Data class that allows you to persist your resource to a local cache. Of course you are welcome to reuse our BMLMinimalResource implementation as you wish.

    In a pretty similar way you can create a dataset from the data source just created:

    [connector createResource:BMLResourceTypeDataset
                         name:@"My first dataset"
                      options:nil
                         from:myDatasource
                   completion:^(id resource, NSError* error) {
    
            if (error == nil) {
                  //-- use resource
            } else {
                  //-- handle error
            }
    }];
    

    If you know the UUID of an existing resource of a given type and want to retrieve it from BigML, you can use BMLAPIConnector’s getResource method:

    [connector getResource:BMLResourceTypeDataset
                         uuid:resourceUUID
                   completion:^(id resource, NSError* error) {
    
              if (error == nil) {
                   //-- use resource
              } else {
                   //-- handle error
              }
    }];
    

    Creating WhizzML Scripts

    You can create a WhizzML script in a way similar to how you create a datasource, i.e., by using BMLAPIConnector‘s createResource method and providing a BMLResourceTypeWhizzmlSource resource that encodes the WhizzML source code:

        BMLMinimalResource* resource =
        [[BMLMinimalResource alloc] initWithName:
         _model.viewModel.currentWorkflowResource.name
                                            type:BMLResourceTypeWhizzmlSource
                                            uuid:@""
                                      definition:@{}];
        NSDictionary* dict = @{ @"source_code" : @"My source code here",
                                @"description" : @"My first WhizzML script",
                                @"inputs" : @[@{@"name" : @"inDataset", @"type" : @"dataset-id"}],
                                @"tags" : @[@"tag1", @"tag2"] };
    
        [[BMLAPIConnector newConnector]
         createResource:BMLResourceTypeWhizzmlScript
         name:@"My first WhizzML Script"
         options:dict
         from:resource
         completion:^(id<BMLResource> resource, NSError* error) {
    
             if (resource) {
                // execute script passed in resource
             } else {
                // handle error
             }
         }];
    

    Creating WhizzML scripts yourself is not the only way to take advantage of our new workflow automation DSL. Indeed, you can browse our WhizzML script Gallery and find a growing collection of scripts to solve recurrent machine learning tasks such as removing anomalies from a dataset, identifying a dataset’s best features, doing cross-validation, and many more. Once you have found what you are looking for, you can clone that script (many are even free!) to your account for use from your Objective-C program.

    Once you have created or cloned your script from the gallery, you can execute it very easily:

    [connector createResource:BMLResourceTypeWhizzmlExecution
                                  name:@"New Execution"
                               options:@{ @"inputs" : @[@[@"inDataset", @"dataset/573d9b147e0a8d70da01a0b5"]] }
                                  from:myScript
                            completion:^(id<BMLResource> resource, NSError* error) {</pre>
    if (resource) {
                // execute script passed in resource
             } else {
                // handle error
             }
    }];
    

    Read a thorough description of WhizzML and how you can use WhizzML scripts, libraries and executions in our REST API documentation! A great resource to learn about the language is our series of training videos.

    Local algorithms

    The most exciting part of BigML’s SDK for Objective-C is surely its support for a collection of the most widely used ML algorithms such as model prediction, clustering, anomaly detection etc. What is even more exciting is that the family of algorithms that BigML’s SDK for Objective-C supports is constantly growing!

    As an example, say that you have a model in your BigML account and that you want to use it to make a prediction based on some set of data that you have got. This is a two step process:

    • Retrieve the model from your account, as shown above, with getResource.
    • Use BigML’s SDK for Objective-C to calculate a prediction locally.

    The second step can be executed inside of the completion block that you pass to getResource. This could look like the following:

    [connector getResource:BMLResourceTypeModel
                         uuid:resourceUUID
                   completion:^(id resource, NSError* error) {
    
                           if (error == nil) {
                               NSDictionary* prediction =
            [BMLLocalPredictions localPredictionWithJSONModelSync:resource.jsonDefinition
                                                        arguments:@{ @"sepal length": @(6.02),
                                                 @"sepal width": @(3.15),
                                                 @"petal width": @(1.51),
                                                 @"petal length": @(4.07) }
                                                          options:nil];
                           } else {
                              //-- handle error
                           }
    }];
    

    The prediction object returned is a dictionary containing the value of the prediction and its confidence. In similar ways, you can calculate the nearest centroid, or do anomaly scoring.

    Practical Info

    The BigML SDK for Objective-C is compatible with Objective-C 2.0 and later. You can fork BigML’s SDK for Objective-C from BigML’s GitHub account and send us your PRs. As always, let us know what you think about it and how we can improve it to better suit your requirements!

One comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s