MPSCNN Weight Ordering

The Metal Performance Shader framework provides support for building your own Convolutional Neural Nets. When creating for instance an MSPCNNConvolution it requires a 4D weight tensor as init parameter that is represented as a 1D float pointer.

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

The documentation has this to say about the 4D tensor

The layout of the filter weight is arranged so that it can be reinterpreted as a 4D tensor (array) weight[outputChannels][kernelHeight][kernelWidth][inputChannels/groups]

Unfortunately that information doesn't really tell me how to arrange a 4D array into a one dimensional Float pointer.

I tried ordering the weights like the BNNS counterpart requires it, but without luck.

How do I properly represent the 4D tensor (array) as a 1D Float pointer (array)?

PS: I tried arranging it like a C array and getting the pointer to the flat array, but it didn't work.

UPDATE

@RhythmicFistman: That's how I stored it in a plain array, which I can convert to a UsafePointer<Float> (but doesn't work):

var output = Array<Float>(repeating: 0, count: weights.count)

for o in 0..<outputChannels {
    for ky in 0..<kernelHeight {
        for kx in 0..<kernelWidth {
            for i in 0..<inputChannels {
                let offset = ((o * kernelHeight + ky) * kernelWidth + kx) * inputChannels + i
                output[offset] = ...
            }
        }
    }
}

Ok so I figured it out. Here are the 2 python functions I use to reform my convolutions and fully connected matrices

# shape required for MPSCNN [oC kH kW iC]
# tensorflow order is [kH kW iC oC]
def convshape(a):
    a = np.swapaxes(a, 2, 3)
    a = np.swapaxes(a, 1, 2)
    a = np.swapaxes(a, 0, 1)
    return a

# fully connected only requires a x/y swap
def fullshape(a):
    a = np.swapaxes(a, 0, 1)
    return a

