Xcode Reset
1 | default delete com.apple.Xcode |
UI
CocoaPods
1 | pod init |
1 | # Uncomment the next line to define a global platform for your project |
model
trace_model.py
1 | import torch |
模型
1 | wget -c https://download.pytorch.org/models/mobilenet_v2-b0353104.pth |
拖动生成的 model.pt
到 iOS
项目。
拍照/相册
Info.plist
1 | <key>NSCameraUsageDescription</key> |
拍照/相册选择图片
要在 iOS
上开始使用 PyTorch
,我们建议您浏览以下HelloWorld。
HELLO WORLD示例快速入门
HelloWorld是一个简单的图像分类应用程序,演示了如何在iOS上使用PyTorch C ++库。该代码用Swift编写,并使用Objective-C作为桥梁。
模型准备
让我们从模型准备开始。如果您熟悉PyTorch,您可能应该已经知道如何训练和保存模型。如果您没有,我们将使用预先训练的图像分类模型-MobileNet v2,该模型已经包装在TorchVision中。要安装它,请运行以下命令。
我们强烈建议您遵循Pytorch Github页面在本地计算机上设置Python开发环境。
1 | pip install torchvision |
成功安装TorchVision后,让我们导航到HelloWorld文件夹并运行trace_model.py
。该脚本包含跟踪和保存可在移动设备上运行的Torchscript模型的代码。
1 | python trace_model.py |
如果一切正常,我们应该model.pt
在HelloWorld
文件夹中生成模型。现在将模型文件复制到我们的应用程序文件夹中HelloWorld/model
。
要了解有关TorchScript的更多详细信息,请访问pytorch.org上的教程。
通过Cocoapods安装LibTorch
PyTorch C++库在Cocoapods中可用,可以将其集成到我们的项目中,只需运行即可
1 | pod install |
现在是时候HelloWorld.xcworkspace
在XCode中打开,选择一个iOS模拟器并启动它(cmd + R)。如果一切正常,我们应该在模拟器屏幕上看到狼的图片以及预测结果。
我已经加了一张新图片。
代码演练
在这一部分中,我们将逐步介绍代码。
图片载入
让我们从图像加载开始。
1 | let image = UIImage(named: "image.jpg")! |
我们首先从包中加载图像,然后将其调整为224x224。然后,我们将此normalized()
类别方法称为归一化像素缓冲区。让我们仔细看看下面的代码。
1 | var normalizedBuffer: [Float32] = [Float32](repeating: 0, count: w * h * 3) |
乍一看,这些代码可能看起来很奇怪,但是一旦我们理解了模型,它就会变得有意义。输入数据是形状为(3 x H x W)的3通道RGB图像,其中H和W至少应为224。图像必须加载到的范围内[0, 1]
,然后使用mean = [0.485, 0.456, 0.406]
和进行归一化std = [0.229, 0.224, 0.225]
。
TorchScript模块
现在我们已经对输入数据进行了预处理,并且有了预先训练的TorchScript模型,下一步就是使用它们来运行谓词。为此,我们首先将模型加载到应用程序中。
1 | private lazy var module: TorchModule = { |
请注意,TorchModule
该类是的Objective-C包装器torch::jit::script::Module
。
1 | torch::jit::script::Module module = torch::jit::load(filePath.UTF8String); |
由于Swift无法直接与C ++对话,因此我们必须使用Objective-C类作为桥梁,或者为C ++库创建C包装器。出于演示目的,我们将把所有内容包装在这个Objective-C类中。但是,我们正在努力为PyTorch提供Swift / Objective-C API包装器。敬请关注!
运行推断
现在该进行推断并获取结果了。
1 | guard let outputs = module.predict(image: UnsafeMutableRawPointer(&pixelBuffer)) else { |
同样,该predict
方法只是一个Objective-C包装器。在后台,它调用C ++ forward
函数。让我们看一下它是如何实现的。
1 | at::Tensor tensor = torch::from_blob(imageBuffer, {1, 3, 224, 224}, at::kFloat); |
C ++函数torch::from_blob
将从像素缓冲区创建输入张量。请注意,张量的形状{1,3,224,224}
代表NxCxWxH
我们在上一节中讨论的形状。
1 | torch::autograd::AutoGradMode guard(false); |
以上两行告诉PyTorch引擎仅进行推断。这是因为默认情况下,PyTorch内置了对进行自动分化的支持,这也称为autograd。由于我们不进行手机培训,因此我们可以禁用自动毕业模式。
最后,我们可以调用此forward
函数以获取输出张量并将其转换为float
缓冲区。
1 | auto outputTensor = _impl.forward({tensor}).toTensor(); |
收集结果
输出张量是形状为1x1000的一维浮点数组,其中每个值表示从图像预测标签的置信度。下面的代码对数组进行排序,并检索前三个结果。
1 | let zippedResults = zip(labels.indices, outputs) |
PyTorch演示应用
对于更复杂的用例,我们建议您检查PyTorch演示应用程序。该演示应用程序包含两个展示柜。一个运行量化模型的相机应用程序,可以实时预测来自设备后置相机的图像。还有一个基于文本的应用程序,它使用文本分类模型来根据输入字符串预测主题。
从源代码构建PYTORCH IOS库
要跟踪iOS的最新更新,您可以从源代码构建PyTorch iOS库。
1 | git clone --recursive https://github.com/pytorch/pytorch |
确保已
cmake
在本地计算机上正确安装了Python。我们建议您遵循Pytorch Github页面来设置Python开发环境
为iOS模拟器构建LibTorch
打开终端并导航到PyTorch根目录。运行以下命令
1 | BUILD_PYTORCH_MOBILE=1 IOS_PLATFORM=SIMULATOR ./scripts/build_ios.sh |
构建成功后,所有静态库和头文件将在 build_ios/install
为arm64设备构建LibTorch
打开终端并导航到PyTorch根目录。运行以下命令
1 | BUILD_PYTORCH_MOBILE=1 IOS_ARCH=arm64 ./scripts/build_ios.sh |
构建成功后,所有静态库和头文件将在 build_ios/install
XCode设置
在XCode中打开您的项目,将所有静态库以及头文件复制到您的项目中。导航到项目设置,将“ Header Search Paths ”值设置为刚复制的头文件的路径。
在构建设置中,搜索其他链接器标志。在下面添加自定义链接器标志
1 | -force_load $(PROJECT_DIR)/${path-to-libtorch.a} |
最后,通过选择“构建设置”,搜索“ 启用位码”,然后将值设置为No,为目标禁用位码。
API文件
当前,iOS框架直接使用Pytorch C ++前端API。可以在这里找到C ++文档。要了解更多信息,我们建议在PyTorch网页上浏览C ++前端教程。同时,我们正在努力为PyTorch提供Swift / Objective-C API包装器。
定制版
从1.4.0开始,PyTorch支持自定义构建。现在,您可以构建PyTorch库,其中仅包含模型所需的运算符。为此,请按照以下步骤操作
1.确认您的PyTorch版本为1.4.0或更高版本。您可以通过检查的值来实现torch.__version__
。
2.要转储模型中的运算符,请说MobileNetV2
运行以下几行Python代码:
1 | import torch, yaml |
在上面的代码段中,您首先需要加载ScriptModule。然后,使用export_opnames
来返回ScriptModule及其子模块的运算符名称的列表。最后,将结果保存在yaml文件中。
3.要使用准备好的yaml运算符列表在本地运行iOS构建脚本,请将从最后一步生成的yaml文件传递到环境变量中SELECTED_OP_LIST
。同样在自变量中,指定BUILD_PYTORCH_MOBILE=1
以及平台/架构类型。以arm64构建为例,命令应为:
1 | SELECTED_OP_LIST=MobileNetV2.yaml BUILD_PYTORCH_MOBILE=1 IOS_ARCH=arm64 ./scripts/build_ios.sh |
4.构建成功后,您可以按照上面的XCode Setup部分将结果库集成到项目中。
5.最后一步是在运行之前添加一行C ++代码forward
。这是因为默认情况下,JIT将对运算符进行一些优化(例如,融合),这可能会破坏我们从模型中转储的操作的一致性。
1 | torch::jit::GraphOptimizerEnabledGuard guard(false); |
问题与贡献
如果您有任何疑问或想为PyTorch做出贡献,请随时提出问题或打开请求请求以取得联系。
PyTorch iOS 官方:
https://github.com/pytorch/ios-demo-app
带拍照和相册的源码: