FC2ブログ

頭と尻尾はくれてやる!

パソコンおやじのiPhoneアプリ・サイト作成・運営日記


学習後パラメータをファイルからMPSで読み込む(CNNの場合)

Kerasの学習後パラメータを保存する(CNNの場合)

↑この続き。
この方法で出力した係数のファイルをmacOSアプリのMetal Performance Shadersで使いたい。
なお、今回の話は係数ファイルがすでにできてしまっているのでTensorFlowもKerasも関係ない。

APPLEのサンプルコードだとSwiftのみ(やめてーっ!!)の
MPSCNNHelloWorld: Simple Digit Detection Convolution Neural Networks (CNN)
というサンプルコードがある。
ダウンロードするページを見てみると、、、

サンプルコードMPSCNNHelloWorldのダウンロードページスクショ

↑全然メンテされてない、、、😅
ダウンロードしてもエラーでてビルドできないんだが。
Update to recommended settings ってのが出るのでそれをしてやるとできるのかもしれないけど、知らない、Swiftだし(なげやり)。

サンプルコードだとバンドルされた係数ファイルを読み込んでるので、これを別なフォルダに置いてるファイルから読み込むようにする。

サンプルコードのSlimMPSCNN.swiftというNNの層を作成する補助クラスみたいなのをObjective-Cで書き換えたのがこんな感じ↓
{
@implementation SlimMPSCNNConvolution

- (instancetype)initWithKernelWidth:(NSUInteger)kernelWidth
                       kernelHeight:(NSUInteger)kernelHeight
               inputFeatureChannels:(NSUInteger)inputFeatureChannels
              outputFeatureChannels:(NSUInteger)outputFeatureChannels
                       neuronFilter:(MPSCNNNeuron *)neuronFilter
                             device:(id<MTLDevice>)device
             kernelParamsBinaryName:(NSString *)kernelParamsBinaryName
{

    NSUInteger nofWeight = inputFeatureChannels*kernelHeight*kernelWidth*outputFeatureChannels;
    NSUInteger nofBias = outputFeatureChannels;
    float *weightP = calloc(nofWeight, sizeof(float));
    float *biasP = calloc(nofBias, sizeof(float));

    //外部ファイルから得る
    //(略)
    NSData *wData = [[NSData alloc] initWithContentsOfFile:filePath_w];
    NSData *bData = [[NSData alloc] initWithContentsOfFile:filePath_b];

    [wData getBytes:weightP length:nofWeight*sizeof(float)];
    [bData getBytes:biasP length:nofBias*sizeof(float)];

    MPSCNNConvolutionDescriptor *convDesc = [MPSCNNConvolutionDescriptor
                                             cnnConvolutionDescriptorWithKernelWidth:kernelWidth
                                             kernelHeight:kernelHeight
                                             inputFeatureChannels:inputFeatureChannels
                                             outputFeatureChannels:outputFeatureChannels ];
    convDesc.strideInPixelsX = 1;
    convDesc.strideInPixelsY = 1;
    convDesc.groups = 1;

    if (@available(macOS 10.13.4, *)) {
        MPSNNNeuronDescriptor *fusedNeuronDescriptor =[MPSNNNeuronDescriptor new];
        fusedNeuronDescriptor.neuronType = MPSCNNNeuronTypeReLU;
        fusedNeuronDescriptor.a = 0.0;
        //    convDesc.neuron = neuronFilter;//deprecated!
        convDesc.fusedNeuronDescriptor = fusedNeuronDescriptor;

    } else {
        // 古いのはダメ
    }

    NSInvocation *invocation;
    NSMethodSignature *signature;
    SEL argSelector =  @selector(initWithDevice:convolutionDescriptor:kernelWeights:biasTerms:flags:);
    
    MPSCNNConvolution *result = [MPSCNNConvolution alloc];
    
    signature = [self methodSignatureForSelector:argSelector];
    invocation = [NSInvocation invocationWithMethodSignature:signature];
    [invocation setTarget:result];
    [invocation setSelector:argSelector];

    NSUInteger n = 0;
    
    [invocation setArgument:&device atIndex:2];
    [invocation setArgument:&convDesc atIndex:3];
    [invocation setArgument:&weightP atIndex:4];
    [invocation setArgument:&biasP atIndex:5];
    [invocation setArgument:&n atIndex:6];
    [invocation invoke];
    [invocation getReturnValue:(void*)&result];

    self = (SlimMPSCNNConvolution *)result;
    
    self.destinationFeatureChannelOffset = 0;

    free(weightP);
    free(biasP);

    return self;
}
↑CNNの方。deprecatedを避けるためにいろいろと記述して長くなってる。もはや説明できないくらいの呪文である。

↓全結合層の場合はすでにこちらに書いてた。
KerasとMPSで同じ計算をする(2)

<< macOSでNSPopUpButtonとたわむれる  TopPage  Storyboardで部品を選ぶ方法 >>

コメント


管理者にだけ表示を許可する
 

トラックバック

トラックバックURL
http://ringsbell.blog117.fc2.com/tb.php/1213-7ce3b226




Copyright ©頭と尻尾はくれてやる!. Powered by FC2 Blog. Template by eriraha.

FC2Ad