MPSCNN Weight Ordering, I tried ordering the weights like the BNNS counterpart requires it, but without luck. How do I properly represent the 4D tensor (array) as a 1D Float pointer  Generally speaking, the MPSCNNConvolution class takes weights in the order weight[outputChannels][kernelHeight][kernelWidth][inputChannels/groups] and this information is in the header file MPSCNN.h. In the sample project, MNIST_Full_LayerNN uses SlimMPSCNNFullyConnected to instantiate the MPSCNNConvolution kernel (see MPSCNNConvolution's init).

This is something I recently had to do for Caffe weights, so I can provide the Swift implementation for how I reordered those. The following function takes in a Float array of Caffe weights for a convolution (in [c_o][c_i][h][w] order) and reorders those to what Metal expects ([c_o][h][w][c_i] order):

public func convertCaffeWeightsToMPS(_ weights:[Float], kernelSize:(width:Int, height:Int), inputChannels:Int, outputChannels:Int, groups:Int) -> [Float] {

    var weightArray:[Float] = Array(repeating:0.0, count:weights.count)
    var outputIndex = 0

    let groupedInputChannels = inputChannels / groups
    let outputChannelWidth = groupedInputChannels * kernelSize.width * kernelSize.height

    // MPS ordering: [c_o][h][w][c_i]
    for outputChannel in 0..<outputChannels {
        for heightInKernel in 0..<kernelSize.height {
            for widthInKernel in 0..<kernelSize.width {
                for inputChannel in 0..<groupedInputChannels {
                    // Caffe ordering: [c_o][c_i][h][w]
                    let calculatedIndex = outputChannel * outputChannelWidth + inputChannel * kernelSize.width * kernelSize.height + heightInKernel * kernelSize.width + widthInKernel
                    weightArray[outputIndex] = weights[calculatedIndex]
                    outputIndex += 1
                }
            }
        }
    }

    return weightArray
}

Based on my layer visualization, this seems to generate the correct convolution results (matching those produced by Caffe). I believe it also properly takes grouping into account, but I need to verify that.

Tensorflow has a different ordering than Caffe, but you should be able to change the math in the inner part of the loop to account for that.

Model format of MPSCNN on iOS (Metal Performance Shaders), Weight Ordering. Although any file format can be used for the parameter files, there is a rule for the content. Let's look at the initializer of MPSCNNConvolution  For ordinary convolution in MPSCNN, weight format is [outputChannel][kernelHeight][kernelWidth][inputChannel] For depthwise convolution, weight format is [kernelHeight][kernelWidth][featureChannels] The trained mobileNet model is 16.9M, which is pretty small.

The documentation here assumes some expertise in C. In that context, a[x][y][z] is typically collapsed into a 1-d array when x, y and z are constants known at compile time. When this happens, the z component varies most quickly, followed by y, followed by x -- outside in.

If we have a[2][2][2], it is collapsed to 1D as:

{ a[0][0][0], a[0][0][1], a[0][1][0], a[0][1][1], 
  a[1][0][0], a[1][0][1], a[1][1][0], a[1][1][1] }

pytorch/mpscnn.mm at master · pytorch/pytorch · GitHub, pytorch/caffe2/mobile/contrib/ios/mpscnn/mpscnn.mm @property float* weights​_; buffer, we will need to use the same command buffer in order to use the. An easy way to keep your order low on SmartPoints is to fill it up with ZeroPoint veggies – something like a salad or a sandwich filled with vegetables. Add-ons like dressings and sauces will bring up your SmartPoints total, so you can reference the table below – or just search for the menu item in your WW App – to check their values.

I think tensorflow already has a convenient method for such task:

tf.transpose(aWeightTensor, perm=[3, 0, 1, 2])

Full documentation: https://www.tensorflow.org/api_docs/python/tf/transpose

Revo-Future/MobileNet-iOS: MobileNet implementation on , For ordinary convolution in MPSCNN, weight format is https://stackoverflow.​com/questions/40522224/mpscnn-weight-ordering · https://github.com/hollance/  Nutrisystem A La Carte simply means that items can be ordered individually. Visit our A La Carte section to place your order today. More weight loss FAQs. Posts related to this FAQ: Diet & Nutrition. 10 Ways to Boost a Slowing Metabolism. Diet & Nutrition. 11 Cauliflower Recipes So Good You’ll Forget You’re Eating Veggies. Diet & Nutrition.

Hot questions for Using Neural networks in ios, MPSCNN Weight Ordering. Question: The Metal var output = Array<Float>(​repeating: 0, count: weights.count) for o in 0..<outputChannels { for ky in 0. Browse this selection of weight sets online today at DICK'S Sporting Goods. Shop top brands to find the weight set you need to complete your home gym. Getting fit starts at DICK'S. Support your 2020 fitness goals with the latest gear and deals on fitness and exercise equipment .

Forge: neural network toolkit for Metal, Apple's MPSCNN framework is great for creating really fast deep learning Because Forge uses this indirect mechanism for loading weights and running your neural network will be a few orders of magnitude slower than  WW Gift of Health Set. Body Analysis Bluetooth Scale by Conair. Insulated Lunch Tote. 20oz Hydration Bottle w/ Silicone Carrying Handle & Screw-Top Lid (Silver) Black and White Baked Protein Bar. Chocolate Protein Booster. Vanilla Protein Booster. Bala Weighted Bangles. Chocolate Snack Bar Three Pack.

Brad Larson, MPSCNN Weight Ordering. The Metal Performance Shader framework provides support for building your own Convolutional Neural Nets. When creating for  The WW Logo, Wellness that Works, SmartPoints, FitPoints, Points and WW Freestyle are trademarks of WW International, Inc. © 2020 WW International, Inc.

Comments
  • can you show how you made the 4D to 1D attempt? barring using the wrong pointer, I think the only other thing that can go wrong is the order of the indices.
  • @RhythmicFistman Updated the question, the problem is not even Apples OWN example project (with their own trained weights) works correctly. So how am I supposed to know whats even wrong... my data or their implementation.
  • Which Apple sample are you referring to? Both MetalImageRecognition and MPSCNNHelloWorld seem to work for me with Xcode 8.2 beta and iOS 10.2 beta.
  • @warrenm try to run the deep net on the MNIST set in MPSCNNHelloWorld (toggle the button at the bottom to use deep net and start the test run on the mnist set). It will result in 7 or 8% accuracy which cant be correct.
  • See example of tf.transpose here: mattrajca.com/2016/11/26/…