迁移MPSCNNFully连接到MPSCNNConvolutionDataSource

时间:2019-03-19 16:31:36

标签: ios conv-neural-network metal-performance-shaders

我正在从弃用的位置迁移神经网络:

init(device: MTLDevice, convolutionDescriptor: MPSCNNConvolutionDescriptor, kernelWeights: UnsafePointer<Float>, biasTerms: UnsafePointer<Float>?, flags: MPSCNNConvolutionFlags)

init(device: MTLDevice, weights: MPSCNNConvolutionDataSource)

我已经实现了MPSCNNConvolutionDataSource,它经过了很好的调试,可用于除一层之外的所有层。仅出于测试目的,我在这里将数据源与MPSCNNFullyConnected弃用的init()一起使用,以确保数据源正确实现。我知道这不是它的预期用途,但是我希望将相同的数据放入两个MPSCNNFullyConnected()构造函数中。运行以下代码,NN正常工作。

  /* This code runs as intended */
  let datasource = DataSource("test", 8, 8, 224, 1024, .reLU)
  _ = datasource.load()
    let layer = MPSCNNFullyConnected(device: device,
                                   convolutionDescriptor: datasource.descriptor(),
                                   kernelWeights: UnsafeMutablePointer<Float>(mutating: datasource.weights().assumingMemoryBound(to: Float.self)),
                                   biasTerms: datasource.biasTerms(),
                                   flags: .none)

当我使用新的init()实例化完全连接的层时,网络将失败。以下代码可以运行,但是NN无法正常工作。

  /* This code does run, but the layer does NOT output the correct values */
  let datasource = DataSource("test", 8, 8, 224, 1024, .reLU)
  let layer = MPSCNNFullyConnected(device: device, weights: datasource)

任何建议为何两个电话都不相同?

2 个答案:

答案 0 :(得分:1)

最后我解决了。两次调用之间的区别在于,如果使用,则必须显式设置layer.offset:

import json
from datetime import datetime, timedelta

@monitors.name("Item count dropped")
class ItemCountDroppedMonitor(Monitor):
    @monitors.name("Item count dropped since previous run")
    def test_item_count_dropped(self):
        yesterday = (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d')
        last_day_item_path = f'/home/user/scraped_items/{yesterday}.json'
        minimum_threshold = 0.5  # 50%
        items_extracted_now = getattr(self.data.stats, "item_scraped_count", 0)
        items_extracted_last_run = json.loads(open(last_day_item_path).read())
        items_extracted_last_run = len(items_extracted_last_run)
        diff = items_extracted_last_run - items_extracted_now
        self.assertFalse(
            diff >= (items_extracted_last_run * minimum_threshold),
            msg="Extracted less items than expected"
        )

已弃用的呼叫:

init(device: MTLDevice, weights: MPSCNNConvolutionDataSource) 

似乎暗中做了。

此代码有效:

init(device: MTLDevice, convolutionDescriptor: MPSCNNConvolutionDescriptor, kernelWeights: UnsafePointer<Float>, biasTerms: UnsafePointer<Float>?, flags: MPSCNNConvolutionFlags)

我猜这没有记载!感谢苹果进行为期三天的核心调试。

答案 1 :(得分:0)

有关大多数Metal的Apple文档似乎已经消失,但是如果您查看头文件(或在Xcode中按住Alt键并单击,然后跳到定义),它仍然存在。

权重的顺序未更改。您仍然可以像以前一样加载它们。

有关如何编写此类数据源对象的示例,请查看以下存储库:https://github.com/hollance/YOLO-CoreML-MPSNNGraph/blob/2ba3435bfacb8d2f792b95887fc9df85d7048ae1/TinyYOLO-NNGraph/TinyYOLO-NNGraph/YOLO.swift#L254