使用Core ML,Swift和Neural Engine在iOS设备上实现机器学习

哈伯,你好!预期高级课程“ iOS Developer”的开始,我们通常会为您准备有用材料的翻译。










介绍



Core ML是Apple在WWDC 2017上发布的机器学习库。



它使iOS开发人员可以使用神经引擎使用高级本地机器学习模型向其应用程序添加实时个性化体验。



A11仿生芯片评论





A11仿生碎屑填充

晶体管:43亿个

内核:6个ARM内核(64位)-2个高频(2.4 GHz)-4个低功耗

GPU:3个

神经引擎-每秒600次基本操作


2017年9月12日,苹果向全球推出了带有神经引擎的A11仿生芯片。这种神经网络硬件每秒可以执行多达600个基本操作(BOPS),并用于FaceID,Animoji和其他机器学习任务。开发人员可以使用Core ML API使用神经引擎。



Core ML通过利用CPU,GPU和Neural Engine资源来优化设备上的性能,从而最大程度地减少内存和功耗。



在用户设备上本地运行模型消除了对网络连接的需求,这有助于保持用户数据的私密性并提高应用程序的响应速度。


核心ML是该领域的框架和功能的基础。Core ML支持用于图像分析的视觉,用于文字处理的自然语言,用于语音到文本的语音以及用于识别音频中声音的声音分析。





核心ML API

我们可以轻松地自动完成构建机器学习模型的任务,包括使用Playground训练和测试模型,以及将结果模型文件集成到我们的iOS项目中。



新手提示:高亮显示分类任务的单独标签。






核心ML通用框图



好的。我们要创造什么?



在本教程中,我将向您展示如何使用Core ML构建图像分类器模型,该模型可以对Orange和Strawberry图像进行分类,并将该模型添加到我们的iOS应用程序中。





图像分类器模型。



新手提示:图像分类是指有监督的学习问题,其中我们使用标签数据(在我们的情况下,标签是图像的名称)。








最低要求:



  • 懂Swift语言
  • iOS开发基础
  • 了解面向对象的编程概念




应用程序:



  • X代码10或更高版本
  • iOS SDK 11.0以上
  • macOS 10.13以上




数据采集







收集图像分类数据时,请遵循Apple准则。



  • 10 — , .
  • , .
  • , Create ML UI’s Augmentation: Crop, Rotate, Blur, Expose, Noise Flip.
  • : , . , .
  • , , .
  • , , -.




收集数据集后,将其分为训练和测试集,然后将它们放置在适当的文件夹中。







重要说明:确保将图像分发到测试文件夹中的相应文件夹。因为文件夹名称用作我们图像的标签。






在我们的例子中,我们有两个文件夹,每个文件夹包含相应的图像。



模型制作







不要恐慌!苹果通过自动实现里程碑使这一过程变得更加容易。



使用Core ML,您可以使用已经训练有素的模型对输入数据进行分类,或者创建自己的模型。 Vision框架已经与Core ML一起使用,以将分类模型应用于图像并对其进行预处理,并使机器学习任务更简单,更强大。



只需按照以下步骤。



步骤1:打开您的X代码。

第2步:创建一个干净的Swift游乐场。

步骤3:删除默认的生成代码,添加以下程序并运行playground



   import CreateMLUI //  
  
   let builder = MLImageClassifierBuilder() 
//  MLImageClassifierBuilder
 
   builder.showInLiveView() 
//   Xcode Model builder




说明:

在这里,我们打开Xcode提供的默认模型构建器的界面。



步骤4:将训练样本文件夹拖到训练区域。



将训练样本文件夹放在虚线指示的训练区域中。



新手提示:我们还可以通过单击教程区域中的向下箭头为模型提供任意名称。




步骤5:Xcode将自动处理图像并开始学习过程。默认情况下,需要10次迭代来训练模型,具体取决于Mac的特性和数据集的大小。您可以在Playground终端窗口中观看训练进度。





我正在等待模型训练中。



步骤6:完成训练后,您可以通过将Test文件夹拖放到测试区域中来测试模型。 Xcode将自动测试您的模型并显示结果。





如您所见,我们的模型已对图像进行了准确分类。



