Applications can utilize CoreML for many different purposes. One of these purposes is text analysis. You can use a trained model to detect whether a particular piece of text has a positive or negative sentiment. To implement a feature like this, you can use a trained and converted CoreML model.
The code bundle for this chapter includes a project named TextAnalyzer. If you open the start version of this project, you'll find a project that has an implementation of a simple layout along with a button that is hooked up to an @IBAction, named analyze(). The project folder also contains a file called SentimentPolarity.mlmodel. This file is a trained CoreML model that analyzes the sentiment associated with a certain text. Drag this file into Xcode to add the CoreML model to your project.
After adding the model to your project, you can click it in the Project Navigator to see more information about the model, as illustrated in the following screenshot:
You can see that this model is provided by Vadym Markov under the MIT license. In the bottom section, you can find out which inputs and outputs you can expect this model to work with. In this case, the input is a dictionary of the [String: Double] type. This means that we should feed this model a dictionary of word counts. If you add this model to Xcode, the center section that lists the Model Class might notify you that the model isn't part of any targets yet. If this is the case, fix it as you have done previously, by adding this model to your app target in the Utilities sidebar on the right side of the window.
Now that your model is implemented, it's time to take it for a spin. First, implement a method that extracts the word count from any given string. You can implement this using the NLTokenizer object from the new NaturalLanguage framework. NLTokenizer is a text analysis class that is used to split a string into words, sentences, paragraphs, or even whole documents. In this example, the tokenizer is set up to detect individual words. Implement the word count method as follows:
func getWordCounts(from string: String) -> [String: Int] { let tokenizer = NLTokenizer(unit: .word) tokenizer.string = string var wordCount = [String: Int]() tokenizer.enumerateTokens(in: string.startIndex..<string.endIndex) { range, attributes in let word = String(string[range]) wordCount[word] = (wordCount[word] ?? 0) + 1 return true } return wordCount }
The previous code iterates over all the words that the tokenizer has recognized, and stores it in a dictionary of the [String: Double] type. You might wonder why a Double type is used for the word count, rather than an Int type, since the word counts won't have to deal with decimals. This is true, but the SentimentPolarity model requires its input to be a dictionary of the [String: Double] type, so you must prepare the data accordingly.
Now that you have the code to prepare the input data for the SentimentPolarity model, let's see how you can use this model to analyze the user's input. Add the following implementation for the analyze() method:
@IBAction func analyze() { let wordCount = getWordCounts(from: textView.text) let model = SentimentPolarity() guard let prediction = try? model.prediction(input: wordCount) else { return } let alert = UIAlertController(title: nil, message: "Your text is rated: \(prediction.classLabel)", preferredStyle: .alert) let okayAction = UIAlertAction(title: "Okay", style: .default, handler: nil) alert.addAction(okayAction) present(alert, animated: true, completion: nil) }
You might be surprised that this method is so short, but that's how simple CoreML is! First, we retrieve the wordCount using the method we implemented earlier. Then, an instance of the CoreML model is created. When you added the SentimentPolarity model to the app target, Xcode generated a class interface that abstracted away all complexities involving the model. Because the model is now a simple class, you can obtain a prediction for the sentiment of the text by calling prediction(input:) on the model instance.
The prediction method returns an object that contains the processed prediction in the classLabel property, as well as an overview of all available predictions and how certain the model is about each option in the classProbability property. You can use this property if you want to be a bit more transparent to the user about the different options that the model suggested and how certain it was about these options.
In the last section of this chapter, you will learn how you can use CreateML to train your own natural language model to analyze texts that use domain-specific language relevant to your own app.
Using CoreML to perform text analysis was quite simple. Now let's see how you can use computer vision together with CoreML to determine the type of object that exists in a particular picture.