准备工作
- 首先得有一个Xcode以及一个简单的添加了CoreMLFramework的工程;
- 下载模型,如官方推荐的MobileNetV2
- 将模型导入到工程中,并添加到你的编译项目中
- 双击打开,会看到这么一个页面:
5. 然后点击
就可以进入到模型自动生成的头文件中:
模型分析
1.关键词@interface
通过搜索关键词interface,我们可以得到三个结果:
@interface MobileNetV2Input : NSObject
@interface MobileNetV2Output : NSObject
@interface MobileNetV2 : NSObject
其中MobileNetV2Input是模型输入的类,Output是输出类,它们都继承自NSObject,最后的MobileNetV2是模型类。
2.MLFeatureProvider
这个协议定义了一个属性featureNames以及一个从某个featureName获取featureValue的方法featureValueForName,需要注意的是,这里的featureNames是一个NSSet!这一点非常重要,涉及到CoreML多输出的实现方法。
3.MobileNetV2Input
对输入而言,最重要的就是构造和初始化,这里CoreML提供了很多初始化的方法,从最简的传入CVPixelBufferRef到其他各种图像URL等方法,目的就是要完成对各个属性的赋值。因为我们这个模型输入只要一个图像,所以就只需要对image赋值即可。
4.MobileNetV2Output
前面已经说过Input只需要给各个属性值赋值,Output则需要能够表示模型的输出,并提供获取模型输出的方法,即模型输出的表示和获取方法。
5.MobileNetV2
如注释所说,这个类主要负责模型的加载和计算过程。
initWithMLModel:(MLModel *)model
initWithConfiguration:(MLModelConfiguration *)configuration error:(NSError * _Nullable __autoreleasing * _Nullable)error
initWithContentsOfURL:(NSURL *)modelURL error:(NSError * _Nullable __autoreleasing * _Nullable)error
initWithContentsOfURL:(NSURL *)modelURL configuration:(MLModelConfiguration *)configuration error:(NSError * _Nullable __autoreleasing * _Nullable)error
loadWithConfiguration:(MLModelConfiguration *)configuration completionHandler:(void (^)(MobileNetV2 * _Nullable model, NSError * _Nullable error))handler
loadContentsOfURL(NSURL *)modelURL configuration:(MLModelConfiguration *)configuration completionHandler:(void (^)(MobileNetV2 * _Nullable model, NSError * _Nullable error))handler
这些函数的目的都是初始化一个MobileNetV2实例,从函数名和参数我们看出,CoreML提供了多种灵活的初始化方法,来应对不同的使用场景。可以直接从一个MLModel类创建一个新的MobileNetV2实例,也可以从.mlmodelc的URL来加载,还可以通过MLModelConfiguration来决定是否要对模型进行特殊配置,最后两个load开头的函数是异步加载。
predictionFromFeatures:(MobileNetV2Input *)input error:(NSError * _Nullable __autoreleasing * _Nullable)error
predictionFromFeatures:(MobileNetV2Input *)input options:(MLPredictionOptions *)options error:(NSError * _Nullable __autoreleasing * _Nullable)error
predictionFromImage:(CVPixelBufferRef)image error:(NSError * _Nullable __autoreleasing * _Nullable)error
predictionsFromInputs:(NSArray<MobileNetV2Input*> *)inputArray options:(MLPredictionOptions *)options error:(NSError * _Nullable __autoreleasing * _Nullable)error
这四个函数都是用来完成预测,得到模型预测结果,只不过传入的参数不一样。前面两个的主要参数都是MobileNetV2Input,区别是是否使用MLPredictionOptions来做一些预测配置;predictionsFromInputs的主要参数也是MobileNetV2Input,只不过是多个MobileNetV2Input组成的NSArray,来适配多输入场景。predictionFromImage可能是我们最常用的一个方法,输入是一个CVPixelBufferRef,根据模型其格式也会做相应的调整,比如MobileNetV2就是:
color (kCVPixelFormatType_32BGRA) image buffer, 224 pixels wide by 224 pixels high
6.MLModelConfiguration
模型初始化时传入的配置类,最重要的就是这个computeUnits属性,可以设置只使用CPU、CPU和GPU以及所有设备三个选项:
MLComputeUnitsCPUOnly = 0
使用这个选项,则模型只能使用CPU来进行计算。
MLComputeUnitsCPUAndGPU = 1
使用这个选项,则模型可以使用CPU和GPU,但是不包括neural engine。
MLComputeUnitsAll = 2
使用这个选项,系统会自动选择计算设备,包括neural engine。
7.MLPredictionOptions
模型预测时的配置,最重要的是可以通过usesCPUOnly属性来控制是否仅仅使用CPU来进行推断,实测有效!
8. MLPredictionOptions 和 MLModelConfiguration的关系
根据目前的测试结果,这两个config都是有效的,最大的区别在于,MLPredictionOptions是Core ML1.0的设计,且属性值usesCPUOnly默认是False,即Core ML1.0默认使用GPU来进行推断;而MLPredictionOptions是2.0新增的,在模型初始化的时候就传入参数来确定计算设备,更重要的是,现在可以控制除了CPU和GPU之外的neural engine,当设置为ALL时,系统会自动选择使用最佳设备。针对这两种功能相似的结构体,有一个判断原则,功能更多的一定是后来出现的!