步骤7:保存您的模型。









集成到iOS应用程序中:



步骤1:打开您的X代码。

步骤2:创建一个Single Page iOS应用。

步骤3:打开项目导航器。

步骤4:将训练好的模型拖到项目导航器中。





将模型放置在项目导航器中。



步骤5:打开Main.storyboard并创建一个如下所示的简单界面,为各个视图添加IBOutlets和IBAction。





添加UIImageView,UIButtons和UILabels。



步骤6:打开文件ViewController.swift并添加以下代码作为扩展名。



  extension ViewController: UINavigationControllerDelegate, UIImagePickerControllerDelegate { 
 
 
       func getimage() { 
 
           let imagePicker = UIImagePickerController()
//  UIImagePickerController()
 
           imagePicker.delegate = self //  
 
           imagePicker.sourceType = .photoLibrary  //       
 
           imagePicker.allowsEditing = true  //   
 
           present(imagePicker, animated: true)  //  UIPickerView
 
       } 
 
       func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo : [UIImagePickerController.InfoKey: Any]) { 
 
           let fimage = info[.editedImage] as!UIImage 
//      .editedImage   info 
 
           //    UIImage
 
           fruitImageView.image = fimage  
//    UIImageView
 
           dismiss(animated: true, completion: nil)  //   ,    
 
       } 
 
       func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { 
 
           dismiss(animated: true, completion: nil)  
//     ,     
 
       } 
 
   } 




说明:在这里,我们为ViewController类创建一个扩展,并实现UINavigationControllerDelegate和UIImagePickerControllerDelegate以在用户单击PickImage UIButton时显示UIImagePickerView。确保设置委托上下文。







与在iOS应用程序中访问Core ML模型有关的步骤







步骤1:确保已导入以下库。



import CoreML 
 import Vision




步骤2:创建我们的Model Core ML类的实例。



let modelobj = ImageClassifier()




步骤3:要强制Core ML进行分类,我们必须首先形成一个类似于VNCoreMLRequest的请求(VN代表Vision)



var myrequest: VNCoreMLRequest? 
//  VNCoreMLRequest
 
myrequest = VNCoreMLRequest(model: fruitmodel, completionHandler: { (request, error) in    
//    
 
               //  ,     Core ML
 
               self.handleResult(request: request, error: error)
//  
 
                                                     })




步骤4:确保裁剪图像,使其与Core ML模型兼容。 步骤5:将以上代码放在返回请求对象的自定义函数中。



myrequest!.imageCropAndScaleOption = .centerCrop







 func mlrequest() - > VNCoreMLRequest { 
        var myrequest: VNCoreMLRequest ? 
            let modelobj = ImageClassifier() 
        do { 
            let fruitmodel = 
                try VNCoreMLModel( 
                    for: modelobj.model) 
 
           myrequest = VNCoreMLRequest(model: fruitmodel, completionHandler: {   
                (request, error) in self.handleResult(request: request, error: error) 
          
           }) 
 
       } catch { 
           print("Unable to create a request") 
 
       } 
 
       myrequest!.imageCropAndScaleOption = .centerCrop 
        return myrequest! 
    } 




步骤6:现在我们需要将UIImage转换为CIImage(CI:CoreImage),以便可以将其用作Core ML模型的输入。通过在构造函数中传递UIImage实例化CIImage可以轻松完成此操作。



guard  let ciImage = CIImage(image: image)  else { 
       return 
    } 




步骤7:现在,我们可以VNCoreMLRequest通过创建请求处理程序并传递来处理我们的请求ciImage



let handler = VNImageRequestHandler(ciImage: ciImage)




步骤8:可以通过调用方法perform()并将其作为参数传递来实现请求VNCoreMLRequest



DispatchQueue.global(qos: .userInitiated).async { 
       let handler = VNImageRequestHandler(ciImage: ciImage) 
       do { 
           try handler.perform([self.mlrequest()]) 
       } catch {  
           print("Failed to get the description")  
       }  
   } 




描述:DispatchQueue是一个对象,用于管理应用程序主(或后台)线程中顺序(或同时)执行任务。



步骤10:将以上代码放在自定义函数中,如下所示。



