タイトルの通り、ディープラーニングで醤油顔とソース顔を判定するiOSアプリを作ってみました。

事前にTensorFlowをインストールし、下記サイトを参考にしてiOSアプリでTensorFlowが使える状態にしておきます。
https://deepage.net/tensorflow/2017/02/22/tensorflow-ios.html

学習データについては、芸能人の画像を利用しました。
ネットで検索して出てきた画像から、顔の部分を正方形にトリミングして使っています。

学習データをもとに、TensorFlowのモデルを作っていきます。
この部分のコードは、下記ブログを参考にさせていただきました。
https://qiita.com/kenmaz/items/4b60ea00b159b3e00100

普通にTensorFlowで学習を行って作成されたモデルファイルはiOSアプリで取り扱うことができないので、.pbファイルに変換する必要があります。
この処理は下記ブログが参考になりました。
https://qiita.com/keonheon/items/82f4731afb4c99a09791

アプリ側は下記のサンプルプロジェクトを元に作っていきます。
tensorflow/sorce/tensorflow/tensorflow/contrib/ios_examples/camera

UIを作った後、判定の部分は setPredictionValues のあたりのコードを下記のように修正しました。

- (void)setPredictionValues:(NSDictionary *)newValues {
    const float decayValue = 0.75f;
    const float updateValue = 0.25f;
    const float minimumThreshold = 0.01f;

    NSMutableDictionary *decayedPredictionValues =
    [[NSMutableDictionary alloc] init];
    for (NSString *label in oldPredictionValues) {
        NSNumber *oldPredictionValueObject =
        [oldPredictionValues objectForKey:label];
        const float oldPredictionValue = [oldPredictionValueObject floatValue];
        const float decayedPredictionValue = (oldPredictionValue * decayValue);
        if (decayedPredictionValue > minimumThreshold) {
            NSNumber *decayedPredictionValueObject =
            [NSNumber numberWithFloat:decayedPredictionValue];
            [decayedPredictionValues setObject:decayedPredictionValueObject
                                        forKey:label];
        }
    }
    oldPredictionValues = decayedPredictionValues;

    for (NSString *label in newValues) {
        NSNumber *newPredictionValueObject = [newValues objectForKey:label];
        NSNumber *oldPredictionValueObject =
        [oldPredictionValues objectForKey:label];
        if (!oldPredictionValueObject) {
            oldPredictionValueObject = [NSNumber numberWithFloat:0.0f];
        }
        const float newPredictionValue = [newPredictionValueObject floatValue];
        const float oldPredictionValue = [oldPredictionValueObject floatValue];
        const float updatedPredictionValue =
        (oldPredictionValue + (newPredictionValue * updateValue));
        NSNumber *updatedPredictionValueObject =
        [NSNumber numberWithFloat:updatedPredictionValue];
        [oldPredictionValues setObject:updatedPredictionValueObject forKey:label];
    }
    NSArray *candidateLabels = [NSMutableArray array];
    for (NSString *label in oldPredictionValues) {
        NSNumber *oldPredictionValueObject =
        [oldPredictionValues objectForKey:label];
            NSDictionary *entry = @{
                                    @"label" : label,
                                    @"value" : oldPredictionValueObject
                                    };
            candidateLabels = [candidateLabels arrayByAddingObject:entry];
    }
    NSSortDescriptor *sort =
    [NSSortDescriptor sortDescriptorWithKey:@"value" ascending:NO];
    NSArray *sortedLabels = [candidateLabels
                             sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];
    [self setFaceBar: sortedLabels];
}

- (void)setFaceBar:(NSArray *)sortedLabels {
    if(!duringBarAnimation && sortedLabels.count > 0) {
        NSDictionary *entry = sortedLabels[0];
        NSString *label = [entry objectForKey:@"label"];
        NSNumber *valueObject = [entry objectForKey:@"value"];
        const float value = [valueObject floatValue];

        float syoyuValue = value;
        if([label isEqualToString:@"ソースがお"]) {
            syoyuValue = 1 - value;
        }

        duringBarAnimation = true;
        [UIView animateWithDuration:0.2f delay:0.0f options:UIViewAnimationOptionCurveEaseInOut animations:^ {
            self.syoyuBarWidth.constant = displayWidth * syoyuValue;
        } completion:^(BOOL finished) {
            duringBarAnimation = false;
        }];
    }
}

結果としては、学習データが足りないため精度はイマイチですが、試作アプリとしてはなかなか面白いものができたのでないかなと思います。