Permalink
Show file tree
Hide file tree
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Adding MLCompute compute context to DC (#3279)
- Loading branch information
1 parent
dadfae5
commit 7b6b72a
Showing
7 changed files
with
562 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/* Copyright © 2020 Apple Inc. All rights reserved. | ||
* | ||
* Use of this source code is governed by a BSD-3-clause license that can | ||
* be found in the LICENSE.txt file or at | ||
* https://opensource.org/licenses/BSD-3-Clause | ||
*/ | ||
|
||
#import <MLCompute/MLCompute.h> | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
// Defines the parameters for the MLCompute-based implementation of the | ||
// Drawing Classifier model. | ||
API_AVAILABLE(macos(10.16)) | ||
@interface TCMLComputeDrawingClassifierDescriptor : NSObject | ||
|
||
// Defines the shape of the graph's input. | ||
@property(nonatomic) MLCTensor *inputTensor; | ||
|
||
// Defines the shape of the graph's ouput. | ||
@property(nonatomic) MLCTensor *outputTensor; | ||
|
||
// Controls the number of features in the output tensor, which should be equal | ||
// to the number of classes. | ||
@property(nonatomic) NSUInteger outputChannels; | ||
|
||
// Dictionary mapping layer names to weights. | ||
@property(nonatomic) NSDictionary<NSString *, MLCTensor *> *weights; | ||
|
||
@end | ||
|
||
API_AVAILABLE(macos(10.16)) | ||
@interface MLCGraph (TCMLComputeDrawingClassifier) | ||
|
||
+ (instancetype)tc_graphForDrawingClassifierDescriptor: | ||
(TCMLComputeDrawingClassifierDescriptor *)descriptor | ||
batchSize:(NSUInteger)batchSize; | ||
|
||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
/* Copyright © 2020 Apple Inc. All rights reserved. | ||
* | ||
* Use of this source code is governed by a BSD-3-clause license that can | ||
* be found in the LICENSE.txt file or at | ||
* https://opensource.org/licenses/BSD-3-Clause | ||
*/ | ||
|
||
#import <ml/neural_net/TCMLComputeDrawingClassifierDescriptor.h> | ||
|
||
#import <ml/neural_net/TCMLComputeUtil.h> | ||
|
||
@implementation TCMLComputeDrawingClassifierDescriptor | ||
|
||
- (BOOL)isComplete | ||
{ | ||
if (self.inputTensor == nil) return NO; | ||
if (self.outputChannels == 0) return NO; | ||
|
||
return YES; | ||
} | ||
|
||
- (MLCTensor *)addConvLayer:(NSUInteger)index | ||
outputChannels:(NSUInteger)outputChannels | ||
source:(MLCTensor *)source | ||
graph:(MLCGraph *)graph | ||
{ | ||
// Find the weights for this conv layer in our dictionary of parameters. | ||
NSString *biasKey = [NSString stringWithFormat:@"drawing_conv%lu_bias", (unsigned long)index]; | ||
NSString *weightKey = [NSString stringWithFormat:@"drawing_conv%lu_weight", (unsigned long)index]; | ||
MLCTensor *bias = self.weights[biasKey]; | ||
MLCTensor *weights = self.weights[weightKey]; | ||
|
||
// Configure the convolution descriptor. | ||
NSUInteger inputChannels = | ||
weights.descriptor.shape[TCMLComputeTensorSizeChannels].unsignedIntegerValue / outputChannels; | ||
NSUInteger kernelHeight = | ||
weights.descriptor.shape[TCMLComputeTensorSizeHeight].unsignedIntegerValue; | ||
NSUInteger kernelWidth = | ||
weights.descriptor.shape[TCMLComputeTensorSizeWidth].unsignedIntegerValue; | ||
// Configure the convolution descriptor. | ||
MLCConvolutionDescriptor *conv_desc = | ||
[MLCConvolutionDescriptor descriptorWithKernelSizes:@[ @(kernelHeight), @(kernelWidth) ] | ||
inputFeatureChannelCount:inputChannels | ||
outputFeatureChannelCount:outputChannels | ||
strides:@[ @1, @1 ] | ||
paddingPolicy:MLCPaddingPolicySame | ||
paddingSizes:nil]; | ||
|
||
MLCConvolutionLayer *conv = [MLCConvolutionLayer layerWithWeights:weights | ||
biases:bias | ||
descriptor:conv_desc]; | ||
MLCTensor *convTensor = [graph nodeWithLayer:conv source:source]; | ||
|
||
MLCLayer *relu1 = [MLCActivationLayer | ||
layerWithDescriptor:[MLCActivationDescriptor descriptorWithType:MLCActivationTypeReLU | ||
a:0.0f]]; | ||
MLCTensor *reluTensor = [graph nodeWithLayer:relu1 source:convTensor]; | ||
|
||
MLCPoolingDescriptor *poolDesc = | ||
[MLCPoolingDescriptor maxPoolingDescriptorWithKernelSizes:@[ @2, @2 ] | ||
strides:@[ @2, @2 ] | ||
paddingPolicy:MLCPaddingPolicyValid | ||
paddingSizes:nil]; | ||
MLCLayer *pool = [MLCPoolingLayer layerWithDescriptor:poolDesc]; | ||
|
||
MLCTensor *poolTensor = [graph nodeWithLayer:pool source:reluTensor]; | ||
|
||
return poolTensor; | ||
} | ||
|
||
- (MLCTensor *)addDenseLayer:(NSUInteger)index | ||
outputChannels:(NSUInteger)outputChannels | ||
source:(MLCTensor *)source | ||
graph:(MLCGraph *)graph | ||
{ | ||
// Find the weights for this conv layer in our dictionary of parameters. | ||
NSString *biasKey = [NSString stringWithFormat:@"drawing_dense%lu_bias", (unsigned long)index]; | ||
NSString *weightKey = | ||
[NSString stringWithFormat:@"drawing_dense%lu_weight", (unsigned long)index]; | ||
MLCTensor *bias = self.weights[biasKey]; | ||
MLCTensor *weights = self.weights[weightKey]; | ||
|
||
// Configure the convolution descriptor. | ||
NSUInteger inputChannels = | ||
weights.descriptor.shape[TCMLComputeTensorSizeChannels].unsignedIntegerValue / outputChannels; | ||
MLCConvolutionDescriptor *dense_desc = | ||
[MLCConvolutionDescriptor descriptorWithKernelSizes:@[ @1, @1 ] | ||
inputFeatureChannelCount:inputChannels | ||
outputFeatureChannelCount:outputChannels | ||
strides:@[ @1, @1 ] | ||
paddingPolicy:MLCPaddingPolicySame | ||
paddingSizes:nil]; | ||
|
||
MLCFullyConnectedLayer *dense = [MLCFullyConnectedLayer layerWithWeights:weights | ||
biases:bias | ||
descriptor:dense_desc]; | ||
MLCTensor *denseTensor = [graph nodeWithLayer:dense source:source]; | ||
return denseTensor; | ||
} | ||
@end | ||
|
||
@implementation MLCGraph (TCMLComputeDrawingClassifier) | ||
|
||
+ (instancetype)tc_graphForDrawingClassifierDescriptor: | ||
(TCMLComputeDrawingClassifierDescriptor *)descriptor | ||
batchSize:(NSUInteger)batchSize | ||
{ | ||
if (![descriptor isComplete]) return nil; | ||
|
||
MLCGraph *graph = [[self alloc] init]; | ||
|
||
NSUInteger channelCounts[] = {16, 32, 64}; | ||
MLCTensor *tensor = descriptor.inputTensor; | ||
for (NSUInteger i = 0; i < 3; ++i) { | ||
tensor = [descriptor addConvLayer:i outputChannels:channelCounts[i] source:tensor graph:graph]; | ||
} | ||
MLCReshapeLayer *flatten_layer = | ||
[MLCReshapeLayer layerWithShape:@[ @(batchSize), @(576), @(1), @(1) ]]; | ||
tensor = [graph nodeWithLayer:flatten_layer source:tensor]; | ||
tensor = [descriptor addDenseLayer:0 outputChannels:128 source:tensor graph:graph]; | ||
MLCLayer *relu1 = [MLCActivationLayer | ||
layerWithDescriptor:[MLCActivationDescriptor descriptorWithType:MLCActivationTypeReLU | ||
a:0.0f]]; | ||
MLCTensor *reluTensor = [graph nodeWithLayer:relu1 source:tensor]; | ||
descriptor.outputTensor = [descriptor addDenseLayer:1 | ||
outputChannels:descriptor.outputChannels | ||
source:reluTensor | ||
graph:graph]; | ||
return graph; | ||
} | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/* Copyright © 2020 Apple Inc. All rights reserved. | ||
* | ||
* Use of this source code is governed by a BSD-3-clause license that can | ||
* be found in the LICENSE.txt file or at | ||
* https://opensource.org/licenses/BSD-3-Clause | ||
*/ | ||
|
||
#pragma once | ||
|
||
#import <MLCompute/MLCompute.h> | ||
|
||
#include <ml/neural_net/mlc_layer_weights.hpp> | ||
#include <ml/neural_net/model_backend.hpp> | ||
|
||
namespace turi { | ||
namespace neural_net { | ||
|
||
class API_AVAILABLE(macos(10.16)) mlc_drawing_classifier_backend : public model_backend { | ||
public: | ||
mlc_drawing_classifier_backend(MLCDevice *device, const float_array_map &weights, | ||
size_t batch_size, size_t num_classes); | ||
|
||
// model_backend interface | ||
float_array_map export_weights() const override; | ||
void set_learning_rate(float lr) override; | ||
float_array_map train(const float_array_map &inputs) override; | ||
float_array_map predict(const turi::neural_net::float_array_map &inputs) const override; | ||
|
||
private: | ||
MLCTrainingGraph *training_graph_ = nil; | ||
MLCInferenceGraph *inference_graph_ = nil; | ||
MLCTensor *input_ = nil; | ||
MLCTensor *weights_ = nil; | ||
MLCTensor *labels_ = nil; | ||
|
||
mlc_layer_weights layer_weights_; | ||
size_t num_classes_; | ||
}; | ||
|
||
} // namespace neural_net | ||
} // namespace turi |
Oops, something went wrong.