func excecuteRequest(image: UIImage) { 
 
            guard 
            let ciImage = CIImage(image: image) 
            else { 
                return 
            } 
            DispatchQueue.global(qos: .userInitiated).async { 
                let handler = VNImageRequestHandler(ciImage: ciImage) 
                do { 
                    try handler.perform([self.mlrequest()]) 
                } catch { 
                    print("Failed to get the description") 
                } 
            } 




步骤11:创建一个命名自定义函数handleResult()VNRequest函数错误对象和错误对象作为参数。完成时将调用此函数VNCoreMLRequest



func handleResult(request: VNRequest, error: Error ? ) { 
 
       if let classificationresult = request.results as ? [VNClassificationObservation] {//      VNClassificationObservation
 
           DispatchQueue.main.async { 
               self.fruitnamelbl.text = classificationresult.first!.identifier// UILabel          prperty
                print(classificationresult.first!.identifier)
            } 
        } 
        else { 
            print("Unable to get the results") 
        } 
    }  




注意DispatchQueue.main.async由于所有分类任务均在后台线程中执行,因此该方法用于使用UI线程或主线程来更新UIKit对象(在我们的示例中为UILabel)。








清单 ViewController.Swift





import UIKit 
    import CoreML 
    import Vision 
    class ViewController: UIViewController { 
        var name: String = "" 
        @IBOutlet weak 
        var fruitnamelbl: UILabel!@IBOutlet weak 
        var fruitImageView: UIImageView!override func viewDidLoad() { 
            super.viewDidLoad() 
            //       .  
        } 
        @IBAction func classifybtnclicked(_ sender: Any) { 
            excecuteRequest(image: fruitImageView.image!) 
        } 
        @IBAction func piclimage(_ sender: Any) { 
            getimage() 
        } 
        func mlrequest() - > VNCoreMLRequest { 
            var myrequest: VNCoreMLRequest ? 
                let modelobj = ImageClassifier() 
           do { 
                let fruitmodel = 
                    try VNCoreMLModel( 
                        for: modelobj.model) 
                myrequest = VNCoreMLRequest(model: fruitmodel, completionHandler: { 
                    (request, error) in self.handleResult(request: request, error: error) 
                }) 
            } catch { 
                print("Unable to create a request") 
            } 
            myrequest!.imageCropAndScaleOption = .centerCrop 
            return myrequest! 
        } 
        func excecuteRequest(image: UIImage) { 
            guard 
            let ciImage = CIImage(image: image) 
            else { 
                return 
            } 
            DispatchQueue.global(qos: .userInitiated).async { 
                let handler = VNImageRequestHandler(ciImage: ciImage) 
                do { 
                    try handler.perform([self.mlrequest()]) 
                } catch { 
                    print("Failed to get the description") 
                } 
            } 
        } 
        func handleResult(request: VNRequest, error: Error ? ) { 
            if let classificationresult = request.results as ? [VNClassificationObservation] { 
                DispatchQueue.main.async { 
                    self.fruitnamelbl.text = classificationresult.first!.identifier 
                    print(classificationresult.first!.identifier) 
                } 
            } 
            else { 
                print("Unable to get the results") 
            } 
        } 
    } 
    extension ViewController: UINavigationControllerDelegate, UIImagePickerControllerDelegate { 
        func getimage() { 
            let imagePicker = UIImagePickerController() 
            imagePicker.delegate = self 
            imagePicker.sourceType = .photoLibrary 
            imagePicker.allowsEditing = true 
            present(imagePicker, animated: true) 
        } 
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) { 
            let fimage = info[.editedImage] as!UIImage 
            fruitImageView.image = fimage 
            dismiss(animated: true, completion: nil) 
        } 
        func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { 
            dismiss(animated: true, completion: nil) 
        } 
    }




全部都准备好了!







现在启动您的模拟器并测试您的应用程序。



注意:确保在Simulator的照片库中有橙子和草莓的照片。






单击“选择图像”按钮





选择任何图像





单击“分类”按钮





选择另一个图像,然后单击“分类”



万岁:



您已使用Core ML创建了第一个iOS应用程序。



然而:






All Articles