iOS
自然言語処理
機械学習
Swift
CoreM

[iOS 12]Natural Languageフレームワークのメモ

iOS 12で追加されたNatural Languageフレームワークのスニペットとかを置いていきます。自分で動作確認したものだけ。何か試すたびに追記していく予定。

名前の検出

NLTaggerpersonalName(人の名前), placeName(場所の名前), organizationName(組織の名前)をタグ付けし、抽出する。

func extractNames(from sentence: String) -> [String] {
    let tagger = NLTagger(tagSchemes: [.nameType])
    tagger.string = str
    let range = str.startIndex ..< str.endIndex

    var names = [String]()
    let nameTags: [NLTag] = [.personalName, .placeName, .organizationName]
    tagger.enumerateTags(in: range, unit: .word, scheme: .nameType) { (tag: NLTag?, tokenRange: Range<String.Index>) -> Bool in
        if let tag = tag, nameTags.contains(tag) {
            let name: Substring = str[tokenRange]
            names.append(String(name))
        }
        return true
    }
    return names
}

ポイント:

  • NLTaggerenumrateTagsメソッドに、NLTagSchemeとして.nameTypeを指定
  • それ以外の単語としてタグ付けされたものも結果に入ってくるので、NLTagの型を見てフィルタリングする

結果:

private let str = "Tim Cook welcomes developers from 77 different countries to WWDC 2018."

["Tim", "Cook", "WWDC"]

ちなみに"iOS 12 is designed to make your iPhone and iPad experience even faster, more responsive, and more delightful."を入力したときは、何も名前としてはタグ付けされなかった。"iOS", "iPhone", "iPad"といった固有名詞もタグとしては.otherWordになっていた。

カスタム言語モデルの使用

Create MLで学習させたCore MLのカスタムモデルを使ってテキストを分類/ラベリングする。主要クラスとしてはNLModel

カスタムモデルファイル名をMyTextClassifier.mlmodelとすると、

func predictLabel(for sentence: String) -> String {
    let mlModel = MyTextClassifier().model
    let nlModel = try! NLModel(mlModel: mlModel)

    guard let label = nlModel.predictedLabel(for: sentence) else { fatalError() }

    return label
}

結果:

試したのはネガティブ/ポジティブ判定モデル。

let label = predictLabel(for: "I'm happy.")
print(label)

pos

let label = predictLabel(for: "I'm sad.")
print(label)

neg